Skip to content

Commit f8b9493

Browse files
committed
apply: test re-adding a file after removing it
Ensure that we can add a file back after it's been removed. Update the renamed/deleted validation in application to not apply to deltas that are adding files to support this.
1 parent 78580ad commit f8b9493

File tree

3 files changed

+63
-10
lines changed

3 files changed

+63
-10
lines changed

src/apply.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -458,23 +458,26 @@ static int apply_one(
458458
}
459459

460460
/*
461-
* We may be applying a second delta to an already seen file. If so,
462-
* use the already modified data in the postimage instead of the
463-
* content from the index or working directory. (Don't do this in
464-
* the case of a rename, which must be specified before additional
465-
* deltas since we apply deltas to the target filename.)
466-
*
467-
* Additionally, make sure that the file has not been deleted or renamed
468-
* out of the way; again, except in the rename case, since we support
469-
* renaming a single file into two target files.
461+
* Ensure that the file has not been deleted or renamed if we're
462+
* applying a modification delta.
470463
*/
471-
if (delta->status != GIT_DELTA_RENAMED) {
464+
if (delta->status != GIT_DELTA_RENAMED &&
465+
delta->status != GIT_DELTA_ADDED) {
472466
pos = git_strmap_lookup_index(removed_paths, delta->old_file.path);
473467
if (git_strmap_valid_index(removed_paths, pos)) {
474468
error = apply_err("path '%s' has been renamed or deleted", delta->old_file.path);
475469
goto done;
476470
}
471+
}
477472

473+
/*
474+
* We may be applying a second delta to an already seen file. If so,
475+
* use the already modified data in the postimage instead of the
476+
* content from the index or working directory. (Don't do this in
477+
* the case of a rename, which must be specified before additional
478+
* deltas since we apply deltas to the target filename.)
479+
*/
480+
if (delta->status != GIT_DELTA_RENAMED) {
478481
if ((error = git_reader_read(&pre_contents, &pre_id, &pre_filemode,
479482
postimage_reader, delta->old_file.path)) == 0) {
480483
skip_preimage = true;

tests/apply/apply_helpers.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,31 @@
394394
" Put into a pot three quarts of water, three onions cut small, one\n" \
395395
" spoonful of black pepper pounded, and two of salt, with two or three\n"
396396

397+
#define DIFF_DELETE_AND_READD_FILE \
398+
"diff --git a/asparagus.txt b/asparagus.txt\n" \
399+
"deleted file mode 100644\n" \
400+
"index f516580..0000000\n" \
401+
"--- a/asparagus.txt\n" \
402+
"+++ /dev/null\n" \
403+
"@@ -1,10 +0,0 @@\n" \
404+
"-ASPARAGUS SOUP!\n" \
405+
"-\n" \
406+
"-Take four large bunches of asparagus, scrape it nicely, cut off one inch\n" \
407+
"-of the tops, and lay them in water, chop the stalks and put them on the\n" \
408+
"-fire with a piece of bacon, a large onion cut up, and pepper and salt;\n" \
409+
"-add two quarts of water, boil them till the stalks are quite soft, then\n" \
410+
"-pulp them through a sieve, and strain the water to it, which must be put\n" \
411+
"-back in the pot; put into it a chicken cut up, with the tops of\n" \
412+
"-asparagus which had been laid by, boil it until these last articles are\n" \
413+
"-sufficiently done, thicken with flour, butter and milk, and serve it up.\n" \
414+
"diff --git a/asparagus.txt b/asparagus.txt\n" \
415+
"new file mode 100644\n" \
416+
"index 0000000..2dc7f8b\n" \
417+
"--- /dev/null\n" \
418+
"+++ b/asparagus.txt\n" \
419+
"@@ -0,0 +1 @@\n" \
420+
"+New file.\n" \
421+
397422
struct iterator_compare_data {
398423
struct merge_index_entry *expected;
399424
size_t cnt;

tests/apply/both.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,3 +698,28 @@ void test_apply_both__cant_modify_source_path_after_rename(void)
698698

699699
git_diff_free(diff);
700700
}
701+
702+
void test_apply_both__readd_deleted_file(void)
703+
{
704+
git_diff *diff;
705+
706+
struct merge_index_entry both_expected[] = {
707+
{ 0100644, "2dc7f8b24ba27f3888368bd180df03ff4c6c6fab", 0, "asparagus.txt" },
708+
{ 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" },
709+
{ 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" },
710+
{ 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" },
711+
{ 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" },
712+
{ 0100644, "94d2c01087f48213bd157222d54edfefd77c9bba", 0, "veal.txt" }
713+
};
714+
size_t both_expected_cnt = sizeof(both_expected) /
715+
sizeof(struct merge_index_entry);
716+
717+
cl_git_pass(git_diff_from_buffer(&diff, DIFF_DELETE_AND_READD_FILE,
718+
strlen(DIFF_DELETE_AND_READD_FILE)));
719+
cl_git_pass(git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, NULL));
720+
721+
validate_apply_index(repo, both_expected, both_expected_cnt);
722+
validate_apply_workdir(repo, both_expected, both_expected_cnt);
723+
724+
git_diff_free(diff);
725+
}

0 commit comments

Comments
 (0)