Compare commits
2 Commits
2a054276cd
...
0c3b440bf8
Author | SHA1 | Date | |
---|---|---|---|
0c3b440bf8 | |||
64b5528dc9 |
80
README.md
80
README.md
@ -0,0 +1,80 @@
|
||||
# PyDiffChecker
|
||||
|
||||
**Wrappers for git diff**
|
||||
|
||||
## LineShiftChecker
|
||||
|
||||
This tool provides an API for checking shifted but not modified lines in changed files of a Git diff. The tool will collect the lines where the content did not change into dict-like objects with source->destination line number mapping per changed file. File renames are detected as well.
|
||||
|
||||
The behavior is very similar to unified diff on Github or output of [git-diffn](https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh). There are green (added), red (remove) and white (unmodified) lines. The return value of the API will contain these "white" lines with the source/destination line number for the whole file.
|
||||
|
||||
### Example
|
||||
|
||||
Let's assume this is the output of git-diffn:
|
||||
```diff
|
||||
diff --git a/pydiffchecker/helper.py b/pydiffchecker/helper.py
|
||||
index f9d4e08..6a6c214 100644
|
||||
--- a/pydiffchecker/helper.py
|
||||
+++ b/pydiffchecker/helper.py
|
||||
@@ -3,14 +3,13 @@ from typing import Iterator
|
||||
3, 3:
|
||||
4, 4:
|
||||
5, 5: def subprocess_readlines(cmd, cwd=None) -> Iterator[str]:
|
||||
- 6 :- process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE)
|
||||
+ 6:+ process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, text=True)
|
||||
7, 7:
|
||||
8, 8: for line in process.stdout:
|
||||
- 9 :- line = line.decode().rstrip(r'\n')
|
||||
- 10 :-
|
||||
+ 9:+ line = line.rstrip('\n')
|
||||
11, 10: yield line
|
||||
12, 11:
|
||||
- 13 :- process.wait()
|
||||
+ 12:+ process.communicate()
|
||||
14, 13:
|
||||
15, 14: if process.returncode != 0:
|
||||
16, 15: raise subprocess.CalledProcessError(process.returncode, cmd)
|
||||
```
|
||||
|
||||
Here the lines 3-5, 7-8, 11-12 and 14-16 are unmodified, but some of them are shifted. Of course, "white" lines that are not shown above are also unmodified. The API fill return the following data (visualized for simplicity, see Usage how to access the data programatically):
|
||||
```
|
||||
* pydiffchecker/helper.py->pydiffchecker/helper.py:
|
||||
1->1
|
||||
2->2
|
||||
3->3
|
||||
4->4
|
||||
5->5
|
||||
6->None
|
||||
7->7
|
||||
8->8
|
||||
9->None
|
||||
10->None
|
||||
11->10
|
||||
12->11
|
||||
13->None
|
||||
14->13
|
||||
15->14
|
||||
16->15
|
||||
```
|
||||
|
||||
### Usage
|
||||
```python
|
||||
from pydiffchecker.line_shift_checker import LineShiftChecker
|
||||
|
||||
line_shift_checker = LineShiftChecker('HEAD~', 'HEAD')
|
||||
all_shifted_lines = line_shift_checker.get_all_shifted_lines()
|
||||
|
||||
# Iterate through shifted lines
|
||||
for src_path, shifted_lines in all_shifted_lines.items():
|
||||
renamed_to = shifted_lines.dst_path
|
||||
for src_line_index, dst_line_index in shifted_lines:
|
||||
print(f'{src_line_index}->{dst_line_index}')
|
||||
|
||||
# Find if lines are shifted (and to where) in a file
|
||||
if 'your/file.cpp' in all_shifted_lines:
|
||||
shifted_lines = all_shifted_lines['your/file.cpp']
|
||||
renamed_to = shifted_lines.dst_path
|
||||
if 12 in shifted_lines:
|
||||
# line 12 was shifted, to where?
|
||||
shifted_to = shifted_lines[12]
|
||||
```
|
@ -3,7 +3,7 @@ from .version import get_version
|
||||
from .line_shift_checker import LineShiftChecker
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description='Diff checker')
|
||||
|
||||
parser.add_argument('-v',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import re
|
||||
from typing import List, Dict, Sized, Iterable
|
||||
from typing import List, Dict, Tuple, Sized, Iterable, Iterator
|
||||
from .helper import subprocess_readlines
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ class ShiftedLines(Sized, Iterable):
|
||||
return None
|
||||
return self.__lines[src_line_index]
|
||||
|
||||
def __iter__(self):
|
||||
def __iter__(self) -> 'Iterator[Tuple[int, int | None]]':
|
||||
return iter(self.__lines.items())
|
||||
|
||||
def __len__(self) -> int:
|
||||
@ -30,7 +30,7 @@ class ShiftedLines(Sized, Iterable):
|
||||
class LineShiftChecker:
|
||||
DIFF_BLOCK_REGEX = r'@@ -(\d+),(\d+) \+(\d+),(\d+) @@'
|
||||
|
||||
def __init__(self, revision_since, revision_until) -> None:
|
||||
def __init__(self, revision_since: str, revision_until: str) -> None:
|
||||
self.revision_since = revision_since
|
||||
self.revision_until = revision_until
|
||||
|
||||
@ -52,7 +52,7 @@ class LineShiftChecker:
|
||||
|
||||
return file_list
|
||||
|
||||
def __get_shifted_lines_in_file(self, file_info) -> ShiftedLines:
|
||||
def __get_shifted_lines_in_file(self, file_info: Dict[str, str]) -> ShiftedLines:
|
||||
process_output = subprocess_readlines(['git', 'diff',
|
||||
self.revision_since, self.revision_until, '--',
|
||||
file_info['src'], file_info['dst']])
|
||||
@ -98,6 +98,6 @@ class LineShiftChecker:
|
||||
|
||||
return shifted_lines
|
||||
|
||||
def __count_lines_in_source_file(self, file) -> int:
|
||||
def __count_lines_in_source_file(self, file: str) -> int:
|
||||
process_output = subprocess_readlines(['git', 'show', f'{self.revision_since}:{file}'])
|
||||
return sum(1 for _ in process_output)
|
||||
|
@ -1,7 +1,7 @@
|
||||
from importlib.metadata import version, PackageNotFoundError
|
||||
|
||||
|
||||
def get_version():
|
||||
def get_version() -> str:
|
||||
try:
|
||||
return version('pydiffchecker')
|
||||
except PackageNotFoundError:
|
||||
|
Loading…
x
Reference in New Issue
Block a user