+ def changed_files(self, tree, pathlimits = []):
+ """Return the set of files in the worktree that have changed with
+ respect to C{tree}. The listing is optionally restricted to
+ those files that match any of the path limiters given.
+
+ The path limiters are relative to the current working
+ directory; the returned file names are relative to the
+ repository root."""
+ assert isinstance(tree, Tree)
+ return set(self.run_in_cwd(
+ ['git', 'diff-index', tree.sha1, '--name-only', '-z', '--']
+ + list(pathlimits)).raw_output().split('\0')[:-1])
+ def update_index(self, paths):
+ """Update the index with files from the worktree. C{paths} is an
+ iterable of paths relative to the root of the repository."""
+ cmd = ['git', 'update-index', '--remove']
+ self.run(cmd + ['-z', '--stdin']
+ ).input_nulterm(paths).discard_output()
+ def worktree_clean(self):
+ """Check whether the worktree is clean relative to index."""
+ try:
+ self.run(['git', 'update-index', '--refresh']).discard_output()
+ except run.RunException:
+ return False
+ else:
+ return True
+
+class Branch(object):
+ """Represents a Git branch."""
+ def __init__(self, repository, name):
+ self.__repository = repository
+ self.__name = name
+ try:
+ self.head
+ except KeyError:
+ raise BranchException('%s: no such branch' % name)
+
+ name = property(lambda self: self.__name)
+ repository = property(lambda self: self.__repository)
+
+ def __ref(self):
+ return 'refs/heads/%s' % self.__name
+ @property
+ def head(self):
+ return self.__repository.refs.get(self.__ref())
+ def set_head(self, commit, msg):
+ self.__repository.refs.set(self.__ref(), commit, msg)
+
+ def set_parent_remote(self, name):
+ value = config.set('branch.%s.remote' % self.__name, name)
+ def set_parent_branch(self, name):
+ if config.get('branch.%s.remote' % self.__name):
+ # Never set merge if remote is not set to avoid
+ # possibly-erroneous lookups into 'origin'
+ config.set('branch.%s.merge' % self.__name, name)
+
+ @classmethod
+ def create(cls, repository, name, create_at = None):
+ """Create a new Git branch and return the corresponding
+ L{Branch} object."""
+ try:
+ branch = cls(repository, name)
+ except BranchException:
+ branch = None
+ if branch:
+ raise BranchException('%s: branch already exists' % name)
+
+ cmd = ['git', 'branch']
+ if create_at:
+ cmd.append(create_at.sha1)
+ repository.run(['git', 'branch', create_at.sha1]).discard_output()
+
+ return cls(repository, name)
+
+def diffstat(diff):
+ """Return the diffstat of the supplied diff."""
+ return run.Run('git', 'apply', '--stat', '--summary'
+ ).raw_input(diff).raw_output()