# HG changeset patch # User Scott Chacon <schacon@gmail.com> # Date 1240703831 25200 # Sat Apr 25 16:57:11 2009 -0700 # Node ID 2548735d24efb0e678eee047b08a0605dc882318 # Parent 89992b6d2eef20ace7cc579267c547183c8b4b2a will now more or less correctly determine a changelist from a git commit diff --git a/dulwich/objects.py b/dulwich/objects.py --- a/dulwich/objects.py +++ b/dulwich/objects.py @@ -362,6 +362,9 @@ """Return a list of tuples describing the tree entries""" return [(mode, name, hexsha) for (name, (mode, hexsha)) in self._entries.iteritems()] + def entry(self, name): + return self._entries[name] + def iteritems(self): for name in sorted(self._entries.keys()): yield name, self_entries[name][0], self._entries[name][1] @@ -501,18 +504,6 @@ self._text += "\n" # There must be a new line after the headers self._text += self._message - def getfile(self, f): - import random - dt = "file contents:" + str(random.randrange(1, 100)) - print dt - return dt - - def getmode(self, f): - return "" - - def getfiles(self): - return ['test'] - @property def tree(self): """Returns the tree that is the state of this commit""" diff --git a/dulwich/repo.py b/dulwich/repo.py --- a/dulwich/repo.py +++ b/dulwich/repo.py @@ -305,6 +305,56 @@ def get_blob(self, sha): return self._get_object(sha, Blob) + + # takes a commit object and a file path + # returns the contents of that file at that commit + # TODO : make this recursive - any file in a subdir wont be found here + def get_file(self, commit, f): + otree = self.tree(commit.tree) + parts = f.split('/') + for part in parts: + (mode, sha) = otree.entry(part) + obj = self.get_object(sha) + if isinstance (obj, Blob): + return (mode, sha, obj._text) + elif isinstance(obj, Tree): + otree = obj + + # takes a commit and returns an array of the files that were changed + # between that commit and it's parents + # TODO : optimize this, it's horrible + # TODO : if no parents, return all files + def get_files_changed(self, commit): + + def filenames(basetree, comptree, prefix): + changes = list() + csha = None + ctree = None + for (bmode, bname, bsha) in basetree.entries(): + bobj = self.get_object(bsha) + if comptree: + (cmode, csha) = comptree.entry(bname) + if csha != bsha: + if isinstance (bobj, Blob): + changes.append (prefix + bname) + elif isinstance(bobj, Tree): + if csha: + ctree = self.get_object(csha) + changes.extend (filenames (bobj, ctree, prefix + bname + '/')) + # TODO: handle removals? + return changes + + all_changes = list() + otree = self.tree(commit.tree) + if len(commit.parents) == 0: + all_changes = filenames(otree, None, '') + for parent in commit.parents: + pcommit = self.commit(parent) + ptree = self.tree(pcommit.tree) + all_changes.extend(filenames(otree, ptree, '')) + + return all_changes + def revision_history(self, head): """Returns a list of the commits reachable from head. diff --git a/git_handler.py b/git_handler.py --- a/git_handler.py +++ b/git_handler.py @@ -81,19 +81,18 @@ # import each of the commits, oldest first for commit in convert_list: - print "commit: %s" % sha self.import_git_commit(commit) # TODO : update Hg bookmarks (possibly named heads?) print bookmarks.parse(self.repo) def import_git_commit(self, commit): - print commit.parents - + print "importing: " + commit.id + # TODO : have to handle merge contexts at some point (two parent files, etc) def getfilectx(repo, memctx, f): - data = commit.getfile(f) - e = commit.getmode(f) + (e, sha, data) = self.git.get_file(commit, f) + e = '' # TODO : make this a real mode return context.memfilectx(f, data, 'l' in e, 'x' in e, None) p1 = "0" * 40 @@ -109,7 +108,9 @@ # TODO : map extra parents to the extras file pass - files = commit.getfiles() + files = self.git.get_files_changed(commit) + + print files # get a list of the changed, added, removed files extra = {}