fix(picker): status picker crash on renamed files (#139)

This commit is contained in:
Björn Steinbrink
2026-07-10 12:45:57 +02:00
committed by GitHub
parent b7c17af6d2
commit b5fe23351a
2 changed files with 75 additions and 16 deletions
+12 -16
View File
@@ -75,24 +75,20 @@ function M.parse_file_info_from_status_line(line)
line = vim.trim(line)
-- Handle renamed files in nested path form:
-- R dir/{old_name => new_name}
local dir_path, old_name, new_name = line:match("^R%s+(.*)/{(.*)%s=>%s([^}]+)}$")
if dir_path and old_name and new_name then
return {
old_path = dir_path .. "/" .. old_name,
new_path = dir_path .. "/" .. new_name,
is_rename = true,
}
end
-- Handle renamed files in top-level brace form:
-- Handle renamed/copied files with a brace group anywhere in the path,
-- where either side may be empty:
-- R {old_name => new_name}
local old_top, new_top = line:match("^R%s+{(.-)%s=>%s([^}]+)}$")
if old_top and new_top then
-- R dir/{old_name => new_name}/rest
-- R dir/{ => new_dir}/rest
local prefix, old_part, new_part, suffix = line:match("^[RC]%s+(.-){(.-) => (.-)}(.*)$")
if prefix then
local function join(part)
local path = (prefix .. part .. suffix):gsub("//", "/"):gsub("^/", "")
return path
end
return {
old_path = old_top,
new_path = new_top,
old_path = join(old_part),
new_path = join(new_part),
is_rename = true,
}
end
+63
View File
@@ -432,6 +432,69 @@ run_test("scan_conflict_sections: empty file yields empty list", function()
assert_table_equals({}, parser.scan_conflict_sections("a.txt", "/abs/a.txt", {}))
end)
print("\n=== Running parse_file_info_from_status_line tests ===\n")
run_test("status line: parses regular modified file", function()
assert_table_equals(
{ old_path = "src/main.rs", new_path = "src/main.rs", is_rename = false },
parser.parse_file_info_from_status_line("M src/main.rs")
)
end)
run_test("status line: parses top-level brace rename", function()
assert_table_equals(
{ old_path = "old.txt", new_path = "new.txt", is_rename = true },
parser.parse_file_info_from_status_line("R {old.txt => new.txt}")
)
end)
run_test("status line: parses rename with brace group at end", function()
assert_table_equals(
{ old_path = "dir/old.txt", new_path = "dir/new.txt", is_rename = true },
parser.parse_file_info_from_status_line("R dir/{old.txt => new.txt}")
)
end)
run_test("status line: parses rename with brace group mid-path", function()
assert_table_equals({
old_path = "Business/OAuth/Exceptions/OAuth2RefreshTokenExpiredException.php",
new_path = "Business/OAuth2/Exceptions/OAuth2RefreshTokenExpiredException.php",
is_rename = true,
}, parser.parse_file_info_from_status_line(
"R Business/{OAuth => OAuth2}/Exceptions/OAuth2RefreshTokenExpiredException.php"
))
end)
run_test("status line: parses rename with empty old side mid-path", function()
assert_table_equals({
old_path = "Business/Exceptions/Error.php",
new_path = "Business/OAuth2/Sub/Exceptions/Error.php",
is_rename = true,
}, parser.parse_file_info_from_status_line("R Business/{ => OAuth2/Sub}/Exceptions/Error.php"))
end)
run_test("status line: parses rename with empty new side mid-path", function()
assert_table_equals({
old_path = "Business/OAuth/Exceptions/Error.php",
new_path = "Business/Exceptions/Error.php",
is_rename = true,
}, parser.parse_file_info_from_status_line("R Business/{OAuth => }/Exceptions/Error.php"))
end)
run_test("status line: parses rename with empty side at top level", function()
assert_table_equals(
{ old_path = "a.txt", new_path = "dir/a.txt", is_rename = true },
parser.parse_file_info_from_status_line("R { => dir}/a.txt")
)
end)
run_test("status line: parses copied file with brace group", function()
assert_table_equals(
{ old_path = "dir/old.txt", new_path = "dir/new.txt", is_rename = true },
parser.parse_file_info_from_status_line("C dir/{old.txt => new.txt}")
)
end)
print("\n=== Running parse_default_cmd tests ===\n")
run_test("parse_default_cmd: parses config list array output", function()