Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Use git cat-file --batch, to avoid repeated fork+exec

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Loading branch information...
commit 0283ffb60178078a2d2d9a83137c83cdd092cc4c 1 parent aa80f45
@andersk andersk authored
Showing with 29 additions and 3 deletions.
  1. +29 −3 tracext/git/PyGIT.py
View
32 tracext/git/PyGIT.py
@@ -67,7 +67,12 @@ def __execute(self, git_cmd, *cmd_args):
return stdout_data
+ def cat_file_batch(self):
+ return self.__pipe('cat-file', '--batch', stdin=PIPE, stdout=PIPE)
+
def __getattr__(self, name):
+ if name[0] == '_' or name in ['cat_file_batch']:
+ raise AttributeError, name
return partial(self.__execute, name.replace('_','-'))
__is_sha_pat = re.compile(r'[0-9A-Fa-f]*$')
@@ -256,6 +261,13 @@ def __init__(self, git_dir, log, git_bin='git', git_fs_encoding=None):
self.__commit_msg_cache = SizedDict(200)
self.__commit_msg_lock = Lock()
+ self.__cat_file_pipe = None
+
+ def __del__(self):
+ if self.__cat_file_pipe is not None:
+ self.__cat_file_pipe.stdin.close()
+ self.__cat_file_pipe.wait()
+
#
# cache handling
#
@@ -475,6 +487,20 @@ def head(self):
"get current HEAD commit id"
return self.verifyrev("HEAD")
+ def cat_file(self, kind, sha):
+ if self.__cat_file_pipe is None:
+ self.__cat_file_pipe = self.repo.cat_file_batch()
+
+ self.__cat_file_pipe.stdin.write(sha + '\n')
+ self.__cat_file_pipe.stdin.flush()
+ _sha, _type, _size = self.__cat_file_pipe.stdout.readline().split()
+
+ if _type != kind:
+ raise TracError("internal error (got unexpected object kind '%s')" % k)
+
+ size = int(_size)
+ return self.__cat_file_pipe.stdout.read(size + 1)[:size]
+
def verifyrev(self, rev):
"verify/lookup given revision object and return a sha id or None if lookup failed"
rev = str(rev)
@@ -496,7 +522,7 @@ def verifyrev(self, rev):
return rc
if rc in _rev_cache.tag_set:
- sha = self.repo.cat_file("tag", rc).split(None, 2)[:2]
+ sha = self.cat_file("tag", rc).split(None, 2)[:2]
if sha[0] != 'object':
self.logger.debug("unexpected result from 'git-cat-file tag %s'" % rc)
return None
@@ -606,7 +632,7 @@ def read_commit(self, commit_id):
return result[0], dict(result[1])
# cache miss
- raw = self.repo.cat_file("commit", commit_id)
+ raw = self.cat_file("commit", commit_id)
raw = unicode(raw, self.get_commit_encoding(), 'replace')
lines = raw.splitlines()
@@ -627,7 +653,7 @@ def read_commit(self, commit_id):
return result[0], dict(result[1])
def get_file(self, sha):
- return cStringIO.StringIO(self.repo.cat_file("blob", str(sha)))
+ return cStringIO.StringIO(self.cat_file("blob", str(sha)))
def get_obj_size(self, sha):
sha = str(sha)
Please sign in to comment.
Something went wrong with that request. Please try again.