diff options
author | Vincent Driessen <me@nvie.com> | 2016-04-19 21:46:59 +0200 |
---|---|---|
committer | Vincent Driessen <me@nvie.com> | 2016-04-19 21:46:59 +0200 |
commit | 8bbf1a3b801fb4e00c10f631faa87114dcd0462f (patch) | |
tree | a231962fc64fb5b255d87ecb409bfc1f48dfe8a5 /git/diff.py | |
parent | 0d7a40f603412be7e1046b500057b08558d9d250 (diff) | |
parent | 1445b59bb41c4b1a94b7cb0ec6864c98de63814b (diff) | |
download | gitpython-8bbf1a3b801fb4e00c10f631faa87114dcd0462f.tar.gz |
Merge pull request #412 from nvie/fix-diff-patch-parsing
Fix diff patch parsing
Diffstat (limited to 'git/diff.py')
-rw-r--r-- | git/diff.py | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/git/diff.py b/git/diff.py index de3aa1e8..d4affd30 100644 --- a/git/diff.py +++ b/git/diff.py @@ -198,16 +198,18 @@ class Diff(object): # precompiled regex re_header = re.compile(r""" ^diff[ ]--git - [ ](?:a/)?(?P<a_path>.+?)[ ](?:b/)?(?P<b_path>.+?)\n - (?:^similarity[ ]index[ ](?P<similarity_index>\d+)%\n - ^rename[ ]from[ ](?P<rename_from>\S+)\n - ^rename[ ]to[ ](?P<rename_to>\S+)(?:\n|$))? + [ ](?:a/)?(?P<a_path_fallback>.+?)[ ](?:b/)?(?P<b_path_fallback>.+?)\n (?:^old[ ]mode[ ](?P<old_mode>\d+)\n ^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))? + (?:^similarity[ ]index[ ]\d+%\n + ^rename[ ]from[ ](?P<rename_from>.*)\n + ^rename[ ]to[ ](?P<rename_to>.*)(?:\n|$))? (?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))? (?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))? (?:^index[ ](?P<a_blob_id>[0-9A-Fa-f]+) \.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))? + (?:^---[ ](?:a/)?(?P<a_path>[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))? + (?:^\+\+\+[ ](?:b/)?(?P<b_path>[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))? """.encode('ascii'), re.VERBOSE | re.MULTILINE) # can be used for comparisons NULL_HEX_SHA = "0" * 40 @@ -231,15 +233,14 @@ class Diff(object): if self.b_mode: self.b_mode = mode_str_to_int(self.b_mode) - if a_blob_id is None: + if a_blob_id is None or a_blob_id == self.NULL_HEX_SHA: self.a_blob = None else: - assert self.a_mode is not None self.a_blob = Blob(repo, hex_to_bin(a_blob_id), mode=self.a_mode, path=a_path) - if b_blob_id is None: + + if b_blob_id is None or b_blob_id == self.NULL_HEX_SHA: self.b_blob = None else: - assert self.b_mode is not None self.b_blob = Blob(repo, hex_to_bin(b_blob_id), mode=self.b_mode, path=b_path) self.new_file = new_file @@ -329,11 +330,23 @@ class Diff(object): index = DiffIndex() previous_header = None for header in cls.re_header.finditer(text): - a_path, b_path, similarity_index, rename_from, rename_to, \ - old_mode, new_mode, new_file_mode, deleted_file_mode, \ - a_blob_id, b_blob_id, b_mode = header.groups() + a_path_fallback, b_path_fallback, \ + old_mode, new_mode, \ + rename_from, rename_to, \ + new_file_mode, deleted_file_mode, \ + a_blob_id, b_blob_id, b_mode, \ + a_path, b_path = header.groups() new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode) + a_path = a_path or rename_from or a_path_fallback + b_path = b_path or rename_to or b_path_fallback + + if a_path == b'/dev/null': + a_path = None + + if b_path == b'/dev/null': + b_path = None + # Our only means to find the actual text is to see what has not been matched by our regex, # and then retro-actively assin it to our index if previous_header is not None: |