Skip to content

Commit

Permalink
refactor; add failing test to validate #1210
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Apr 14, 2021
1 parent 14fc8bd commit 651a81d
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 54 deletions.
107 changes: 54 additions & 53 deletions git/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,58 @@ def _index_from_patch_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:

return index

@staticmethod
def _handle_diff_line(lines_bytes: bytes, repo: 'Repo', index: TBD) -> None:
lines = lines_bytes.decode(defenc)

for line in lines.split(':')[1:]:
meta, _, path = line.partition('\x00')
path = path.rstrip('\x00')
a_blob_id, b_blob_id = None, None # Type: Optional[str]
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)
deleted_file = False
new_file = False
copied_file = False
rename_from = None
rename_to = None

# NOTE: We cannot conclude from the existence of a blob to change type
# as diffs with the working do not have blobs yet
if change_type == 'D':
b_blob_id = None # Optional[str]
deleted_file = True
elif change_type == 'A':
a_blob_id = None
new_file = True
elif change_type == 'C':
copied_file = True
a_path_str, b_path_str = path.split('\x00', 1)
a_path = a_path_str.encode(defenc)
b_path = b_path_str.encode(defenc)
elif change_type == 'R':
a_path_str, b_path_str = path.split('\x00', 1)
a_path = a_path_str.encode(defenc)
b_path = b_path_str.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, copied_file, rename_from, rename_to,
'', change_type, score)
index.append(diff)

@classmethod
def _index_from_raw_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
"""Create a new DiffIndex from the given stream which must be in raw format.
Expand All @@ -498,58 +550,7 @@ def _index_from_raw_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
# :100644 100644 687099101... 37c5e30c8... M .gitignore

index = DiffIndex()

def handle_diff_line(lines_bytes: bytes) -> None:
lines = lines_bytes.decode(defenc)

for line in lines.split(':')[1:]:
meta, _, path = line.partition('\x00')
path = path.rstrip('\x00')
a_blob_id, b_blob_id = None, None # Type: Optional[str]
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)
deleted_file = False
new_file = False
copied_file = False
rename_from = None
rename_to = None

# NOTE: We cannot conclude from the existence of a blob to change type
# as diffs with the working do not have blobs yet
if change_type == 'D':
b_blob_id = None # Optional[str]
deleted_file = True
elif change_type == 'A':
a_blob_id = None
new_file = True
elif change_type == 'C':
copied_file = True
a_path_str, b_path_str = path.split('\x00', 1)
a_path = a_path_str.encode(defenc)
b_path = b_path_str.encode(defenc)
elif change_type == 'R':
a_path_str, b_path_str = path.split('\x00', 1)
a_path = a_path_str.encode(defenc)
b_path = b_path_str.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, 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)
handle_process_output(proc, lambda bytes: cls._handle_diff_line(
bytes, repo, index), None, finalize_process, decode_streams=False)

return index
2 changes: 1 addition & 1 deletion git/ext/gitdb
Binary file added test/fixtures/diff_file_with_colon
Binary file not shown.
7 changes: 7 additions & 0 deletions test/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ddt
import shutil
import tempfile
import unittest
from git import (
Repo,
GitCommandError,
Expand Down Expand Up @@ -220,6 +221,12 @@ def test_diff_index_raw_format(self):
self.assertIsNotNone(res[0].deleted_file)
self.assertIsNone(res[0].b_path,)

@unittest.skip("This currently fails and would need someone to improve diff parsing")
def test_diff_file_with_colon(self):
output = fixture('diff_file_with_colon')
res = []
Diff._handle_diff_line(output, None, res)

def test_diff_initial_commit(self):
initial_commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')

Expand Down

0 comments on commit 651a81d

Please sign in to comment.