Skip to content

Commit 56185f4

Browse files
author
Junio C Hamano
committed
git-apply: require -p<n> when working in a subdirectory.
git-apply running inside a subdirectory, with or without --index, used to always assume that the patch is formatted in such a way to apply with -p1 from the toplevel, but it is more useful and consistent with the use of "GNU patch -p1" if it defaulted to assume that its input is meant to apply at the level it is invoked in. This changes the behaviour. It used to be that the patch generated this way would apply without any trick: edit Documentation/Makefile git diff >patch.file cd Documentation git apply ../patch.file You need to give an explicit -p2 to git-apply now. On the other hand, if you got a patch from somebody else who did not follow "patch is to apply from the top with -p1" convention, the input patch would start with: diff -u Makefile.old Makefile --- Makefile.old +++ Makefile and in such a case, you can apply it with: git apply -p0 patch.file Signed-off-by: Junio C Hamano <[email protected]>
1 parent aea1945 commit 56185f4

File tree

2 files changed

+46
-28
lines changed

2 files changed

+46
-28
lines changed

builtin-apply.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ static int name_terminate(const char *name, int namelen, int c, int terminate)
238238
return 1;
239239
}
240240

241-
static char * find_name(const char *line, char *def, int p_value, int terminate)
241+
static char *find_name(const char *line, char *def, int p_value, int terminate)
242242
{
243243
int len;
244244
const char *start = line;
@@ -362,7 +362,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
362362
static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
363363
{
364364
if (!orig_name && !isnull)
365-
return find_name(line, NULL, 1, TERM_TAB);
365+
return find_name(line, NULL, p_value, TERM_TAB);
366366

367367
if (orig_name) {
368368
int len;
@@ -372,7 +372,7 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
372372
len = strlen(name);
373373
if (isnull)
374374
die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
375-
another = find_name(line, NULL, 1, TERM_TAB);
375+
another = find_name(line, NULL, p_value, TERM_TAB);
376376
if (!another || memcmp(another, name, len))
377377
die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
378378
free(another);
@@ -427,28 +427,28 @@ static int gitdiff_newfile(const char *line, struct patch *patch)
427427
static int gitdiff_copysrc(const char *line, struct patch *patch)
428428
{
429429
patch->is_copy = 1;
430-
patch->old_name = find_name(line, NULL, 0, 0);
430+
patch->old_name = find_name(line, NULL, p_value-1, 0);
431431
return 0;
432432
}
433433

434434
static int gitdiff_copydst(const char *line, struct patch *patch)
435435
{
436436
patch->is_copy = 1;
437-
patch->new_name = find_name(line, NULL, 0, 0);
437+
patch->new_name = find_name(line, NULL, p_value-1, 0);
438438
return 0;
439439
}
440440

441441
static int gitdiff_renamesrc(const char *line, struct patch *patch)
442442
{
443443
patch->is_rename = 1;
444-
patch->old_name = find_name(line, NULL, 0, 0);
444+
patch->old_name = find_name(line, NULL, p_value-1, 0);
445445
return 0;
446446
}
447447

448448
static int gitdiff_renamedst(const char *line, struct patch *patch)
449449
{
450450
patch->is_rename = 1;
451-
patch->new_name = find_name(line, NULL, 0, 0);
451+
patch->new_name = find_name(line, NULL, p_value-1, 0);
452452
return 0;
453453
}
454454

@@ -2499,15 +2499,26 @@ static int use_patch(struct patch *p)
24992499
return 0;
25002500
x = x->next;
25012501
}
2502-
if (0 < prefix_length) {
2503-
int pathlen = strlen(pathname);
2504-
if (pathlen <= prefix_length ||
2505-
memcmp(prefix, pathname, prefix_length))
2506-
return 0;
2507-
}
25082502
return 1;
25092503
}
25102504

2505+
static char *prefix_one(char *name)
2506+
{
2507+
if (!name)
2508+
return name;
2509+
return xstrdup(prefix_filename(prefix, prefix_length, name));
2510+
}
2511+
2512+
static void prefix_patches(struct patch *p)
2513+
{
2514+
if (!prefix)
2515+
return;
2516+
for ( ; p; p = p->next) {
2517+
p->new_name = prefix_one(p->new_name);
2518+
p->old_name = prefix_one(p->old_name);
2519+
}
2520+
}
2521+
25112522
static int apply_patch(int fd, const char *filename, int inaccurate_eof)
25122523
{
25132524
unsigned long offset, size;
@@ -2530,11 +2541,14 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
25302541
break;
25312542
if (apply_in_reverse)
25322543
reverse_patches(patch);
2544+
if (prefix)
2545+
prefix_patches(patch);
25332546
if (use_patch(patch)) {
25342547
patch_stats(patch);
25352548
*listp = patch;
25362549
listp = &patch->next;
2537-
} else {
2550+
}
2551+
else {
25382552
/* perhaps free it a bit better? */
25392553
free(patch);
25402554
skipped_patch++;

t/t4119-apply-config.sh

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,22 @@ test_description='git-apply --whitespace=strip and configuration file.
1010
. ./test-lib.sh
1111

1212
test_expect_success setup '
13-
echo A >file1 &&
14-
cp file1 saved &&
15-
git add file1 &&
16-
echo "B " >file1 &&
13+
mkdir sub &&
14+
echo A >sub/file1 &&
15+
cp sub/file1 saved &&
16+
git add sub/file1 &&
17+
echo "B " >sub/file1 &&
1718
git diff >patch.file
1819
'
1920

2021
test_expect_success 'apply --whitespace=strip' '
2122
22-
cp saved file1 &&
23+
rm -f sub/file1 &&
24+
cp saved sub/file1 &&
2325
git update-index --refresh &&
2426
2527
git apply --whitespace=strip patch.file &&
26-
if grep " " file1
28+
if grep " " sub/file1
2729
then
2830
echo "Eh?"
2931
false
@@ -34,12 +36,13 @@ test_expect_success 'apply --whitespace=strip' '
3436

3537
test_expect_success 'apply --whitespace=strip from config' '
3638
37-
cp saved file1 &&
39+
rm -f sub/file1 &&
40+
cp saved sub/file1 &&
3841
git update-index --refresh &&
3942
4043
git config apply.whitespace strip &&
4144
git apply patch.file &&
42-
if grep " " file1
45+
if grep " " sub/file1
4346
then
4447
echo "Eh?"
4548
false
@@ -48,19 +51,19 @@ test_expect_success 'apply --whitespace=strip from config' '
4851
fi
4952
'
5053

51-
mkdir sub
5254
D=`pwd`
5355

5456
test_expect_success 'apply --whitespace=strip in subdir' '
5557
5658
cd "$D" &&
5759
git config --unset-all apply.whitespace
58-
cp saved file1 &&
60+
rm -f sub/file1 &&
61+
cp saved sub/file1 &&
5962
git update-index --refresh &&
6063
6164
cd sub &&
62-
git apply --whitespace=strip ../patch.file &&
63-
if grep " " ../file1
65+
git apply --whitespace=strip -p2 ../patch.file &&
66+
if grep " " file1
6467
then
6568
echo "Eh?"
6669
false
@@ -73,11 +76,12 @@ test_expect_success 'apply --whitespace=strip from config in subdir' '
7376
7477
cd "$D" &&
7578
git config apply.whitespace strip &&
76-
cp saved file1 &&
79+
rm -f sub/file1 &&
80+
cp saved sub/file1 &&
7781
git update-index --refresh &&
7882
7983
cd sub &&
80-
git apply ../patch.file &&
84+
git apply -p2 ../patch.file &&
8185
if grep " " file1
8286
then
8387
echo "Eh?"

0 commit comments

Comments
 (0)