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
18 changes: 12 additions & 6 deletions src/patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,29 +687,35 @@ static int process_patches(const Options& options, DeferredWriter& deferred_writ
} else {
bool write_to_file = !options.dry_run;

const bool make_backup = options.save_backup
|| (!result.all_hunks_applied_perfectly && !result.was_skipped && options.backup_if_mismatch == Options::OptionalBool::Yes);

// Clean up the file if it looks like it was removed.
// NOTE: we check for file size for the degenerate case that the file is a removal, but has nothing left.
if (options.remove_empty_files == Options::OptionalBool::Yes
&& (patch.operation == Operation::Delete || (patch.format == Format::Ed && tmp_out_file.size() == 0))) {
if (tmp_out_file.size() == 0) {
if (!options.dry_run)
if (!options.dry_run) {
if (make_backup)
backup.make_backup_for(output_file);
remove_file_and_empty_parent_folders(output_file);
}
write_to_file = false;
} else {
out << "Not deleting file " << output_file << " as content differs from patch\n";
had_failure = true;
}
}

if (write_to_file) {
const bool make_backup = options.save_backup
|| (!result.all_hunks_applied_perfectly && !result.was_skipped && options.backup_if_mismatch == Options::OptionalBool::Yes);
if (write_to_file)
write_patched_result_to_file(patch, output_file, input_permissions, mode, deferred_writer, tmp_out_file, backup, make_backup);
}

if (result.failed_hunks == 0) {
if (write_to_file && patch.operation == Operation::Rename)
if (write_to_file && patch.operation == Operation::Rename) {
if (make_backup)
backup.make_backup_for(file_to_patch);
remove_file_and_empty_parent_folders(file_to_patch);
}
}
}
}
Expand Down
121 changes: 121 additions & 0 deletions tests/test_basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,127 @@ rename to b
EXPECT_FILE_EQ("b", to_patch);
EXPECT_FILE_EQ("b.orig", "");
EXPECT_FALSE(Patch::filesystem::exists("a"));
EXPECT_FILE_EQ("a.orig", to_patch);
}

COMPAT_TEST(backup_of_removed_file)
{
{
Patch::File file("diff.patch", std::ios_base::out);

file << R"(--- gone.txt
+++ /dev/null
@@ -1 +0,0 @@
-content to lose
)";
file.close();
}

const std::string to_patch = "content to lose\n";
{
Patch::File file("gone.txt", std::ios_base::out);
file << to_patch;
file.close();
}

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

EXPECT_EQ(process.stdout_data(), "patching file gone.txt\n");
EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);

// The file is removed, so the backup is the only copy left of its content.
EXPECT_FALSE(Patch::filesystem::exists("gone.txt"));
EXPECT_FILE_EQ("gone.txt.orig", to_patch);
}

COMPAT_TEST(backup_of_removed_file_in_subdirectory)
{
{
Patch::File file("diff.patch", std::ios_base::out);

file << R"(--- sub/nested.txt
+++ /dev/null
@@ -1 +0,0 @@
-content to lose
)";
file.close();
}

const std::string to_patch = "content to lose\n";
{
Patch::filesystem::create_directory("sub");
Patch::File file("sub/nested.txt", std::ios_base::out);
file << to_patch;
file.close();
}

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

EXPECT_EQ(process.stdout_data(), "patching file sub/nested.txt\n");
EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);

EXPECT_FALSE(Patch::filesystem::exists("sub/nested.txt"));
EXPECT_FILE_EQ("sub/nested.txt.orig", to_patch);
}

COMPAT_TEST(no_backup_of_removed_file_without_flag)
{
{
Patch::File file("diff.patch", std::ios_base::out);

file << R"(--- gone.txt
+++ /dev/null
@@ -1 +0,0 @@
-content to lose
)";
file.close();
}

{
Patch::File file("gone.txt", std::ios_base::out);
file << "content to lose\n";
file.close();
}

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

EXPECT_EQ(process.stdout_data(), "patching file gone.txt\n");
EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);

EXPECT_FALSE(Patch::filesystem::exists("gone.txt"));
EXPECT_FALSE(Patch::filesystem::exists("gone.txt.orig"));
}

COMPAT_TEST(no_backup_of_removed_file_for_dry_run)
{
{
Patch::File file("diff.patch", std::ios_base::out);

file << R"(--- gone.txt
+++ /dev/null
@@ -1 +0,0 @@
-content to lose
)";
file.close();
}

const std::string to_patch = "content to lose\n";
{
Patch::File file("gone.txt", std::ios_base::out);
file << to_patch;
file.close();
}

Process process(patch_path, { patch_path, "--batch", "-p0", "-b", "--dry-run", "-i", "diff.patch", nullptr });

EXPECT_EQ(process.stderr_data(), "");
EXPECT_EQ(process.return_code(), 0);

EXPECT_FILE_EQ("gone.txt", to_patch);
EXPECT_FALSE(Patch::filesystem::exists("gone.txt.orig"));
}

COMPAT_TEST(backup_on_top_of_existing_file)
Expand Down
Loading