diff options
Diffstat (limited to 'lib/git/objects')
-rw-r--r-- | lib/git/objects/base.py | 1 | ||||
-rw-r--r-- | lib/git/objects/commit.py | 40 | ||||
-rw-r--r-- | lib/git/objects/tree.py | 17 |
3 files changed, 35 insertions, 23 deletions
diff --git a/lib/git/objects/base.py b/lib/git/objects/base.py index 0dfd1a23..0bece6f1 100644 --- a/lib/git/objects/base.py +++ b/lib/git/objects/base.py @@ -20,6 +20,7 @@ class Object(LazyMixin): inst.size # objects uncompressed data size inst.data # byte string containing the whole data of the object """ + NULL_HEX_SHA = '0'*40 TYPES = ("blob", "tree", "commit", "tag") __slots__ = ("repo", "id", "size", "data" ) type = None # to be set by subclass diff --git a/lib/git/objects/commit.py b/lib/git/objects/commit.py index 0f8ed7f8..d9f87116 100644 --- a/lib/git/objects/commit.py +++ b/lib/git/objects/commit.py @@ -83,7 +83,7 @@ class Commit(base.Object, Iterable, diff.Diffable): # prepare our data lines to match rev-list data_lines = self.data.splitlines() data_lines.insert(0, "commit %s" % self.id) - temp = self._iter_from_process_or_stream(self.repo, iter(data_lines)).next() + temp = self._iter_from_process_or_stream(self.repo, iter(data_lines), False).next() self.parents = temp.parents self.tree = temp.tree self.author = temp.author @@ -111,7 +111,8 @@ class Commit(base.Object, Iterable, diff.Diffable): to commits actually containing the paths ``kwargs`` - Additional options to be passed to git-rev-list + Additional options to be passed to git-rev-list. They must not alter + the ouput style of the command, or parsing will yield incorrect results Returns int """ @@ -153,9 +154,8 @@ class Commit(base.Object, Iterable, diff.Diffable): options = {'pretty': 'raw', 'as_process' : True } options.update(kwargs) - # the test system might confront us with string values - proc = repo.git.rev_list(rev, '--', paths, **options) - return cls._iter_from_process_or_stream(repo, proc) + return cls._iter_from_process_or_stream(repo, proc, True) def iter_parents(self, paths='', **kwargs): """ @@ -200,7 +200,7 @@ class Commit(base.Object, Iterable, diff.Diffable): return stats.Stats._list_from_string(self.repo, text) @classmethod - def _iter_from_process_or_stream(cls, repo, proc_or_stream): + def _iter_from_process_or_stream(cls, repo, proc_or_stream, from_rev_list): """ Parse out commit information into a list of Commit objects @@ -210,6 +210,9 @@ class Commit(base.Object, Iterable, diff.Diffable): ``proc`` git-rev-list process instance (raw format) + ``from_rev_list`` + If True, the stream was created by rev-list in which case we parse + the message differently Returns iterator returning Commit objects """ @@ -217,10 +220,10 @@ class Commit(base.Object, Iterable, diff.Diffable): if not hasattr(stream,'next'): stream = proc_or_stream.stdout - for line in stream: - id = line.split()[1] - assert line.split()[0] == "commit" + commit_tokens = line.split() + id = commit_tokens[1] + assert commit_tokens[0] == "commit" tree = stream.next().split()[1] parents = [] @@ -240,13 +243,20 @@ class Commit(base.Object, Iterable, diff.Diffable): stream.next() message_lines = [] - next_line = None - for msg_line in stream: - if not msg_line.startswith(' '): - break - # END abort message reading - message_lines.append(msg_line.strip()) - # END while there are message lines + if from_rev_list: + for msg_line in stream: + if not msg_line.startswith(' '): + # and forget about this empty marker + break + # END abort message reading + # strip leading 4 spaces + message_lines.append(msg_line[4:]) + # END while there are message lines + else: + # a stream from our data simply gives us the plain message + for msg_line in stream: + message_lines.append(msg_line) + # END message parsing message = '\n'.join(message_lines) yield Commit(repo, id=id, parents=tuple(parents), tree=tree, author=author, authored_date=authored_date, diff --git a/lib/git/objects/tree.py b/lib/git/objects/tree.py index 92aae881..371c0dd3 100644 --- a/lib/git/objects/tree.py +++ b/lib/git/objects/tree.py @@ -38,9 +38,9 @@ class Tree(base.IndexObject, diff.Diffable): __slots__ = "_cache" # using ascii codes for comparison - ascii_commit_id = (0x31 << 4) + 0x36 - ascii_blob_id = (0x31 << 4) + 0x30 - ascii_tree_id = (0x34 << 4) + 0x30 + commit_id = 016 + blob_id = 010 + tree_id = 040 def __init__(self, repo, id, mode=0, path=None): @@ -88,8 +88,8 @@ class Tree(base.IndexObject, diff.Diffable): mode = 0 mode_boundary = i + 6 - # keep it ascii - we compare against the respective values - type_id = (ord(data[i])<<4) + ord(data[i+1]) + # read type + type_id = ((ord(data[i])-ord_zero)<<3) + (ord(data[i+1])-ord_zero) i += 2 while data[i] != ' ': @@ -115,12 +115,13 @@ class Tree(base.IndexObject, diff.Diffable): sha = data[i:i+20] i = i + 20 + mode |= type_id<<12 hexsha = sha_to_hex(sha) - if type_id == self.ascii_blob_id: + if type_id == self.blob_id: yield blob.Blob(self.repo, hexsha, mode, name) - elif type_id == self.ascii_tree_id: + elif type_id == self.tree_id: yield Tree(self.repo, hexsha, mode, name) - elif type_id == self.ascii_commit_id: + elif type_id == self.commit_id: # todo yield None else: |