From 9987d7c58a847ab1605ae3216ff1ca95b19f0ad1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 21 Feb 2007 14:31:10 -0800 Subject: [PATCH] git-apply: notice "diff --git" patch again Earlier one that tried to be too consistent with GNU patch by not stripping the leading path when we _know_ we are in a subdirectory and the patch is relative to the toplevel was a mistake. This fixes it. - No change to behaviour when it is run from the toplevel of the repository. - When run from a subdirectory to apply a git-generated patch, it uses the right -p value automatically, with or without --index nor --cached option. - When run from a subdirectory to apply a randomly generated patch, it wants the right -p value to be given by the user. The second one is a pure improvement to correct inconsistency between --index and non --index case, compared with 1.5.0. The third point could be further improved to guess what the right value for -p should be by looking at the patch, but should be a topic of a separate patch. Signed-off-by: Junio C Hamano --- builtin-apply.c | 23 ++++++++++++++++------- t/t4119-apply-config.sh | 4 ++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index 1beebe5ff1..12f00e38db 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -144,6 +144,7 @@ struct patch { unsigned long deflate_origlen; int lines_added, lines_deleted; int score; + unsigned int is_toplevel_relative:1; unsigned int inaccurate_eof:1; unsigned int is_binary:1; unsigned int is_copy:1; @@ -362,7 +363,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch) static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew) { if (!orig_name && !isnull) - return find_name(line, NULL, p_value, TERM_TAB); + return find_name(line, NULL, 1, TERM_TAB); if (orig_name) { int len; @@ -372,7 +373,7 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, len = strlen(name); if (isnull) die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr); - another = find_name(line, NULL, p_value, TERM_TAB); + another = find_name(line, NULL, 1, TERM_TAB); if (!another || memcmp(another, name, len)) die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr); free(another); @@ -427,28 +428,28 @@ static int gitdiff_newfile(const char *line, struct patch *patch) static int gitdiff_copysrc(const char *line, struct patch *patch) { patch->is_copy = 1; - patch->old_name = find_name(line, NULL, p_value-1, 0); + patch->old_name = find_name(line, NULL, 0, 0); return 0; } static int gitdiff_copydst(const char *line, struct patch *patch) { patch->is_copy = 1; - patch->new_name = find_name(line, NULL, p_value-1, 0); + patch->new_name = find_name(line, NULL, 0, 0); return 0; } static int gitdiff_renamesrc(const char *line, struct patch *patch) { patch->is_rename = 1; - patch->old_name = find_name(line, NULL, p_value-1, 0); + patch->old_name = find_name(line, NULL, 0, 0); return 0; } static int gitdiff_renamedst(const char *line, struct patch *patch) { patch->is_rename = 1; - patch->new_name = find_name(line, NULL, p_value-1, 0); + patch->new_name = find_name(line, NULL, 0, 0); return 0; } @@ -787,6 +788,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc { unsigned long offset, len; + patch->is_toplevel_relative = 0; patch->is_rename = patch->is_copy = 0; patch->is_new = patch->is_delete = -1; patch->old_mode = patch->new_mode = 0; @@ -831,6 +833,7 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc die("git diff header lacks filename information (line %d)", linenr); patch->old_name = patch->new_name = patch->def_name; } + patch->is_toplevel_relative = 1; *hdrsize = git_hdr_len; return offset; } @@ -2499,6 +2502,12 @@ static int use_patch(struct patch *p) return 0; x = x->next; } + if (0 < prefix_length) { + int pathlen = strlen(pathname); + if (pathlen <= prefix_length || + memcmp(prefix, pathname, prefix_length)) + return 0; + } return 1; } @@ -2513,7 +2522,7 @@ static void prefix_one(char **name) static void prefix_patches(struct patch *p) { - if (!prefix) + if (!prefix || p->is_toplevel_relative) return; for ( ; p; p = p->next) { if (p->new_name == p->old_name) { diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh index f9b9425153..32e0d7172e 100755 --- a/t/t4119-apply-config.sh +++ b/t/t4119-apply-config.sh @@ -78,7 +78,7 @@ test_expect_success 'apply --whitespace=strip in subdir' ' git update-index --refresh && cd sub && - git apply --whitespace=strip -p2 ../patch.file && + git apply --whitespace=strip ../patch.file && if grep " " file1 then echo "Eh?" @@ -101,7 +101,7 @@ test_expect_success 'apply --whitespace=strip from config in subdir' ' git update-index --refresh && cd sub && - git apply -p2 ../patch.file && + git apply ../patch.file && if grep " " file1 then echo "Eh?"