Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/applier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ static LineNumber write_define_hunk(LineWriter& output, const Hunk& hunk, const

for (const auto& patch_line : hunk.lines) {
if (patch_line.operation == ' ') {
if (line_number >= lines.size())
continue;

const auto& line = lines.at(line_number);
++line_number;
if (define_state != DefineState::Outside) {
Expand All @@ -105,6 +108,9 @@ static LineNumber write_define_hunk(LineWriter& output, const Hunk& hunk, const
}
output << patch_line.line;
} else if (patch_line.operation == '-') {
if (line_number >= lines.size())
continue;

const auto& line = lines.at(line_number);
++line_number;

Expand Down Expand Up @@ -136,12 +142,16 @@ static LineNumber write_hunk(LineWriter& output, const Hunk& hunk, const Locatio

for (const auto& patch_line : hunk.lines) {
if (patch_line.operation == ' ') {
if (line_number >= lines.size())
continue;

output << lines.at(line_number);
++line_number;
} else if (patch_line.operation == '+') {
output << patch_line.line;
} else if (patch_line.operation == '-') {
++line_number;
if (line_number < lines.size())
++line_number;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/locator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ Location locate_hunk(const std::vector<Line>& content, const Hunk& hunk, bool ig
if (hunk.old_file_range.number_of_lines == 0) {
if (hunk.old_file_range.start_line == 0 && !content.empty())
return {};
return { offset_guess, 0, 0 };
const auto end = static_cast<LineNumber>(content.size());
return { std::min(std::max<LineNumber>(offset_guess, 0), end), 0, 0 };
}

LineNumber patch_prefix_content = 0;
Expand Down
82 changes: 82 additions & 0 deletions tests/test_applier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,88 @@ int another()
EXPECT_FILE_EQ("a.rej", patch);
}

static void write_context_past_end_of_file_patch()
{
Patch::File file("diff.patch", std::ios_base::out);
file << R"(--- a
+++ a
@@ -1,5 +1,5 @@
a
-b
+B
c
ZZZ
QQQ
)";
file.close();
}

static void write_three_line_file()
{
Patch::File file("a", std::ios_base::out);
file << "a\nb\nc\n";
file.close();
}

COMPAT_TEST(applier_insertion_past_end_of_file)
{
{
Patch::File file("diff.patch", std::ios_base::out);
file << R"(--- a
+++ a
@@ -100,0 +100,1 @@
+inserted
)";
file.close();
}

write_three_line_file();

Process process(patch_path, { patch_path, "--force", "-i", "diff.patch", nullptr });

EXPECT_EQ(process.stdout_data(), "patching file a\n");
EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);
EXPECT_FILE_EQ("a", "a\nb\nc\ninserted\n");
}

COMPAT_TEST(applier_fuzz_matches_context_past_end_of_file)
{
write_context_past_end_of_file_patch();
write_three_line_file();

Process process(patch_path, { patch_path, "--force", "--fuzz=3", "-i", "diff.patch", nullptr });

EXPECT_EQ(process.stdout_data(), R"(patching file a
Hunk #1 succeeded at 1 with fuzz 2.
)");
EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);
EXPECT_FILE_EQ("a", "a\nB\nc\n");
}

COMPAT_TEST(applier_fuzz_matches_context_past_end_of_file_with_define)
{
write_context_past_end_of_file_patch();
write_three_line_file();

Process process(patch_path, { patch_path, "--force", "--fuzz=3", "-D", "FOO", "-i", "diff.patch", nullptr });

EXPECT_EQ(process.stdout_data(), R"(patching file a
Hunk #1 succeeded at 1 with fuzz 2.
)");
EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);
EXPECT_FILE_EQ("a", R"(a
#ifndef FOO
b
#else
B
#endif
c
)");
}

COMPAT_TEST(applier_end_of_file_hunk_requires_fuzz_when_no_longer_at_end)
{
const std::string patch = R"(--- a
Expand Down
Loading