diff options
Diffstat (limited to 'lib/git')
-rw-r--r-- | lib/git/objects/commit.py | 42 | ||||
-rw-r--r-- | lib/git/refs.py | 6 | ||||
-rw-r--r-- | lib/git/repo.py | 120 |
3 files changed, 89 insertions, 79 deletions
diff --git a/lib/git/objects/commit.py b/lib/git/objects/commit.py index 14839e12..ab8fdf26 100644 --- a/lib/git/objects/commit.py +++ b/lib/git/objects/commit.py @@ -100,17 +100,39 @@ class Commit(base.Object, Iterable): First line of the commit message. """ return self.message.split('\n', 1)[0] + + def iter_parents(self, paths='', **kwargs): + """ + Iterate _all_ parents of this commit. + + ``paths`` + Optional path or list of paths limiting the Commits to those that + contain at least one of the paths + + ``kwargs`` + All arguments allowed by git-rev-list + + Return: + Iterator yielding Commit objects which are parents of self + """ + # skip ourselves + skip = kwargs.get("skip", 1) + if skip == 0: # skip ourselves + skip = 1 + kwargs['skip'] = skip + + return self.iter_items( self.repo, self, paths, **kwargs ) @classmethod - def count(cls, repo, ref, paths=''): + def count(cls, repo, rev, paths=''): """ - Count the number of commits reachable from this ref + Count the number of commits reachable from this revision ``repo`` is the Repo - ``ref`` - is the ref from which to begin (SHA1 or name) + ``rev`` + revision specifier, see git-rev-parse for viable options ``paths`` is an optinal path or a list of paths restricting the return value @@ -119,18 +141,18 @@ class Commit(base.Object, Iterable): Returns int """ - return len(repo.git.rev_list(ref, '--', paths).strip().splitlines()) + return len(repo.git.rev_list(rev, '--', paths).strip().splitlines()) @classmethod - def iter_items(cls, repo, ref, paths='', **kwargs): + def iter_items(cls, repo, rev, paths='', **kwargs): """ Find all commits matching the given criteria. ``repo`` is the Repo - ``ref`` - is the ref from which to begin (SHA1, Head or name) + ``rev`` + revision specifier, see git-rev-parse for viable options ``paths`` is an optinal path or list of paths, if set only Commits that include the path @@ -149,7 +171,7 @@ class Commit(base.Object, Iterable): options.update(kwargs) # the test system might confront us with string values - - proc = repo.git.rev_list(ref, '--', paths, **options) + proc = repo.git.rev_list(rev, '--', paths, **options) return cls._iter_from_process_or_stream(repo, proc) @classmethod @@ -201,7 +223,7 @@ class Commit(base.Object, Iterable): # END while there are message lines message = '\n'.join(message_lines) - yield Commit(repo, id=id, parents=parents, tree=tree, author=author, authored_date=authored_date, + yield Commit(repo, id=id, parents=tuple(parents), tree=tree, author=author, authored_date=authored_date, committer=committer, committed_date=committed_date, message=message) # END for each line in stream diff --git a/lib/git/refs.py b/lib/git/refs.py index 3c9eb817..8ed578ef 100644 --- a/lib/git/refs.py +++ b/lib/git/refs.py @@ -10,7 +10,7 @@ from objects.base import Object from objects.utils import get_object_type_by_name from utils import LazyMixin, Iterable -class Ref(LazyMixin, Iterable): +class Reference(LazyMixin, Iterable): """ Represents a named reference to any object """ @@ -138,7 +138,7 @@ class Ref(LazyMixin, Iterable): # return cls(repo, full_path, obj) -class Head(Ref): +class Head(Reference): """ A Head is a named reference to a Commit. Every Head instance contains a name and a Commit object. @@ -181,7 +181,7 @@ class Head(Ref): -class TagRef(Ref): +class TagRef(Reference): """ Class representing a lightweight tag reference which either points to a commit or to a tag object. In the latter case additional information, like the signature diff --git a/lib/git/repo.py b/lib/git/repo.py index 40c71fd8..9b947d60 100644 --- a/lib/git/repo.py +++ b/lib/git/repo.py @@ -116,12 +116,12 @@ class Repo(object): """ return Tag.list_items(self) - def blame(self, ref, file): + def blame(self, rev, file): """ - The blame information for the given file at the given ref. + The blame information for the given file at the given revision. - ``ref`` - Ref object or Commit + ``rev`` + revision specifier, see git-rev-parse for viable options. Returns list: [git.Commit, list: [<line>]] @@ -199,37 +199,29 @@ class Repo(object): # END distinguish hexsha vs other information return blames - def commits(self, start=None, paths='', max_count=None, skip=0): + def iter_commits(self, rev=None, paths='', **kwargs): """ A list of Commit objects representing the history of a given ref/commit - ``start`` - is a Ref or Commit to start the commits from. If start is None, - the active branch will be used + ``rev`` + revision specifier, see git-rev-parse for viable options. + If None, the active branch will be used. ``paths`` is an optional path or a list of paths to limit the returned commits to Commits that do not contain that path or the paths will not be returned. - - ``max_count`` - is the maximum number of commits to return (default None) - - ``skip`` - is the number of commits to skip (default 0) which will effectively - move your commit-window by the given number. + + ``kwargs`` + Arguments to be passed to git-rev-parse - common ones are + max_count and skip Returns ``git.Commit[]`` """ - options = {'max_count': max_count, - 'skip': skip} - - if max_count is None: - options.pop('max_count') - if start is None: - start = self.active_branch + if rev is None: + rev = self.active_branch - return Commit.list_items(self, start, paths, **options) + return Commit.list_items(self, rev, paths, **kwargs) def commits_between(self, frm, to, *args, **kwargs): """ @@ -248,50 +240,31 @@ class Repo(object): return reversed(Commit.list_items(self, "%s..%s" % (frm, to))) - def commit(self, id=None, paths = ''): + def commit(self, rev=None): """ - The Commit object for the specified id + The Commit object for the specified revision - ``id`` - is the SHA1 identifier of the commit or a ref or a ref name - if None, it defaults to the active branch + ``rev`` + revision specifier, see git-rev-parse for viable options. - - ``paths`` - is an optional path or a list of paths, - if set the returned commit must contain the path or paths - Returns ``git.Commit`` """ - if id is None: - id = self.active_branch - options = {'max_count': 1} - - commits = Commit.list_items(self, id, paths, **options) - - if not commits: - raise ValueError, "Invalid identifier %s, or given path '%s' too restrictive" % ( id, path ) - return commits[0] - - def commit_deltas_from(self, other_repo, ref='master', other_ref='master'): - """ - Returns a list of commits that is in ``other_repo`` but not in self - - Returns - git.Commit[] - """ - repo_refs = self.git.rev_list(ref, '--').strip().splitlines() - other_repo_refs = other_repo.git.rev_list(other_ref, '--').strip().splitlines() + if rev is None: + rev = self.active_branch + + # NOTE: currently we are not checking wheter rev really points to a commit + # If not, the system will barf on access of the object, but we don't do that + # here to safe cycles + c = Commit(self, rev) + return c - diff_refs = list(set(other_repo_refs) - set(repo_refs)) - return map(lambda ref: Commit(other_repo, ref ), diff_refs) - def tree(self, treeish=None): + def tree(self, ref=None): """ The Tree object for the given treeish reference - ``treeish`` + ``ref`` is a Ref instance defaulting to the active_branch if None. Examples:: @@ -305,27 +278,42 @@ class Repo(object): A ref is requried here to assure you point to a commit or tag. Otherwise it is not garantueed that you point to the root-level tree. - If you need a non-root level tree, find it by iterating the root tree. - """ - if treeish is None: - treeish = self.active_branch - if not isinstance(treeish, Ref): - raise ValueError( "Treeish reference required, got %r" % treeish ) + If you need a non-root level tree, find it by iterating the root tree. Otherwise + it cannot know about its path relative to the repository root and subsequent + operations might have unexpected results. + """ + if ref is None: + ref = self.active_branch + if not isinstance(ref, Reference): + raise ValueError( "Reference required, got %r" % ref ) # As we are directly reading object information, we must make sure # we truly point to a tree object. We resolve the ref to a sha in all cases # to assure the returned tree can be compared properly. Except for # heads, ids should always be hexshas - hexsha, typename, size = self.git.get_object_header( treeish ) + hexsha, typename, size = self.git.get_object_header( ref ) if typename != "tree": - hexsha, typename, size = self.git.get_object_header( str(treeish)+'^{tree}' ) + # will raise if this is not a valid tree + hexsha, typename, size = self.git.get_object_header( str(ref)+'^{tree}' ) # END tree handling - treeish = hexsha + ref = hexsha # the root has an empty relative path and the default mode - return Tree(self, treeish, 0, '') + return Tree(self, ref, 0, '') + + def commit_deltas_from(self, other_repo, ref='master', other_ref='master'): + """ + Returns a list of commits that is in ``other_repo`` but not in self + Returns + git.Commit[] + """ + repo_refs = self.git.rev_list(ref, '--').strip().splitlines() + other_repo_refs = other_repo.git.rev_list(other_ref, '--').strip().splitlines() + + diff_refs = list(set(other_repo_refs) - set(repo_refs)) + return map(lambda ref: Commit(other_repo, ref ), diff_refs) def diff(self, a, b, *paths): """ |