Skip to content

Commit 651a81d

Browse files
committed
refactor; add failing test to validate #1210
1 parent 14fc8bd commit 651a81d

File tree

4 files changed

+62
-54
lines changed

4 files changed

+62
-54
lines changed

git/diff.py

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,58 @@ def _index_from_patch_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
490490

491491
return index
492492

493+
@staticmethod
494+
def _handle_diff_line(lines_bytes: bytes, repo: 'Repo', index: TBD) -> None:
495+
lines = lines_bytes.decode(defenc)
496+
497+
for line in lines.split(':')[1:]:
498+
meta, _, path = line.partition('\x00')
499+
path = path.rstrip('\x00')
500+
a_blob_id, b_blob_id = None, None # Type: Optional[str]
501+
old_mode, new_mode, a_blob_id, b_blob_id, _change_type = meta.split(None, 4)
502+
# Change type can be R100
503+
# R: status letter
504+
# 100: score (in case of copy and rename)
505+
change_type = _change_type[0]
506+
score_str = ''.join(_change_type[1:])
507+
score = int(score_str) if score_str.isdigit() else None
508+
path = path.strip()
509+
a_path = path.encode(defenc)
510+
b_path = path.encode(defenc)
511+
deleted_file = False
512+
new_file = False
513+
copied_file = False
514+
rename_from = None
515+
rename_to = None
516+
517+
# NOTE: We cannot conclude from the existence of a blob to change type
518+
# as diffs with the working do not have blobs yet
519+
if change_type == 'D':
520+
b_blob_id = None # Optional[str]
521+
deleted_file = True
522+
elif change_type == 'A':
523+
a_blob_id = None
524+
new_file = True
525+
elif change_type == 'C':
526+
copied_file = True
527+
a_path_str, b_path_str = path.split('\x00', 1)
528+
a_path = a_path_str.encode(defenc)
529+
b_path = b_path_str.encode(defenc)
530+
elif change_type == 'R':
531+
a_path_str, b_path_str = path.split('\x00', 1)
532+
a_path = a_path_str.encode(defenc)
533+
b_path = b_path_str.encode(defenc)
534+
rename_from, rename_to = a_path, b_path
535+
elif change_type == 'T':
536+
# Nothing to do
537+
pass
538+
# END add/remove handling
539+
540+
diff = Diff(repo, a_path, b_path, a_blob_id, b_blob_id, old_mode, new_mode,
541+
new_file, deleted_file, copied_file, rename_from, rename_to,
542+
'', change_type, score)
543+
index.append(diff)
544+
493545
@classmethod
494546
def _index_from_raw_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
495547
"""Create a new DiffIndex from the given stream which must be in raw format.
@@ -498,58 +550,7 @@ def _index_from_raw_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
498550
# :100644 100644 687099101... 37c5e30c8... M .gitignore
499551

500552
index = DiffIndex()
501-
502-
def handle_diff_line(lines_bytes: bytes) -> None:
503-
lines = lines_bytes.decode(defenc)
504-
505-
for line in lines.split(':')[1:]:
506-
meta, _, path = line.partition('\x00')
507-
path = path.rstrip('\x00')
508-
a_blob_id, b_blob_id = None, None # Type: Optional[str]
509-
old_mode, new_mode, a_blob_id, b_blob_id, _change_type = meta.split(None, 4)
510-
# Change type can be R100
511-
# R: status letter
512-
# 100: score (in case of copy and rename)
513-
change_type = _change_type[0]
514-
score_str = ''.join(_change_type[1:])
515-
score = int(score_str) if score_str.isdigit() else None
516-
path = path.strip()
517-
a_path = path.encode(defenc)
518-
b_path = path.encode(defenc)
519-
deleted_file = False
520-
new_file = False
521-
copied_file = False
522-
rename_from = None
523-
rename_to = None
524-
525-
# NOTE: We cannot conclude from the existence of a blob to change type
526-
# as diffs with the working do not have blobs yet
527-
if change_type == 'D':
528-
b_blob_id = None # Optional[str]
529-
deleted_file = True
530-
elif change_type == 'A':
531-
a_blob_id = None
532-
new_file = True
533-
elif change_type == 'C':
534-
copied_file = True
535-
a_path_str, b_path_str = path.split('\x00', 1)
536-
a_path = a_path_str.encode(defenc)
537-
b_path = b_path_str.encode(defenc)
538-
elif change_type == 'R':
539-
a_path_str, b_path_str = path.split('\x00', 1)
540-
a_path = a_path_str.encode(defenc)
541-
b_path = b_path_str.encode(defenc)
542-
rename_from, rename_to = a_path, b_path
543-
elif change_type == 'T':
544-
# Nothing to do
545-
pass
546-
# END add/remove handling
547-
548-
diff = Diff(repo, a_path, b_path, a_blob_id, b_blob_id, old_mode, new_mode,
549-
new_file, deleted_file, copied_file, rename_from, rename_to,
550-
'', change_type, score)
551-
index.append(diff)
552-
553-
handle_process_output(proc, handle_diff_line, None, finalize_process, decode_streams=False)
553+
handle_process_output(proc, lambda bytes: cls._handle_diff_line(
554+
bytes, repo, index), None, finalize_process, decode_streams=False)
554555

555556
return index

test/fixtures/diff_file_with_colon

351 Bytes
Binary file not shown.

test/test_diff.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import ddt
88
import shutil
99
import tempfile
10+
import unittest
1011
from git import (
1112
Repo,
1213
GitCommandError,
@@ -220,6 +221,12 @@ def test_diff_index_raw_format(self):
220221
self.assertIsNotNone(res[0].deleted_file)
221222
self.assertIsNone(res[0].b_path,)
222223

224+
@unittest.skip("This currently fails and would need someone to improve diff parsing")
225+
def test_diff_file_with_colon(self):
226+
output = fixture('diff_file_with_colon')
227+
res = []
228+
Diff._handle_diff_line(output, None, res)
229+
223230
def test_diff_initial_commit(self):
224231
initial_commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')
225232

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy