You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Generate a list of FileChanges from the output of _some_ git diff commands.
57
57
Not all outputs from `git diff` are supported (ex: renames), see set of args in [Git._capture_diff_lines](dda.tools.git.Git._capture_diff_lines) method.
58
-
Accepts a string or a list of lines.
59
58
"""
60
-
ifisinstance(diff_output, str):
61
-
diff_output=diff_output.strip().splitlines()
62
-
63
-
iflen(diff_output) ==0:
64
-
return
65
-
66
-
line_iterator=iter(diff_output)
67
-
68
-
current_file: Path|None=None
69
-
current_type: ChangeType|None=None
70
-
current_patch_lines: list[str] = []
71
-
iterator_exhausted=False
72
-
73
-
try:
74
-
line=next(line_iterator)
75
-
whileTrue:
76
-
# Start processing a new file - the line looks like `diff --git a/<path> b/<path>`
77
-
ifnotline.startswith("diff --git "):
78
-
msg=f"Unexpected line in git diff output: {line}"
79
-
raiseValueError(msg)
80
-
81
-
# Go forward until we find the 'old file' line (---)
82
-
whilenotline.startswith("--- "):
83
-
try:
84
-
line=next(line_iterator)
85
-
exceptStopIteration:
86
-
msg="Unexpected end of git diff output while looking for --- line"
87
-
raiseValueError(msg) # noqa: B904
88
-
89
-
# When we get here, we are on the --- line
90
-
# It should always be followed by a +++ line
91
-
old_file_line=line
92
-
93
-
try:
94
-
new_file_line=next(line_iterator)
95
-
exceptStopIteration:
96
-
msg="Unexpected end of git diff output while looking for +++ line"
97
-
raiseValueError(msg) # noqa: B904
98
-
ifnotnew_file_line.startswith("+++ "):
99
-
msg=f"Unexpected line in git diff output, expected +++ line: {new_file_line}"
100
-
raiseValueError(msg)
101
-
102
-
old_file_path=old_file_line[4:].strip()
103
-
new_file_path=new_file_line[4:].strip()
104
-
105
-
ifold_file_path=="/dev/null":
106
-
current_type=ChangeType.ADDED
107
-
current_file=Path(new_file_path)
108
-
elifnew_file_path=="/dev/null":
109
-
current_type=ChangeType.DELETED
110
-
current_file=Path(old_file_path)
111
-
elifold_file_path==new_file_path:
112
-
current_type=ChangeType.MODIFIED
113
-
current_file=Path(new_file_path)
114
-
else:
115
-
msg=f"Unexpected file paths in git diff output: {old_file_path} -> {new_file_path} - this indicates a rename which we do not support"
116
-
raiseValueError(
117
-
msg,
118
-
)
119
-
120
-
# Now, we should be at the start of the patch hunks (lines starting with @@)
121
-
line=next(line_iterator)
122
-
ifnotline.startswith("@@ "):
123
-
msg=f"Unexpected line in git diff output, expected hunk start: {line}"
124
-
raiseValueError(msg)
125
-
# Collect hunk lines, i.e. lines starting with @@, +, -, or \ (\ is for the "no newline at end of file" message that can appear)
126
-
127
-
whileline.startswith(("@@ ", "+", "-", "\\")):
128
-
current_patch_lines.append(line)
129
-
try:
130
-
line=next(line_iterator)
131
-
exceptStopIteration:
132
-
# Just break out of the loop, we will handle yielding below
133
-
# Set a flag to indicate we reached the end of the iterator
134
-
iterator_exhausted=True
135
-
break
136
-
137
-
# Yield the file we were building now that we have reached the end of its patch
138
-
yieldcls(
139
-
file=current_file,
140
-
type=current_type,
141
-
binary=False, # TODO: Support binaries
142
-
patch="\n".join(current_patch_lines),
143
-
)
144
-
current_file=None
145
-
current_type=None
146
-
current_patch_lines= []
147
-
148
-
ifiterator_exhausted:
149
-
return
150
-
151
-
exceptStopIteration:
152
-
msg="Unexpected end of git diff output while parsing"
0 commit comments