Skip to content

Commit

Permalink
Merge branch 'mk/maint-apply-swap' into maint
Browse files Browse the repository at this point in the history
* mk/maint-apply-swap:
  tests: make test-apply-criss-cross-rename more robust
  builtin-apply: keep information about files to be deleted
  tests: test applying criss-cross rename patch
  • Loading branch information
Junio C Hamano committed May 3, 2009
2 parents 00473fd + f058386 commit c2eae0a
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 7 deletions.
53 changes: 46 additions & 7 deletions builtin-apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -2271,6 +2271,25 @@ static struct patch *in_fn_table(const char *name)
return NULL;
}

/*
* item->util in the filename table records the status of the path.
* Usually it points at a patch (whose result records the contents
* of it after applying it), but it could be PATH_WAS_DELETED for a
* path that a previously applied patch has already removed.
*/
#define PATH_TO_BE_DELETED ((struct patch *) -2)
#define PATH_WAS_DELETED ((struct patch *) -1)

static int to_be_deleted(struct patch *patch)
{
return patch == PATH_TO_BE_DELETED;
}

static int was_deleted(struct patch *patch)
{
return patch == PATH_WAS_DELETED;
}

static void add_to_fn_table(struct patch *patch)
{
struct string_list_item *item;
Expand All @@ -2291,7 +2310,22 @@ static void add_to_fn_table(struct patch *patch)
*/
if ((patch->new_name == NULL) || (patch->is_rename)) {
item = string_list_insert(patch->old_name, &fn_table);
item->util = (struct patch *) -1;
item->util = PATH_WAS_DELETED;
}
}

static void prepare_fn_table(struct patch *patch)
{
/*
* store information about incoming file deletion
*/
while (patch) {
if ((patch->new_name == NULL) || (patch->is_rename)) {
struct string_list_item *item;
item = string_list_insert(patch->old_name, &fn_table);
item->util = PATH_TO_BE_DELETED;
}
patch = patch->next;
}
}

Expand All @@ -2304,8 +2338,8 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
struct patch *tpatch;

if (!(patch->is_copy || patch->is_rename) &&
((tpatch = in_fn_table(patch->old_name)) != NULL)) {
if (tpatch == (struct patch *) -1) {
(tpatch = in_fn_table(patch->old_name)) != NULL && !to_be_deleted(tpatch)) {
if (was_deleted(tpatch)) {
return error("patch %s has been renamed/deleted",
patch->old_name);
}
Expand Down Expand Up @@ -2399,17 +2433,19 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
assert(patch->is_new <= 0);

if (!(patch->is_copy || patch->is_rename) &&
(tpatch = in_fn_table(old_name)) != NULL) {
if (tpatch == (struct patch *) -1) {
(tpatch = in_fn_table(old_name)) != NULL && !to_be_deleted(tpatch)) {
if (was_deleted(tpatch))
return error("%s: has been deleted/renamed", old_name);
}
st_mode = tpatch->new_mode;
} else if (!cached) {
stat_ret = lstat(old_name, st);
if (stat_ret && errno != ENOENT)
return error("%s: %s", old_name, strerror(errno));
}

if (to_be_deleted(tpatch))
tpatch = NULL;

if (check_index && !tpatch) {
int pos = cache_name_pos(old_name, strlen(old_name));
if (pos < 0) {
Expand Down Expand Up @@ -2471,6 +2507,7 @@ static int check_patch(struct patch *patch)
const char *new_name = patch->new_name;
const char *name = old_name ? old_name : new_name;
struct cache_entry *ce = NULL;
struct patch *tpatch;
int ok_if_exists;
int status;

Expand All @@ -2481,7 +2518,8 @@ static int check_patch(struct patch *patch)
return status;
old_name = patch->old_name;

if (in_fn_table(new_name) == (struct patch *) -1)
if ((tpatch = in_fn_table(new_name)) &&
(was_deleted(tpatch) || to_be_deleted(tpatch)))
/*
* A type-change diff is always split into a patch to
* delete old, immediately followed by a patch to
Expand Down Expand Up @@ -2533,6 +2571,7 @@ static int check_patch_list(struct patch *patch)
{
int err = 0;

prepare_fn_table(patch);
while (patch) {
if (apply_verbosely)
say_patch_name(stderr,
Expand Down
66 changes: 66 additions & 0 deletions t/t4130-apply-criss-cross-rename.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/sh

test_description='git apply handling criss-cross rename patch.'
. ./test-lib.sh

create_file() {
cnt=0
while test $cnt -le 100
do
cnt=$(($cnt + 1))
echo "$2" >> "$1"
done
}

test_expect_success 'setup' '
create_file file1 "File1 contents" &&
create_file file2 "File2 contents" &&
create_file file3 "File3 contents" &&
git add file1 file2 file3 &&
git commit -m 1
'

test_expect_success 'criss-cross rename' '
mv file1 tmp &&
mv file2 file1 &&
mv tmp file2 &&
cp file1 file1-swapped &&
cp file2 file2-swapped
'

test_expect_success 'diff -M -B' '
git diff -M -B > diff &&
git reset --hard
'

test_expect_success 'apply' '
git apply diff &&
test_cmp file1 file1-swapped &&
test_cmp file2 file2-swapped
'

test_expect_success 'criss-cross rename' '
git reset --hard &&
mv file1 tmp &&
mv file2 file1 &&
mv file3 file2
mv tmp file3 &&
cp file1 file1-swapped &&
cp file2 file2-swapped &&
cp file3 file3-swapped
'

test_expect_success 'diff -M -B' '
git diff -M -B > diff &&
git reset --hard
'

test_expect_success 'apply' '
git apply diff &&
test_cmp file1 file1-swapped &&
test_cmp file2 file2-swapped &&
test_cmp file3 file3-swapped
'

test_done

0 comments on commit c2eae0a

Please sign in to comment.