Skip to content
This repository has been archived by the owner on May 22, 2019. It is now read-only.

Communication over pipe made more robust. #14

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 32 additions & 12 deletions tracext/git/PyGIT.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from contextlib import contextmanager
import cStringIO
import codecs
from trac.util import TracError

__all__ = ["git_version", "GitError", "GitErrorSha", "Storage", "StorageFactory"]

Expand Down Expand Up @@ -266,11 +267,14 @@ def __init__(self, git_dir, log, git_bin='git', git_fs_encoding=None):
self.__commit_msg_lock = Lock()

self.__cat_file_pipe = None
self.__cat_file_pipe_lock = Lock()

def __del__(self):
if self.__cat_file_pipe is not None:
self.__cat_file_pipe.stdin.close()
self.__cat_file_pipe.wait()
with self.__cat_file_pipe_lock:
if self.__cat_file_pipe is not None:
self.__cat_file_pipe.stdin.close()
self.__cat_file_pipe.terminate()
self.__cat_file_pipe.wait()

#
# cache handling
Expand Down Expand Up @@ -492,18 +496,34 @@ def head(self):
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()
with self.__cat_file_pipe_lock:
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()
try:
self.__cat_file_pipe.stdin.write(sha + '\n')
self.__cat_file_pipe.stdin.flush()

split_stdout_line = self.__cat_file_pipe.stdout.readline().split()
if len(split_stdout_line) != 3:
raise TracError("internal error (could not split line properly %s)" % (split_stdout_line,))

if _type != kind:
raise TracError("internal error (got unexpected object kind '%s')" % k)
_sha, _type, _size = split_stdout_line

size = int(_size)
return self.__cat_file_pipe.stdout.read(size + 1)[:size]
if _type != kind:
raise TracError("internal error (got unexpected object kind '%s', expected '%s')" % (_type, kind))

size = int(_size)
return self.__cat_file_pipe.stdout.read(size + 1)[:size]
except:
# There was an error, we should close the pipe to get to a consistent state
# (Otherwise it happens that next time we call cat_file we get payload from previous call)
self.logger.debug("closing cat_file pipe")
self.__cat_file_pipe.stdin.close()
self.__cat_file_pipe.terminate()
self.__cat_file_pipe.wait()
self.__cat_file_pipe = None
raise

def verifyrev(self, rev):
"verify/lookup given revision object and return a sha id or None if lookup failed"
Expand Down