summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-10-15 14:11:34 +0200
committerSebastian Thiel <byronimo@gmail.com>2009-10-15 14:46:05 +0200
commit9ce1193c851e98293a237ad3d2d87725c501e89f (patch)
treebdac0e4a917ca3c1b21eb580402a2854fcf33692 /lib/git
parent2da2b90e6930023ec5739ae0b714bbdb30874583 (diff)
downloadgitpython-9ce1193c851e98293a237ad3d2d87725c501e89f.tar.gz
Added Commit.iter_parents to iterate all parents
Renamed Commit.commits to iter_commits repo: assured proper use of the terms revision ( rev ) and reference ( ref )
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/objects/commit.py42
-rw-r--r--lib/git/refs.py6
-rw-r--r--lib/git/repo.py120
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):
"""