summaryrefslogtreecommitdiff
path: root/git/diff.py
diff options
context:
space:
mode:
authorAnil Khatri <27620628+imkaka@users.noreply.github.com>2019-10-23 23:37:43 +0530
committerGitHub <noreply@github.com>2019-10-23 23:37:43 +0530
commitabb18968516c6c3c9e1d736bfe6f435392b3d3af (patch)
tree46b45bc52901f0f52526f9573f06b2fc0f777231 /git/diff.py
parent284f89d768080cb86e0d986bfa1dd503cfe6b682 (diff)
parentdfa0eac1578bff14a8f7fa00bfc3c57aba24f877 (diff)
downloadgitpython-abb18968516c6c3c9e1d736bfe6f435392b3d3af.tar.gz
Merge branch 'master' into fix/deepsource-issues
Diffstat (limited to 'git/diff.py')
-rw-r--r--git/diff.py43
1 files changed, 33 insertions, 10 deletions
diff --git a/git/diff.py b/git/diff.py
index 6a5d51cc..897228a7 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):
"""
@@ -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:
@@ -235,7 +237,7 @@ class Diff(object):
# precompiled regex
re_header = re.compile(br"""
^diff[ ]--git
- [ ](?P<a_path_fallback>"?a/.+?"?)[ ](?P<b_path_fallback>"?b/.+?"?)\n
+ [ ](?P<a_path_fallback>"?[ab]/.+?"?)[ ](?P<b_path_fallback>"?[ab]/.+?"?)\n
(?:^old[ ]mode[ ](?P<old_mode>\d+)\n
^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))?
(?:^similarity[ ]index[ ]\d+%\n
@@ -243,6 +245,9 @@ class Diff(object):
^rename[ ]to[ ](?P<rename_to>.*)(?:\n|$))?
(?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))?
(?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))?
+ (?:^similarity[ ]index[ ]\d+%\n
+ ^copy[ ]from[ ].*\n
+ ^copy[ ]to[ ](?P<copied_file_name>.*)(?:\n|$))?
(?:^index[ ](?P<a_blob_id>[0-9A-Fa-f]+)
\.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))?
(?:^---[ ](?P<a_path>[^\t\n\r\f\v]*)[\t\r\f\v]*(?:\n|$))?
@@ -253,11 +258,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
@@ -273,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:
@@ -285,6 +298,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 +350,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:
@@ -420,11 +436,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_name, \
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_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)
@@ -446,7 +463,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))
@@ -487,6 +504,7 @@ class Diff(object):
b_path = path.encode(defenc)
deleted_file = False
new_file = False
+ copied_file = False
rename_from = None
rename_to = None
@@ -498,6 +516,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)
@@ -509,8 +532,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)