summaryrefslogtreecommitdiff
path: root/lib/git/repo.py
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-10-15 14:56:20 +0200
committerSebastian Thiel <byronimo@gmail.com>2009-10-15 15:14:04 +0200
commit9f51eeb2f9a1efe22e45f7a1f7b963100f2f8e6b (patch)
tree75a37c9d1ab697780e4d657119d0f98227d33090 /lib/git/repo.py
parent9ce1193c851e98293a237ad3d2d87725c501e89f (diff)
downloadgitpython-9f51eeb2f9a1efe22e45f7a1f7b963100f2f8e6b.tar.gz
repo: removed commits_between but added a note about how this can be achieved using the iter_commits method; reorganized methods within the type as a start for more interface changes
Diffstat (limited to 'lib/git/repo.py')
-rw-r--r--lib/git/repo.py424
1 files changed, 206 insertions, 218 deletions
diff --git a/lib/git/repo.py b/lib/git/repo.py
index 9b947d60..9ac6ce0c 100644
--- a/lib/git/repo.py
+++ b/lib/git/repo.py
@@ -116,130 +116,6 @@ class Repo(object):
"""
return Tag.list_items(self)
- def blame(self, rev, file):
- """
- The blame information for the given file at the given revision.
-
- ``rev``
- revision specifier, see git-rev-parse for viable options.
-
- Returns
- list: [git.Commit, list: [<line>]]
- A list of tuples associating a Commit object with a list of lines that
- changed within the given commit. The Commit objects will be given in order
- of appearance.
- """
- data = self.git.blame(ref, '--', file, p=True)
- commits = {}
- blames = []
- info = None
-
- for line in data.splitlines(False):
- parts = self.re_whitespace.split(line, 1)
- firstpart = parts[0]
- if self.re_hexsha_only.search(firstpart):
- # handles
- # 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7 - indicates blame-data start
- # 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2
- digits = parts[-1].split(" ")
- if len(digits) == 3:
- info = {'id': firstpart}
- blames.append([None, []])
- # END blame data initialization
- else:
- m = self.re_author_committer_start.search(firstpart)
- if m:
- # handles:
- # author Tom Preston-Werner
- # author-mail <tom@mojombo.com>
- # author-time 1192271832
- # author-tz -0700
- # committer Tom Preston-Werner
- # committer-mail <tom@mojombo.com>
- # committer-time 1192271832
- # committer-tz -0700 - IGNORED BY US
- role = m.group(0)
- if firstpart.endswith('-mail'):
- info["%s_email" % role] = parts[-1]
- elif firstpart.endswith('-time'):
- info["%s_date" % role] = int(parts[-1])
- elif role == firstpart:
- info[role] = parts[-1]
- # END distinguish mail,time,name
- else:
- # handle
- # filename lib/grit.rb
- # summary add Blob
- # <and rest>
- if firstpart.startswith('filename'):
- info['filename'] = parts[-1]
- elif firstpart.startswith('summary'):
- info['summary'] = parts[-1]
- elif firstpart == '':
- if info:
- sha = info['id']
- c = commits.get(sha)
- if c is None:
- c = Commit( self, id=sha,
- author=Actor._from_string(info['author'] + ' ' + info['author_email']),
- authored_date=info['author_date'],
- committer=Actor._from_string(info['committer'] + ' ' + info['committer_email']),
- committed_date=info['committer_date'],
- message=info['summary'])
- commits[sha] = c
- # END if commit objects needs initial creation
- m = self.re_tab_full_line.search(line)
- text, = m.groups()
- blames[-1][0] = c
- blames[-1][1].append( text )
- info = None
- # END if we collected commit info
- # END distinguish filename,summary,rest
- # END distinguish author|committer vs filename,summary,rest
- # END distinguish hexsha vs other information
- return blames
-
- def iter_commits(self, rev=None, paths='', **kwargs):
- """
- A list of Commit objects representing the history of a given ref/commit
-
- ``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.
-
- ``kwargs``
- Arguments to be passed to git-rev-parse - common ones are
- max_count and skip
-
- Returns
- ``git.Commit[]``
- """
- if rev is None:
- rev = self.active_branch
-
- return Commit.list_items(self, rev, paths, **kwargs)
-
- def commits_between(self, frm, to, *args, **kwargs):
- """
- The Commits objects that are reachable via ``to`` but not via ``frm``
- Commits are returned in chronological order.
-
- ``from``
- is the Ref/Commit name of the younger item
-
- ``to``
- is the Ref/Commit name of the older item
-
- Returns
- ``git.Commit[]``
- """
- return reversed(Commit.list_items(self, "%s..%s" % (frm, to)))
-
-
def commit(self, rev=None):
"""
The Commit object for the specified revision
@@ -259,7 +135,6 @@ class Repo(object):
c = Commit(self, rev)
return c
-
def tree(self, ref=None):
"""
The Tree object for the given treeish reference
@@ -302,6 +177,33 @@ class Repo(object):
# the root has an empty relative path and the default mode
return Tree(self, ref, 0, '')
+ def iter_commits(self, rev=None, paths='', **kwargs):
+ """
+ A list of Commit objects representing the history of a given ref/commit
+
+ ``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.
+
+ ``kwargs``
+ Arguments to be passed to git-rev-parse - common ones are
+ max_count and skip
+
+ Note: to receive only commits between two named revisions, use the
+ "revA..revB" revision specifier
+
+ Returns
+ ``git.Commit[]``
+ """
+ if rev is None:
+ rev = self.active_branch
+
+ return Commit.iter_items(self, rev, paths, **kwargs)
+
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
@@ -315,6 +217,102 @@ class Repo(object):
diff_refs = list(set(other_repo_refs) - set(repo_refs))
return map(lambda ref: Commit(other_repo, ref ), diff_refs)
+
+ def _get_daemon_export(self):
+ filename = os.path.join(self.path, self.DAEMON_EXPORT_FILE)
+ return os.path.exists(filename)
+
+ def _set_daemon_export(self, value):
+ filename = os.path.join(self.path, self.DAEMON_EXPORT_FILE)
+ fileexists = os.path.exists(filename)
+ if value and not fileexists:
+ touch(filename)
+ elif not value and fileexists:
+ os.unlink(filename)
+
+ daemon_export = property(_get_daemon_export, _set_daemon_export,
+ doc="If True, git-daemon may export this repository")
+ del _get_daemon_export
+ del _set_daemon_export
+
+ def _get_alternates(self):
+ """
+ The list of alternates for this repo from which objects can be retrieved
+
+ Returns
+ list of strings being pathnames of alternates
+ """
+ alternates_path = os.path.join(self.path, 'objects', 'info', 'alternates')
+
+ if os.path.exists(alternates_path):
+ try:
+ f = open(alternates_path)
+ alts = f.read()
+ finally:
+ f.close()
+ return alts.strip().splitlines()
+ else:
+ return []
+
+ def _set_alternates(self, alts):
+ """
+ Sets the alternates
+
+ ``alts``
+ is the array of string paths representing the alternates at which
+ git should look for objects, i.e. /home/user/repo/.git/objects
+
+ Raises
+ NoSuchPathError
+
+ Returns
+ None
+ """
+ for alt in alts:
+ if not os.path.exists(alt):
+ raise NoSuchPathError("Could not set alternates. Alternate path %s must exist" % alt)
+
+ if not alts:
+ os.remove(os.path.join(self.path, 'objects', 'info', 'alternates'))
+ else:
+ try:
+ f = open(os.path.join(self.path, 'objects', 'info', 'alternates'), 'w')
+ f.write("\n".join(alts))
+ finally:
+ f.close()
+
+ alternates = property(_get_alternates, _set_alternates, doc="Retrieve a list of alternates paths or set a list paths to be used as alternates")
+
+ @property
+ def is_dirty(self):
+ """
+ Return the status of the index.
+
+ Returns
+ ``True``, if the index has any uncommitted changes,
+ otherwise ``False``
+
+ NOTE
+ Working tree changes that have not been staged will not be detected !
+ """
+ if self.bare:
+ # Bare repositories with no associated working directory are
+ # always consired to be clean.
+ return False
+
+ return len(self.git.diff('HEAD', '--').strip()) > 0
+
+ @property
+ def active_branch(self):
+ """
+ The name of the currently active branch.
+
+ Returns
+ Head to the active branch
+ """
+ return Head( self, self.git.symbolic_ref('HEAD').strip() )
+
+
def diff(self, a, b, *paths):
"""
The diff from commit ``a`` to commit ``b``, optionally restricted to the given file(s)
@@ -341,6 +339,89 @@ class Repo(object):
``git.Diff[]``
"""
return Commit.diff(self, commit)
+
+ def blame(self, rev, file):
+ """
+ The blame information for the given file at the given revision.
+
+ ``rev``
+ revision specifier, see git-rev-parse for viable options.
+
+ Returns
+ list: [git.Commit, list: [<line>]]
+ A list of tuples associating a Commit object with a list of lines that
+ changed within the given commit. The Commit objects will be given in order
+ of appearance.
+ """
+ data = self.git.blame(rev, '--', file, p=True)
+ commits = {}
+ blames = []
+ info = None
+
+ for line in data.splitlines(False):
+ parts = self.re_whitespace.split(line, 1)
+ firstpart = parts[0]
+ if self.re_hexsha_only.search(firstpart):
+ # handles
+ # 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7 - indicates blame-data start
+ # 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2
+ digits = parts[-1].split(" ")
+ if len(digits) == 3:
+ info = {'id': firstpart}
+ blames.append([None, []])
+ # END blame data initialization
+ else:
+ m = self.re_author_committer_start.search(firstpart)
+ if m:
+ # handles:
+ # author Tom Preston-Werner
+ # author-mail <tom@mojombo.com>
+ # author-time 1192271832
+ # author-tz -0700
+ # committer Tom Preston-Werner
+ # committer-mail <tom@mojombo.com>
+ # committer-time 1192271832
+ # committer-tz -0700 - IGNORED BY US
+ role = m.group(0)
+ if firstpart.endswith('-mail'):
+ info["%s_email" % role] = parts[-1]
+ elif firstpart.endswith('-time'):
+ info["%s_date" % role] = int(parts[-1])
+ elif role == firstpart:
+ info[role] = parts[-1]
+ # END distinguish mail,time,name
+ else:
+ # handle
+ # filename lib/grit.rb
+ # summary add Blob
+ # <and rest>
+ if firstpart.startswith('filename'):
+ info['filename'] = parts[-1]
+ elif firstpart.startswith('summary'):
+ info['summary'] = parts[-1]
+ elif firstpart == '':
+ if info:
+ sha = info['id']
+ c = commits.get(sha)
+ if c is None:
+ c = Commit( self, id=sha,
+ author=Actor._from_string(info['author'] + ' ' + info['author_email']),
+ authored_date=info['author_date'],
+ committer=Actor._from_string(info['committer'] + ' ' + info['committer_email']),
+ committed_date=info['committer_date'],
+ message=info['summary'])
+ commits[sha] = c
+ # END if commit objects needs initial creation
+ m = self.re_tab_full_line.search(line)
+ text, = m.groups()
+ blames[-1][0] = c
+ blames[-1][1].append( text )
+ info = None
+ # END if we collected commit info
+ # END distinguish filename,summary,rest
+ # END distinguish author|committer vs filename,summary,rest
+ # END distinguish hexsha vs other information
+ return blames
@classmethod
def init_bare(self, path, mkdir=True, **kwargs):
@@ -454,99 +535,6 @@ class Repo(object):
gf.close()
return sio.getvalue()
- def _get_daemon_export(self):
- filename = os.path.join(self.path, self.DAEMON_EXPORT_FILE)
- return os.path.exists(filename)
-
- def _set_daemon_export(self, value):
- filename = os.path.join(self.path, self.DAEMON_EXPORT_FILE)
- fileexists = os.path.exists(filename)
- if value and not fileexists:
- touch(filename)
- elif not value and fileexists:
- os.unlink(filename)
-
- daemon_export = property(_get_daemon_export, _set_daemon_export,
- doc="If True, git-daemon may export this repository")
- del _get_daemon_export
- del _set_daemon_export
-
- def _get_alternates(self):
- """
- The list of alternates for this repo from which objects can be retrieved
-
- Returns
- list of strings being pathnames of alternates
- """
- alternates_path = os.path.join(self.path, 'objects', 'info', 'alternates')
-
- if os.path.exists(alternates_path):
- try:
- f = open(alternates_path)
- alts = f.read()
- finally:
- f.close()
- return alts.strip().splitlines()
- else:
- return []
-
- def _set_alternates(self, alts):
- """
- Sets the alternates
-
- ``alts``
- is the array of string paths representing the alternates at which
- git should look for objects, i.e. /home/user/repo/.git/objects
-
- Raises
- NoSuchPathError
-
- Returns
- None
- """
- for alt in alts:
- if not os.path.exists(alt):
- raise NoSuchPathError("Could not set alternates. Alternate path %s must exist" % alt)
-
- if not alts:
- os.remove(os.path.join(self.path, 'objects', 'info', 'alternates'))
- else:
- try:
- f = open(os.path.join(self.path, 'objects', 'info', 'alternates'), 'w')
- f.write("\n".join(alts))
- finally:
- f.close()
-
- alternates = property(_get_alternates, _set_alternates, doc="Retrieve a list of alternates paths or set a list paths to be used as alternates")
-
- @property
- def is_dirty(self):
- """
- Return the status of the index.
-
- Returns
- ``True``, if the index has any uncommitted changes,
- otherwise ``False``
-
- NOTE
- Working tree changes that have not been staged will not be detected !
- """
- if self.bare:
- # Bare repositories with no associated working directory are
- # always consired to be clean.
- return False
-
- return len(self.git.diff('HEAD', '--').strip()) > 0
-
- @property
- def active_branch(self):
- """
- The name of the currently active branch.
-
- Returns
- Head to the active branch
- """
- return Head( self, self.git.symbolic_ref('HEAD').strip() )
def __repr__(self):
return '<git.Repo "%s">' % self.path