2 # script to show recent checkins in git
4 # Copyright (C) Andrew Tridgell <tridge@samba.org> 2001
5 # Copyright (C) Martin Pool <mbp@samba.org> 2003
6 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 from cStringIO import StringIO
24 from dulwich.objects import Tree
25 from dulwich.patch import write_tree_diff
26 from dulwich.repo import Repo
30 """A version control branch."""
32 def log(self, limit=None):
33 raise NotImplementedError(self.log)
35 def diff(self, revision):
36 raise NotImplementedError(self.diff)
38 def changes_summary(self, revision):
39 raise NotImplementedError(self.changes_summary)
42 class Revision(object):
44 def __init__(self, revision, date, committer, author, message):
45 self.revision = revision
48 self.committer = committer
49 self.message = message
52 class GitBranch(Branch):
54 def __init__(self, path, branch="master"):
55 self.repo = Repo(path)
56 self.store = self.repo.object_store
59 def _changes_for(self, commit):
60 if len(commit.parents) == 0:
61 parent_tree = Tree().id
63 parent_tree = self.store[commit.parents[0]].tree
64 return self.store.tree_changes(parent_tree, commit.tree)
66 def _revision_from_commit(self, commit):
67 return Revision(commit.id, commit.commit_time,
68 committer=commit.committer, author=commit.author,
69 message=commit.message)
71 def log(self, from_rev=None, exclude_revs=None, limit=None):
72 if exclude_revs is None:
76 commit = self.repo["refs/heads/%s" % self.branch]
81 pending_commits = [from_rev]
82 while pending_commits != []:
83 commit_id = pending_commits.pop(0)
84 commit = self.repo[commit_id]
85 yield self._revision_from_commit(commit)
87 if len(done) >= limit:
89 exclude_revs.add(commit.id)
90 # FIXME: Add sorted by commit_time
91 for p in commit.parents:
94 pending_commits.append(p)
97 def changes_summary(self, revision):
98 commit = self.repo[revision]
102 for ((oldpath, newpath), (oldmode, newmode), (oldsha, newsha)) in self._changes_for(commit):
105 elif newpath is None:
108 modified.add(newpath)
109 return (added, modified, removed)
111 def diff(self, revision):
112 commit = self.repo[revision]
114 if len(commit.parents) == 0:
115 parent_tree = Tree().id
117 parent_tree = self.store[commit.parents[0]].tree
118 write_tree_diff(f, self.store, parent_tree, commit.tree)
119 return (self._revision_from_commit(commit), f.getvalue())