Add support for rewriting hunks if only specific lines match
This commit is contained in:
parent
56d1f03c83
commit
8ebcba623e
2 changed files with 87 additions and 22 deletions
|
|
@ -4,9 +4,9 @@ import re
|
|||
import sys
|
||||
|
||||
|
||||
def should_include_change(
|
||||
def filter_change_block(
|
||||
change_lines: list[str], search: str, replace: str
|
||||
) -> bool:
|
||||
) -> tuple[list[str] | None, bool]:
|
||||
removed_lines = []
|
||||
added_lines = []
|
||||
phase = "minus"
|
||||
|
|
@ -23,33 +23,66 @@ def should_include_change(
|
|||
added_lines.append(line[1:])
|
||||
continue
|
||||
raise ValueError("Unexpected non-change line in change block.")
|
||||
|
||||
transformed_removed = [
|
||||
re.sub(search, replace, line) for line in removed_lines
|
||||
]
|
||||
return transformed_removed == added_lines
|
||||
if transformed_removed == added_lines:
|
||||
return change_lines, False
|
||||
|
||||
if len(removed_lines) != len(added_lines):
|
||||
return None, True
|
||||
|
||||
kept_lines = []
|
||||
for removed, added in zip(removed_lines, added_lines):
|
||||
if re.sub(search, replace, removed) == added:
|
||||
kept_lines.append(f"-{removed}")
|
||||
kept_lines.append(f"+{added}")
|
||||
else:
|
||||
kept_lines.append(f" {removed}")
|
||||
|
||||
if not kept_lines:
|
||||
return None, True
|
||||
|
||||
return kept_lines, True
|
||||
|
||||
|
||||
def should_include_hunk(hunk_text: str, search: str, replace: str) -> bool:
|
||||
lines = hunk_text.splitlines()
|
||||
if not lines:
|
||||
return True
|
||||
def filter_hunk(
|
||||
hunk_lines: list[str], search: str, replace: str
|
||||
) -> tuple[list[str] | None, bool]:
|
||||
if not hunk_lines:
|
||||
return None, False
|
||||
|
||||
change = []
|
||||
for line in lines[1:]:
|
||||
header = hunk_lines[0]
|
||||
body = hunk_lines[1:]
|
||||
output_body: list[str] = []
|
||||
left_out = False
|
||||
|
||||
i = 0
|
||||
while i < len(body):
|
||||
line = body[i]
|
||||
if line.startswith(("+", "-")):
|
||||
change.append(line)
|
||||
block = []
|
||||
while i < len(body) and body[i].startswith(("+", "-")):
|
||||
block.append(body[i])
|
||||
i += 1
|
||||
kept_block, block_left_out = filter_change_block(
|
||||
block, search, replace
|
||||
)
|
||||
if kept_block:
|
||||
output_body.extend(kept_block)
|
||||
else:
|
||||
left_out = True
|
||||
if block_left_out:
|
||||
left_out = True
|
||||
continue
|
||||
output_body.append(line)
|
||||
i += 1
|
||||
|
||||
if change:
|
||||
if not should_include_change(change, search, replace):
|
||||
return False
|
||||
change = []
|
||||
if not any(line.startswith(("+", "-")) for line in output_body):
|
||||
return None, True
|
||||
|
||||
if change:
|
||||
if not should_include_change(change, search, replace):
|
||||
return False
|
||||
|
||||
return True
|
||||
return [header] + output_body, left_out
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
|
@ -97,11 +130,15 @@ def main() -> None:
|
|||
|
||||
kept_hunks = []
|
||||
for hunk_lines in section["hunks"]:
|
||||
hunk_text = "".join(hunk_lines)
|
||||
if should_include_hunk(hunk_text, search, replace):
|
||||
kept_hunks.append(hunk_lines)
|
||||
filtered, hunk_left_out = filter_hunk(
|
||||
hunk_lines, search, replace
|
||||
)
|
||||
if filtered:
|
||||
kept_hunks.append(filtered)
|
||||
else:
|
||||
left_out = True
|
||||
if hunk_left_out:
|
||||
left_out = True
|
||||
|
||||
if not kept_hunks:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -128,3 +128,31 @@ setup() {
|
|||
assert_success
|
||||
assert_output "$(cat "$BATS_TEST_TMPDIR/diff")"
|
||||
}
|
||||
|
||||
@test "keeps only matching line in a consecutive change block" {
|
||||
cat >"$BATS_TEST_TMPDIR/old" <<-'EOF'
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
EOF
|
||||
sed \
|
||||
-e 's/foo/foo_changed/' \
|
||||
-e 's/bar/bar_changed/' \
|
||||
"$BATS_TEST_TMPDIR/old" >"$BATS_TEST_TMPDIR/new"
|
||||
sed 's/foo/foo_changed/' "$BATS_TEST_TMPDIR/old" \
|
||||
>"$BATS_TEST_TMPDIR/new_kept"
|
||||
|
||||
git diff --no-index "$BATS_TEST_TMPDIR/old" "$BATS_TEST_TMPDIR/new" \
|
||||
>"$BATS_TEST_TMPDIR/diff_full" || true
|
||||
git diff --no-index "$BATS_TEST_TMPDIR/old" "$BATS_TEST_TMPDIR/new_kept" \
|
||||
>"$BATS_TEST_TMPDIR/diff_expected" || true
|
||||
|
||||
run mechanicaldiff.py foo foo_changed <"$BATS_TEST_TMPDIR/diff_full"
|
||||
assert_failure
|
||||
expected="$(sed \
|
||||
-e 's/new_kept/new/g' \
|
||||
-e '/^index /d' \
|
||||
"$BATS_TEST_TMPDIR/diff_expected")"
|
||||
output_normalized="$(printf '%s\n' "$output" | sed -e '/^index /d')"
|
||||
assert_equal "$expected" "$output_normalized"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue