git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] git-apply: notice "diff --git" patch again

From
Junio C Hamano <junkio@cox.net>
Date
Feb 21, 2007, 22:31 UTC
Message-ID
<7vy7mrm9ch.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<7vr6sjnw15.fsf@assigned-by-dhcp.cox.net>

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<n> 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<n> 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<n> should be by looking at the patch, but should be a topic of a separate patch.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 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 1beebe5..12f00e3 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 f9b9425..32e0d71 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?"
Previous: Junio C HamanoNext: Junio C Hamano
Message 28 of 49 in “Teach core.autocrlf to 'git apply'”
  1. Teach core.autocrlf to 'git apply'Junio C Hamano, Feb 17, 2007
  2. Teach 'git apply' to look at $GIT_DIR/configJunio C Hamano, Feb 17, 2007
  3. Jeff KingFeb 17, 2007
  4. Junio C HamanoFeb 17, 2007
  5. Jeff KingFeb 17, 2007
  6. Linus TorvaldsFeb 19, 2007
  7. Shawn O. PearceFeb 19, 2007
  8. Junio C HamanoFeb 19, 2007
  9. Linus TorvaldsFeb 19, 2007
  10. Junio C HamanoFeb 19, 2007
  11. Linus TorvaldsFeb 20, 2007
  12. Junio C HamanoFeb 20, 2007
  13. Johannes SchindelinFeb 20, 2007
  14. Junio C HamanoFeb 20, 2007
  15. Johannes SchindelinFeb 20, 2007
  16. git-apply: require -p<n> when working in a subdirectory.Junio C Hamano, Feb 20, 2007
  17. apply: fix memory leak in prefix_one()Johannes Schindelin, Feb 20, 2007
  18. Junio C HamanoFeb 20, 2007
  19. Johannes SchindelinFeb 20, 2007
  20. git-apply: do not lose cwd when run from a subdirectory.Junio C Hamano, Feb 20, 2007
  21. Junio C HamanoFeb 20, 2007
  22. Linus TorvaldsFeb 20, 2007
  23. Daniel BarkalowFeb 21, 2007
  24. Junio C HamanoFeb 21, 2007
  25. Daniel BarkalowFeb 21, 2007
  26. Linus TorvaldsFeb 21, 2007
  27. Junio C HamanoFeb 21, 2007
  28. git-apply: notice "diff --git" patch againJunio C Hamano, Feb 21, 2007
  29. git-apply: guess correct -p<n> value for non-git patches.Junio C Hamano, Feb 22, 2007
  30. Johannes SchindelinFeb 20, 2007
  31. Simon 'corecode' SchubertFeb 20, 2007
  32. Johannes SchindelinFeb 18, 2007
  33. Junio C HamanoFeb 18, 2007
  34. Johannes SchindelinFeb 18, 2007
  35. Junio C HamanoFeb 18, 2007
  36. Johannes SchindelinFeb 18, 2007
  37. Junio C HamanoFeb 18, 2007
  38. Johannes SchindelinFeb 18, 2007
  39. Junio C HamanoFeb 18, 2007
  40. Johannes SchindelinFeb 18, 2007
  41. Jakub NarebskiFeb 18, 2007
  42. Johannes SchindelinFeb 18, 2007
  43. Junio C HamanoFeb 18, 2007
  44. Johannes SchindelinFeb 18, 2007
  45. Junio C HamanoFeb 18, 2007
  46. Johannes SchindelinFeb 18, 2007
  47. Junio C HamanoFeb 18, 2007
  48. Johannes SchindelinFeb 18, 2007
  49. Junio C HamanoFeb 18, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.