Compare commits

..

5 Commits

2 changed files with 46 additions and 17 deletions

View File

@ -3,7 +3,12 @@ from typing import Iterator
def subprocess_readlines(cmd, cwd=None) -> Iterator[str]:
process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, text=True)
process = subprocess.Popen(cmd,
cwd=cwd,
stdout=subprocess.PIPE,
text=True,
encoding='utf-8',
errors='replace')
for line in process.stdout:
line = line.rstrip('\n')
@ -13,3 +18,36 @@ def subprocess_readlines(cmd, cwd=None) -> Iterator[str]:
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, cmd)
def get_changed_files(since, until, diff_filter=None, cwd=None):
command = ['git', 'diff-tree', '-r', '-M']
if diff_filter:
command.extend([f'--diff-filter={diff_filter}'])
command.extend([since, until])
raw_diff = subprocess_readlines(command, cwd=cwd)
return [parse_raw_file_info(raw_diff_entry)
for raw_diff_entry in raw_diff]
def parse_raw_file_info(raw_diff_entry):
diff_entry = raw_diff_entry.lstrip(':').split()
mode_src = diff_entry[0]
mode_dst = diff_entry[1]
sha1_src = diff_entry[2]
sha1_dst = diff_entry[3]
status = diff_entry[4]
src = diff_entry[5]
dst = diff_entry[6] if len(diff_entry) > 6 else src
return {
'mode_src': mode_src,
'mode_dst': mode_dst,
'sha1_src': sha1_src,
'sha1_dst': sha1_dst,
'status': status,
'src': src,
'dst': dst
}

View File

@ -1,6 +1,6 @@
import re
from typing import List, Dict, Tuple, Sized, Iterable, Iterator
from .helper import subprocess_readlines
from .helper import subprocess_readlines, get_changed_files
class ShiftedLines(Sized, Iterable):
@ -28,7 +28,8 @@ class ShiftedLines(Sized, Iterable):
class LineShiftChecker:
DIFF_BLOCK_REGEX = r'@@ -(\d+),(\d+) \+(\d+),(\d+) @@'
SUBMODULE_MODE = '160000'
DIFF_BLOCK_REGEX = r'@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@'
def __init__(self, revision_since: str, revision_until: str) -> None:
self.revision_since = revision_since
@ -39,18 +40,8 @@ class LineShiftChecker:
for file_info in self.__get_changed_files()}
def __get_changed_files(self) -> List[Dict]:
process_output = subprocess_readlines(['git', 'diff', '--name-status', '--diff-filter=MR',
self.revision_since, self.revision_until])
file_list = []
for line in process_output:
raw_file_info = line.split()
file_list.append({
'src': raw_file_info[1],
'dst': raw_file_info[2] if len(raw_file_info) > 2 else raw_file_info[1],
})
return file_list
return [file_info for file_info in get_changed_files(self.revision_since, self.revision_until, diff_filter='MR')
if file_info['mode_src'] != LineShiftChecker.SUBMODULE_MODE]
def __get_shifted_lines_in_file(self, file_info: Dict[str, str]) -> ShiftedLines:
process_output = subprocess_readlines(['git', 'diff',
@ -64,8 +55,8 @@ class LineShiftChecker:
for line in process_output:
matches = re.search(LineShiftChecker.DIFF_BLOCK_REGEX, line)
if matches:
diff_block_src_start = int(matches.group(1))
diff_block_dst_start = int(matches.group(3))
diff_block_src_start = max(int(matches.group(1)), 1) # line number should never be 0
diff_block_dst_start = max(int(matches.group(2)), 1) # line number should never be 0
# fill shifted lines between 2 diff blocks
for i in range(0, diff_block_src_start - src_line_index):