Skip to content

Fix rename change type & support 'change in type' #755

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 19, 2018
Merged
Show file tree
Hide file tree
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
32 changes: 23 additions & 9 deletions git/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ class DiffIndex(list):
# A = Added
# D = Deleted
# R = Renamed
# M = modified
change_type = ("A", "D", "R", "M")
# M = Modified
# T = Changed in the type
change_type = ("A", "D", "R", "M", "T")

def iter_change_type(self, change_type):
"""
Expand All @@ -179,7 +180,9 @@ def iter_change_type(self, change_type):
* 'A' for added paths
* 'D' for deleted paths
* 'R' for renamed paths
* 'M' for paths with modified data"""
* 'M' for paths with modified data
* 'T' for changed in the type paths
"""
if change_type not in self.change_type:
raise ValueError("Invalid change type: %s" % change_type)

Expand Down Expand Up @@ -251,11 +254,11 @@ class Diff(object):

__slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "a_rawpath", "b_rawpath",
"new_file", "deleted_file", "raw_rename_from", "raw_rename_to",
"diff", "change_type")
"diff", "change_type", "score")

def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode,
b_mode, new_file, deleted_file, raw_rename_from,
raw_rename_to, diff, change_type):
raw_rename_to, diff, change_type, score):

self.a_mode = a_mode
self.b_mode = b_mode
Expand Down Expand Up @@ -291,6 +294,7 @@ def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode,

self.diff = diff
self.change_type = change_type
self.score = score

def __eq__(self, other):
for name in self.__slots__:
Expand Down Expand Up @@ -445,7 +449,7 @@ def _index_from_patch_format(cls, repo, proc):
new_file, deleted_file,
rename_from,
rename_to,
None, None))
None, None, None))

previous_header = header
# end for each header we parse
Expand All @@ -470,7 +474,13 @@ def handle_diff_line(line):
return

meta, _, path = line[1:].partition('\t')
old_mode, new_mode, a_blob_id, b_blob_id, change_type = meta.split(None, 4)
old_mode, new_mode, a_blob_id, b_blob_id, _change_type = meta.split(None, 4)
# Change type can be R100
# R: status letter
# 100: score (in case of copy and rename)
change_type = _change_type[0]
score_str = ''.join(_change_type[1:])
score = int(score_str) if score_str.isdigit() else None
path = path.strip()
a_path = path.encode(defenc)
b_path = path.encode(defenc)
Expand All @@ -487,15 +497,19 @@ def handle_diff_line(line):
elif change_type == 'A':
a_blob_id = None
new_file = True
elif change_type[0] == 'R': # parses RXXX, where XXX is a confidence value
elif change_type == 'R':
a_path, b_path = path.split('\t', 1)
a_path = a_path.encode(defenc)
b_path = b_path.encode(defenc)
rename_from, rename_to = a_path, b_path
elif change_type == 'T':
# Nothing to do
pass
# 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, rename_from, rename_to, '', change_type)
new_file, deleted_file, rename_from, rename_to, '',
change_type, score)
index.append(diff)

handle_process_output(proc, handle_diff_line, None, finalize_process, decode_streams=False)
Expand Down
10 changes: 10 additions & 0 deletions git/test/fixtures/diff_change_in_type
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
diff --git a/this b/this
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/this b/this
new file mode 120000
index 0000000000000000000000000000000000000000..42061c01a1c70097d1e4579f29a5adf40abdec95
--- /dev/null
+++ b/this
@@ -0,0 +1 @@
+that
1 change: 1 addition & 0 deletions git/test/fixtures/diff_change_in_type_raw
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:100644 120000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 42061c01a1c70097d1e4579f29a5adf40abdec95 T this
29 changes: 29 additions & 0 deletions git/test/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,37 @@ def test_diff_with_rename(self):
self.assertIsNotNone(diff.renamed)
self.assertEqual(diff.rename_from, 'this')
self.assertEqual(diff.rename_to, 'that')
self.assertEqual(diff.change_type, 'R')
self.assertEqual(diff.score, 100)
self.assertEqual(len(list(diffs.iter_change_type('R'))), 1)

def test_diff_with_change_in_type(self):
output = StringProcessAdapter(fixture('diff_change_in_type'))
diffs = Diff._index_from_patch_format(self.rorepo, output)
self._assert_diff_format(diffs)
assert_equal(2, len(diffs))

diff = diffs[0]
self.assertIsNotNone(diff.deleted_file)
assert_equal(diff.a_path, 'this')
assert_equal(diff.b_path, 'this')
assert isinstance(str(diff), str)

diff = diffs[1]
assert_equal(diff.a_path, None)
assert_equal(diff.b_path, 'this')
self.assertIsNotNone(diff.new_file)
assert isinstance(str(diff), str)

output = StringProcessAdapter(fixture('diff_change_in_type_raw'))
diffs = Diff._index_from_raw_format(self.rorepo, output)
self.assertEqual(len(diffs), 1)
diff = diffs[0]
self.assertEqual(diff.rename_from, None)
self.assertEqual(diff.rename_to, None)
self.assertEqual(diff.change_type, 'T')
self.assertEqual(len(list(diffs.iter_change_type('T'))), 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a test for score is missing. It's likely to not work in the current implementation.


def test_diff_of_modified_files_not_added_to_the_index(self):
output = StringProcessAdapter(fixture('diff_abbrev-40_full-index_M_raw_no-color'))
diffs = Diff._index_from_raw_format(self.rorepo, output)
Expand Down