From 59ad90694b5393ce7f6790ade9cb58c24b8028e5 Mon Sep 17 00:00:00 2001 From: JJ Graham Date: Thu, 17 Oct 2019 22:15:45 -0500 Subject: Adding diff support for copied files, still working on test --- git/diff.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'git/diff.py') diff --git a/git/diff.py b/git/diff.py index 10cb9f02..5a63d44c 100644 --- a/git/diff.py +++ b/git/diff.py @@ -193,6 +193,8 @@ class DiffIndex(list): yield diff elif change_type == "D" and diff.deleted_file: yield diff + elif change_type == "C" and diff.copied_file: + yield diff elif change_type == "R" and diff.renamed: yield diff elif change_type == "M" and diff.a_blob and diff.b_blob and diff.a_blob != diff.b_blob: @@ -243,6 +245,7 @@ class Diff(object): ^rename[ ]to[ ](?P.*)(?:\n|$))? (?:^new[ ]file[ ]mode[ ](?P.+)(?:\n|$))? (?:^deleted[ ]file[ ]mode[ ](?P.+)(?:\n|$))? + (?:^copied[ ]file[ ]mode[ ](?P.+)(?:\n|$))? (?:^index[ ](?P[0-9A-Fa-f]+) \.\.(?P[0-9A-Fa-f]+)[ ]?(?P.+)?(?:\n|$))? (?:^---[ ](?P[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))? @@ -253,11 +256,11 @@ class Diff(object): NULL_BIN_SHA = b"\0" * 20 __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", "score") + "new_file", "deleted_file", "copied_file", "raw_rename_from", + "raw_rename_to", "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, + b_mode, new_file, deleted_file, copied_file, raw_rename_from, raw_rename_to, diff, change_type, score): self.a_mode = a_mode @@ -285,6 +288,7 @@ class Diff(object): self.new_file = new_file self.deleted_file = deleted_file + self.copied_file = copied_file # be clear and use None instead of empty strings assert raw_rename_from is None or isinstance(raw_rename_from, binary_type) @@ -336,6 +340,8 @@ class Diff(object): msg += '\nfile deleted in rhs' if self.new_file: msg += '\nfile added in rhs' + if self.copied_file: + msg += '\nfile %r copied from %r' % (self.b_path, self.a_path) if self.rename_from: msg += '\nfile renamed from %r' % self.rename_from if self.rename_to: @@ -419,11 +425,12 @@ class Diff(object): a_path_fallback, b_path_fallback, \ old_mode, new_mode, \ rename_from, rename_to, \ - new_file_mode, deleted_file_mode, \ + new_file_mode, deleted_file_mode, copied_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) + new_file, deleted_file, copied_file = \ + bool(new_file_mode), bool(deleted_file_mode), bool(copied_file_mode) a_path = cls._pick_best_path(a_path, rename_from, a_path_fallback) b_path = cls._pick_best_path(b_path, rename_to, b_path_fallback) @@ -445,7 +452,7 @@ class Diff(object): b_blob_id and b_blob_id.decode(defenc), a_mode and a_mode.decode(defenc), b_mode and b_mode.decode(defenc), - new_file, deleted_file, + new_file, deleted_file, copied_file, rename_from, rename_to, None, None, None)) @@ -485,6 +492,7 @@ class Diff(object): b_path = path.encode(defenc) deleted_file = False new_file = False + copied_file = False rename_from = None rename_to = None @@ -496,6 +504,11 @@ class Diff(object): elif change_type == 'A': a_blob_id = None new_file = True + elif change_type == 'C': + copied_file = True + a_path, b_path = path.split('\t', 1) + a_path = a_path.encode(defenc) + b_path = b_path.encode(defenc) elif change_type == 'R': a_path, b_path = path.split('\t', 1) a_path = a_path.encode(defenc) @@ -507,8 +520,8 @@ class Diff(object): # 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, score) + new_file, deleted_file, copied_file, rename_from, rename_to, + '', change_type, score) index.append(diff) handle_process_output(proc, handle_diff_line, None, finalize_process, decode_streams=False) -- cgit v1.2.1 From 71b3845807458766cd715c60a5f244836f4273b6 Mon Sep 17 00:00:00 2001 From: JJ Graham Date: Thu, 17 Oct 2019 23:04:22 -0500 Subject: Fixed new test for copied files --- git/diff.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'git/diff.py') diff --git a/git/diff.py b/git/diff.py index 5a63d44c..8bb0f839 100644 --- a/git/diff.py +++ b/git/diff.py @@ -167,7 +167,7 @@ class DiffIndex(list): # R = Renamed # M = Modified # T = Changed in the type - change_type = ("A", "D", "R", "M", "T") + change_type = ("A", "C", "D", "R", "M", "T") def iter_change_type(self, change_type): """ @@ -245,7 +245,9 @@ class Diff(object): ^rename[ ]to[ ](?P.*)(?:\n|$))? (?:^new[ ]file[ ]mode[ ](?P.+)(?:\n|$))? (?:^deleted[ ]file[ ]mode[ ](?P.+)(?:\n|$))? - (?:^copied[ ]file[ ]mode[ ](?P.+)(?:\n|$))? + (?:^similarity[ ]index[ ]\d+%\n + ^copy[ ]from[ ].*\n + ^copy[ ]to[ ](?P.*)(?:\n|$))? (?:^index[ ](?P[0-9A-Fa-f]+) \.\.(?P[0-9A-Fa-f]+)[ ]?(?P.+)?(?:\n|$))? (?:^---[ ](?P[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))? -- cgit v1.2.1 From 4744efbb68c562adf7b42fc33381d27a463ae07a Mon Sep 17 00:00:00 2001 From: JJ Graham Date: Fri, 18 Oct 2019 10:32:30 -0500 Subject: Updating variable name to more accurately reflect contents --- git/diff.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'git/diff.py') diff --git a/git/diff.py b/git/diff.py index 8bb0f839..80e0be6a 100644 --- a/git/diff.py +++ b/git/diff.py @@ -247,7 +247,7 @@ class Diff(object): (?:^deleted[ ]file[ ]mode[ ](?P.+)(?:\n|$))? (?:^similarity[ ]index[ ]\d+%\n ^copy[ ]from[ ].*\n - ^copy[ ]to[ ](?P.*)(?:\n|$))? + ^copy[ ]to[ ](?P.*)(?:\n|$))? (?:^index[ ](?P[0-9A-Fa-f]+) \.\.(?P[0-9A-Fa-f]+)[ ]?(?P.+)?(?:\n|$))? (?:^---[ ](?P[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))? @@ -427,12 +427,12 @@ class Diff(object): a_path_fallback, b_path_fallback, \ old_mode, new_mode, \ rename_from, rename_to, \ - new_file_mode, deleted_file_mode, copied_file_mode, \ + new_file_mode, deleted_file_mode, copied_file_name, \ a_blob_id, b_blob_id, b_mode, \ a_path, b_path = header.groups() new_file, deleted_file, copied_file = \ - bool(new_file_mode), bool(deleted_file_mode), bool(copied_file_mode) + bool(new_file_mode), bool(deleted_file_mode), bool(copied_file_name) a_path = cls._pick_best_path(a_path, rename_from, a_path_fallback) b_path = cls._pick_best_path(b_path, rename_to, b_path_fallback) -- cgit v1.2.1 From 95897f99551db8d81ca77adec3f44e459899c20b Mon Sep 17 00:00:00 2001 From: JJ Graham Date: Fri, 18 Oct 2019 14:49:06 -0500 Subject: Satisfying flake8 --- git/diff.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'git/diff.py') diff --git a/git/diff.py b/git/diff.py index 80e0be6a..0150d675 100644 --- a/git/diff.py +++ b/git/diff.py @@ -258,7 +258,7 @@ class Diff(object): NULL_BIN_SHA = b"\0" * 20 __slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "a_rawpath", "b_rawpath", - "new_file", "deleted_file", "copied_file", "raw_rename_from", + "new_file", "deleted_file", "copied_file", "raw_rename_from", "raw_rename_to", "diff", "change_type", "score") def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode, @@ -432,7 +432,7 @@ class Diff(object): a_path, b_path = header.groups() new_file, deleted_file, copied_file = \ - bool(new_file_mode), bool(deleted_file_mode), bool(copied_file_name) + bool(new_file_mode), bool(deleted_file_mode), bool(copied_file_name) a_path = cls._pick_best_path(a_path, rename_from, a_path_fallback) b_path = cls._pick_best_path(b_path, rename_to, b_path_fallback) -- cgit v1.2.1 From b303cb0c5995bf9c74db34a8082cdf5258c250fe Mon Sep 17 00:00:00 2001 From: JJ Graham Date: Sun, 20 Oct 2019 15:40:06 -0500 Subject: Initial stab at fixing diffs involving submodule changes --- git/diff.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'git/diff.py') diff --git a/git/diff.py b/git/diff.py index 0150d675..3dbe0866 100644 --- a/git/diff.py +++ b/git/diff.py @@ -278,6 +278,14 @@ class Diff(object): if self.b_mode: self.b_mode = mode_str_to_int(self.b_mode) + # Determine whether this diff references a submodule, if it does then + # we need to overwrite "repo" to the corresponding submodule's repo instead + if repo and a_rawpath: + for submodule in repo.submodules: + if submodule.path == a_rawpath.decode("utf-8"): + repo = submodule.module() + break + if a_blob_id is None or a_blob_id == self.NULL_HEX_SHA: self.a_blob = None else: -- cgit v1.2.1 From 14d7034adc2698c1e7dd13570c23d217c753e932 Mon Sep 17 00:00:00 2001 From: JJ Graham Date: Mon, 21 Oct 2019 17:16:59 -0500 Subject: Fix #852 by tweaking regex to handle -R option to git diff --- git/diff.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git/diff.py') diff --git a/git/diff.py b/git/diff.py index 3dbe0866..a0076f0c 100644 --- a/git/diff.py +++ b/git/diff.py @@ -237,7 +237,7 @@ class Diff(object): # precompiled regex re_header = re.compile(br""" ^diff[ ]--git - [ ](?P"?a/.+?"?)[ ](?P"?b/.+?"?)\n + [ ](?P"?[ab]/.+?"?)[ ](?P"?[ab]/.+?"?)\n (?:^old[ ]mode[ ](?P\d+)\n ^new[ ]mode[ ](?P\d+)(?:\n|$))? (?:^similarity[ ]index[ ]\d+%\n -- cgit v1.2.1