-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathdiff.py
More file actions
76 lines (59 loc) · 2.68 KB
/
diff.py
File metadata and controls
76 lines (59 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import difflib
import libcst as cst
def create_diff(original_lines: list[str], new_lines: list[str]) -> str:
diff_lines = list(difflib.unified_diff(original_lines, new_lines))
return difflines_to_str(diff_lines)
def create_diff_from_tree(original_tree: cst.Module, new_tree: cst.Module) -> str:
"""
Create a diff between the original and output trees.
"""
return create_diff(
original_tree.code.splitlines(keepends=True),
new_tree.code.splitlines(keepends=True),
)
def create_diff_and_linenums(
original_lines: list[str], new_lines: list[str]
) -> tuple[str, list[int]]:
diff_lines = list(difflib.unified_diff(original_lines, new_lines))
return difflines_to_str(diff_lines), calc_line_num_changes(diff_lines)
def calc_line_num_changes(diff_lines: list[str]) -> list[int]:
"""
Calculates the line numbers changed from a list of diff lines
Returns a list with unique elements.
"""
if not diff_lines:
return []
changed_line_nums: list[int] = []
current_line_number = 0
original_line_number = 0
for line in diff_lines:
if line.startswith("@@"):
# Extract the starting line number for the updated file from the diff metadata.
# The format is @@ -x,y +a,b @@, where a is the starting line number in the updated file.
start_line_original, start_line_updated = line.split(" ")[1:3]
original_line_number = int(start_line_original.split(",")[0][1:]) - 1
current_line_number = int(start_line_updated.split(",")[0][1:]) - 1
elif line.startswith("+"):
# Increment line number for each line in the updated file
current_line_number += 1
if not line.startswith("+++"): # Ignore the diff metadata lines
changed_line_nums.append(current_line_number)
elif line.startswith("-"):
# Increment line number for each line in the original file
original_line_number += 1
if not line.startswith("---"): # Ignore the diff metadata lines
changed_line_nums.append(original_line_number)
else:
# Increment line numbers for unchanged/context lines
original_line_number += 1
current_line_number += 1
return list(set(changed_line_nums))
def difflines_to_str(diff_lines: list[str]) -> str:
if not diff_lines:
return ""
# All but the last diff line should end with a newline
# The last diff line should be preserved as-is (with or without a newline)
diff_lines = [
line if line.endswith("\n") else line + "\n" for line in diff_lines[:-1]
] + [diff_lines[-1]]
return "".join(diff_lines)