diff --git a/git/diff.py b/git/diff.py index d1c6c0ac3..93ef514f0 100644 --- a/git/diff.py +++ b/git/diff.py @@ -310,12 +310,11 @@ def _index_from_patch_format(cls, repo, stream): @classmethod def _index_from_raw_format(cls, repo, stream): """Create a new DiffIndex from the given stream which must be in raw format. - :note: - This format is inherently incapable of detecting renames, hence we only - modify, delete and add files :return: git.DiffIndex""" # handles # :100644 100644 6870991011cc8d9853a7a8a6f02061512c6a8190 37c5e30c879213e9ae83b21e9d11e55fc20c54b7 M .gitignore + # or + # :100644 100644 4aab7ea753e2867dd464f2a50dd266d426ddc8c8 4aab7ea753e2867dd464f2a50dd266d426ddc8c8 R100 src/bootstrap/package.json package.json index = DiffIndex() for line in stream: if not line.startswith(":"): @@ -323,8 +322,12 @@ def _index_from_raw_format(cls, repo, stream): # END its not a valid diff line old_mode, new_mode, a_blob_id, b_blob_id, change_type, path = line[1:].split(None, 5) path = path.strip() - a_path = path - b_path = path + if change_type[0] != 'R': + a_path = b_path = path + rename_from = rename_to = None + else: + a_path, b_path = path.split('\t') + rename_from, rename_to = a_path, b_path deleted_file = False new_file = False @@ -339,7 +342,7 @@ def _index_from_raw_format(cls, repo, stream): # END add/remove handling diff = Diff(repo, a_path, b_path, a_blob_id, b_blob_id, old_mode, new_mode, - new_file, deleted_file, None, None, '') + new_file, deleted_file, rename_from, rename_to, '') index.append(diff) # END for each line diff --git a/git/test/fixtures/diff_rename_raw b/git/test/fixtures/diff_rename_raw new file mode 100644 index 000000000..14e617a7d --- /dev/null +++ b/git/test/fixtures/diff_rename_raw @@ -0,0 +1,4 @@ +:000000 100644 0000000000000000000000000000000000000000 8b137891791fe96927ad78e64b0aad7bded08bdc A git/test/refs/__init__.py +:100644 100644 271924aa5bf43ef58a0b0dae5a356e502c48dcf8 271924aa5bf43ef58a0b0dae5a356e502c48dcf8 R100 git/test/test_reflog.py git/test/refs/test_reflog.py +:100644 100644 e49b23abc5c47f26e8cf64d46aa6851593ce1404 e49b23abc5c47f26e8cf64d46aa6851593ce1404 R100 git/test/test_refs.py git/test/refs/test_refs.py +:100644 100644 b9a0b617b66962d2c2ba211641675d06f591461f b9a0b617b66962d2c2ba211641675d06f591461f R100 git/test/test_git.py git/test/test_cmd.py diff --git a/git/test/test_diff.py b/git/test/test_diff.py index 79f038e84..55ad3379c 100644 --- a/git/test/test_diff.py +++ b/git/test/test_diff.py @@ -51,6 +51,19 @@ def test_diff_with_rename(self): assert_equal(diff.rename_from, 'AUTHORS') assert_equal(diff.rename_to, 'CONTRIBUTORS') + def test_diff_with_rename_raw(self): + output = StringProcessAdapter(fixture('diff_rename_raw')) + diffs = Diff._index_from_raw_format(self.rorepo, output.stdout) + self._assert_diff_format(diffs) + + diffs = filter(lambda d: d.renamed, diffs) + assert_equal(3, len(diffs)) + + diff = diffs[0] + assert_true(diff.renamed) + assert_equal(diff.rename_from, 'git/test/test_reflog.py') + assert_equal(diff.rename_to, 'git/test/refs/test_reflog.py') + def test_diff_patch_format(self): # test all of the 'old' format diffs for completness - it should at least # be able to deal with it @@ -98,6 +111,14 @@ def test_diff_interface(self): # END for each path option # END for each other side # END for each commit + + # test rename detection + rename_commit = self.rorepo.rev_parse('4772fe0') + rename_diffs = rename_commit.parents[0].diff(rename_commit, M=True) + rename_diffs = filter(lambda d: d.renamed, rename_diffs) + assert len(rename_diffs) == 3 + assert rename_diffs[0].rename_from == rename_diffs[0].a_blob.path + assert rename_diffs[0].rename_to == rename_diffs[0].b_blob.path # assert we could always find at least one instance of the members we # can iterate in the diff index - if not this indicates its not working correctly