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

[PATCH v5 08/44] builtin-am: apply patch with git-apply

From
Paul Tan <pyokagan@gmail.com>
Date
Jul 7, 2015, 14:20 UTC
Message-ID
<1436278862-2638-9-git-send-email-pyokagan@gmail.com>
In-Reply-To
<1436278862-2638-1-git-send-email-pyokagan@gmail.com>
Implement applying the patch to the index using git-apply.

If a file is unchanged but stat-dirty, git-apply may erroneously fail to apply patches, thinking that they conflict with a dirty working tree.

As such, since 2a6f08a (am: refresh the index at start and --resolved, 2011-08-15), git-am will refresh the index before applying patches. Re-implement this behavior.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Paul Tan <pyokagan@gmail.com>
---
 builtin/am.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/builtin/am.c b/builtin/am.c
index 4897857..9c7a6c8 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -10,6 +10,7 @@
 #include "dir.h"
 #include "run-command.h"
 #include "quote.h"
+#include "lockfile.h"
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -42,6 +43,14 @@ static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
 	return 0;
 }
 
+/**
+ * Returns the length of the first line of msg.
+ */
+static int linelen(const char *msg)
+{
+	return strchrnul(msg, '\n') - msg;
+}
+
 enum patch_format {
 	PATCH_FORMAT_UNKNOWN = 0,
 	PATCH_FORMAT_MBOX
@@ -561,6 +570,20 @@ static const char *msgnum(const struct am_state *state)
 }
 
 /**
+ * Refresh and write index.
+ */
+static void refresh_and_write_cache(void)
+{
+	static struct lock_file lock_file;
+
+	hold_locked_index(&lock_file, 1);
+	refresh_cache(REFRESH_QUIET);
+	if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+		die(_("unable to write index file"));
+	rollback_lock_file(&lock_file);
+}
+
+/**
  * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
  * state->msg will be set to the patch message. state->author_name,
  * state->author_email and state->author_date will be set to the patch author's
@@ -650,10 +673,35 @@ finish:
 }
 
 /**
+ * Applies current patch with git-apply. Returns 0 on success, -1 otherwise.
+ */
+static int run_apply(const struct am_state *state)
+{
+	struct child_process cp = CHILD_PROCESS_INIT;
+
+	cp.git_cmd = 1;
+
+	argv_array_push(&cp.args, "apply");
+	argv_array_push(&cp.args, "--index");
+	argv_array_push(&cp.args, am_path(state, "patch"));
+
+	if (run_command(&cp))
+		return -1;
+
+	/* Reload index as git-apply will have modified it. */
+	discard_cache();
+	read_cache();
+
+	return 0;
+}
+
+/**
  * Applies all queued mail.
  */
 static void am_run(struct am_state *state)
 {
+	refresh_and_write_cache();
+
 	while (state->cur <= state->last) {
 		const char *mail = am_path(state, msgnum(state));
 
@@ -666,7 +714,27 @@ static void am_run(struct am_state *state)
 		write_author_script(state);
 		write_commit_msg(state);
 
-		/* NEEDSWORK: Patch application not implemented yet */
+		printf_ln(_("Applying: %.*s"), linelen(state->msg), state->msg);
+
+		if (run_apply(state) < 0) {
+			int advice_amworkdir = 1;
+
+			printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
+				linelen(state->msg), state->msg);
+
+			git_config_get_bool("advice.amworkdir", &advice_amworkdir);
+
+			if (advice_amworkdir)
+				printf_ln(_("The copy of the patch that failed is found in: %s"),
+						am_path(state, "patch"));
+
+			exit(128);
+		}
+
+		/*
+		 * NEEDSWORK: After the patch has been applied to the index
+		 * with git-apply, we need to make commit as well.
+		 */
 
 next:
 		am_next(state);
@@ -728,6 +796,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
 
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
 
+	if (read_index_preload(&the_index, NULL) < 0)
+		die(_("failed to read the index"));
+
 	if (am_in_progress(&state))
 		am_load(&state);
 	else {
-- 
2.5.0.rc1.76.gf60a929
Previous: Paul TanNext: Paul Tan
Message 9 of 63 in “Make git-am a builtin”
  1. 00/44 Make git-am a builtinPaul Tan, Jul 7, 2015
  2. 01/44 wrapper: implement xopen()Paul Tan, Jul 7, 2015
  3. 02/44 wrapper: implement xfopen()Paul Tan, Jul 7, 2015
  4. 03/44 builtin-am: implement skeletal builtin amPaul Tan, Jul 7, 2015
  5. 04/44 builtin-am: implement patch queue mechanismPaul Tan, Jul 7, 2015
  6. 05/44 builtin-am: split out mbox/maildir patches with git-mailsplitPaul Tan, Jul 7, 2015
  7. 06/44 builtin-am: auto-detect mbox patchesPaul Tan, Jul 7, 2015
  8. 07/44 builtin-am: extract patch and commit info with git-mailinfoPaul Tan, Jul 7, 2015
  9. 08/44 builtin-am: apply patch with git-applyPaul Tan, Jul 7, 2015
  10. 09/44 builtin-am: implement committing applied patchPaul Tan, Jul 7, 2015
  11. 10/44 builtin-am: refuse to apply patches if index is dirtyPaul Tan, Jul 7, 2015
  12. 11/44 builtin-am: implement --resolved/--continuePaul Tan, Jul 7, 2015
  13. 12/44 builtin-am: implement --skipPaul Tan, Jul 7, 2015
  14. Stefan BellerJul 13, 2015
  15. Paul TanJul 14, 2015
  16. Stefan BellerJul 14, 2015
  17. Paul TanJul 18, 2015
  18. 13/44 builtin-am: implement --abortPaul Tan, Jul 7, 2015
  19. 14/44 builtin-am: reject patches when there's a session in progressPaul Tan, Jul 7, 2015
  20. 15/44 builtin-am: implement -q/--quietPaul Tan, Jul 7, 2015
  21. 16/44 builtin-am: exit with user friendly message on failurePaul Tan, Jul 7, 2015
  22. 17/44 builtin-am: implement -s/--signoffPaul Tan, Jul 7, 2015
  23. 18/44 cache-tree: introduce write_index_as_tree()Paul Tan, Jul 7, 2015
  24. Junio C HamanoJul 7, 2015
  25. 19/44 builtin-am: implement --3way, am.threeWayPaul Tan, Jul 7, 2015
  26. Junio C HamanoJul 7, 2015
  27. Paul TanJul 14, 2015
  28. 20/44 builtin-am: implement --rebasing modePaul Tan, Jul 7, 2015
  29. 21/44 builtin-am: bypass git-mailinfo when --rebasingPaul Tan, Jul 7, 2015
  30. 22/44 builtin-am: handle stray state directoryPaul Tan, Jul 7, 2015
  31. 23/44 builtin-am: implement -u/--utf8Paul Tan, Jul 7, 2015
  32. 24/44 builtin-am: implement -k/--keep, --keep-non-patchPaul Tan, Jul 7, 2015
  33. 25/44 builtin-am: implement --[no-]message-id, am.messageidPaul Tan, Jul 7, 2015
  34. 26/44 builtin-am: support --keep-cr, am.keepcrPaul Tan, Jul 7, 2015
  35. 27/44 builtin-am: implement --[no-]scissorsPaul Tan, Jul 7, 2015
  36. 28/44 builtin-am: pass git-apply's options to git-applyPaul Tan, Jul 7, 2015
  37. 29/44 builtin-am: implement --ignore-datePaul Tan, Jul 7, 2015
  38. 30/44 builtin-am: implement --committer-date-is-author-datePaul Tan, Jul 7, 2015
  39. 31/44 builtin-am: implement -S/--gpg-sign, commit.gpgsignPaul Tan, Jul 7, 2015
  40. 32/44 builtin-am: invoke post-rewrite hookPaul Tan, Jul 7, 2015
  41. 33/44 builtin-am: support automatic notes copyingPaul Tan, Jul 7, 2015
  42. 34/44 builtin-am: invoke applypatch-msg hookPaul Tan, Jul 7, 2015
  43. 35/44 builtin-am: invoke pre-applypatch hookPaul Tan, Jul 7, 2015
  44. 36/44 builtin-am: invoke post-applypatch hookPaul Tan, Jul 7, 2015
  45. 37/44 builtin-am: rerere supportPaul Tan, Jul 7, 2015
  46. 38/44 builtin-am: support and auto-detect StGit patchesPaul Tan, Jul 7, 2015
  47. 39/44 builtin-am: support and auto-detect StGit series filesPaul Tan, Jul 7, 2015
  48. 40/44 builtin-am: support and auto-detect mercurial patchesPaul Tan, Jul 7, 2015
  49. 41/44 builtin-am: implement -i/--interactivePaul Tan, Jul 7, 2015
  50. 42/44 builtin-am: implement legacy -b/--binary optionPaul Tan, Jul 7, 2015
  51. 43/44 builtin-am: check for valid committer identPaul Tan, Jul 7, 2015
  52. 44/44 builtin-am: remove redirection to git-am.shPaul Tan, Jul 7, 2015
  53. Junio C HamanoJul 7, 2015
  54. Paul TanJul 7, 2015
  55. Junio C HamanoJul 8, 2015
  56. Paul TanJul 8, 2015
  57. Junio C HamanoJul 8, 2015
  58. Paul TanJul 8, 2015
  59. Junio C HamanoJul 9, 2015
  60. Paul TanJul 12, 2015
  61. Junio C HamanoJul 12, 2015
  62. Junio C HamanoJul 13, 2015
  63. Paul TanJul 14, 2015

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.