Instead of spawning a separate diff-tree process for every pair of trees we want to diff. This speeds things up slightly: about 10% when uncommitting and rebasing 1470 linux-kernel patches (perftest.py rebase-newrebase-add-file-linux).
Signed-off-by: Karl Wiberg <[email protected]> --- INSTALL | 5 +++-- stgit/lib/git.py | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/INSTALL b/INSTALL index d728441..459b365 100644 --- a/INSTALL +++ b/INSTALL @@ -12,8 +12,9 @@ prefix option. Issues of note: -- StGit requires git version 1.5.6 or later. (Specifically, it needs a - git that includes commit a8128ed6: "git-cat-file: Add --batch option".) +- StGit requires git version 1.6.1 or later. (Specifically, it needs a + git that includes commit 140b378d: "Teach git diff-tree --stdin to + diff trees".) - To build and install the documentation, you need to have the asciidoc/xmlto toolchain. The default build target ("make all") diff --git a/stgit/lib/git.py b/stgit/lib/git.py index f5ea965..56287f6 100644 --- a/stgit/lib/git.py +++ b/stgit/lib/git.py @@ -555,6 +555,34 @@ class CatFileProcess(object): b += os.read(p.stdout.fileno(), 4096) return type, b[:-1] +class DiffTreeProcesses(object): + def __init__(self, repo): + self.__repo = repo + self.__procs = {} + atexit.register(self.__shutdown) + def __get_process(self, args): + args = tuple(args) + if not args in self.__procs: + self.__procs[args] = self.__repo.run( + ['git', 'diff-tree', '--stdin'] + list(args)).run_background() + return self.__procs[args] + def __shutdown(self): + for p in self.__procs.values(): + os.kill(p.pid(), signal.SIGTERM) + p.wait() + def diff_trees(self, args, sha1a, sha1b): + p = self.__get_process(args) + query = '%s %s\n' % (sha1a, sha1b) + end = 'EOF\n' # arbitrary string that's not a 40-digit hex number + p.stdin.write(query + end) + p.stdin.flush() + s = '' + while not (s.endswith('\n' + end) or s.endswith('\0' + end)): + s += os.read(p.stdout.fileno(), 4096) + assert s.startswith(query) + assert s.endswith(end) + return s[len(query):-len(end)] + class Repository(RunWithEnv): """Represents a git repository.""" def __init__(self, directory): @@ -567,6 +595,7 @@ class Repository(RunWithEnv): self.__default_worktree = None self.__default_iw = None self.__catfile = CatFileProcess(self) + self.__difftree = DiffTreeProcesses(self) env = property(lambda self: { 'GIT_DIR': self.__git_dir }) @classmethod def default(cls): @@ -693,8 +722,8 @@ class Repository(RunWithEnv): diff_opts = list(diff_opts) if binary and not '--binary' in diff_opts: diff_opts.append('--binary') - return self.run(['git', 'diff-tree', '-p'] + diff_opts - + [t1.sha1, t2.sha1]).raw_output() + return self.__difftree.diff_trees(['-p'] + diff_opts, + t1.sha1, t2.sha1) def diff_tree_files(self, t1, t2): """Given two L{Tree}s C{t1} and C{t2}, iterate over all files for which they differ. For each file, yield a tuple with the old @@ -704,8 +733,8 @@ class Repository(RunWithEnv): identical.""" assert isinstance(t1, Tree) assert isinstance(t2, Tree) - i = iter(self.run(['git', 'diff-tree', '-r', '-z'] + [t1.sha1, t2.sha1] - ).raw_output().split('\0')) + i = iter(self.__difftree.diff_trees( + ['-r', '-z'], t1.sha1, t2.sha1).split('\0')) try: while True: x = i.next() _______________________________________________ stgit-users mailing list [email protected] https://mail.gna.org/listinfo/stgit-users
