From: Paul Tan <pyokagan@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Stefan Beller <sbeller@google.com>, Paul Tan <pyokagan@gmail.com>
Subject: [PATCH v6 13/45] builtin-am: implement --skip
Date: Mon, 20 Jul 2015 00:10:05 +0800 [thread overview]
Message-ID: <1437322237-29863-14-git-send-email-pyokagan@gmail.com> (raw)
In-Reply-To: <1437322237-29863-1-git-send-email-pyokagan@gmail.com>
Since d1c5f2a (Add git-am, applymbox replacement., 2005-10-07), git-am
supported resuming from a failed patch application by skipping the
current patch. Re-implement this feature by introducing am_skip().
Helped-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Paul Tan <pyokagan@gmail.com>
---
Notes:
v6
* Moved lock_file memory allocation to just before the
hold_locked_index() to prevent memory leaks.
builtin/am.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 121 insertions(+), 2 deletions(-)
diff --git a/builtin/am.c b/builtin/am.c
index ec579a6..765844b 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -16,6 +16,8 @@
#include "commit.h"
#include "diff.h"
#include "diffcore.h"
+#include "unpack-trees.h"
+#include "branch.h"
/**
* Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -868,6 +870,116 @@ static void am_resolve(struct am_state *state)
}
/**
+ * Performs a checkout fast-forward from `head` to `remote`. If `reset` is
+ * true, any unmerged entries will be discarded. Returns 0 on success, -1 on
+ * failure.
+ */
+static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
+{
+ struct lock_file *lock_file;
+ struct unpack_trees_options opts;
+ struct tree_desc t[2];
+
+ if (parse_tree(head) || parse_tree(remote))
+ return -1;
+
+ lock_file = xcalloc(1, sizeof(struct lock_file));
+ hold_locked_index(lock_file, 1);
+
+ refresh_cache(REFRESH_QUIET);
+
+ memset(&opts, 0, sizeof(opts));
+ opts.head_idx = 1;
+ opts.src_index = &the_index;
+ opts.dst_index = &the_index;
+ opts.update = 1;
+ opts.merge = 1;
+ opts.reset = reset;
+ opts.fn = twoway_merge;
+ init_tree_desc(&t[0], head->buffer, head->size);
+ init_tree_desc(&t[1], remote->buffer, remote->size);
+
+ if (unpack_trees(2, t, &opts)) {
+ rollback_lock_file(lock_file);
+ return -1;
+ }
+
+ if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ die(_("unable to write new index file"));
+
+ return 0;
+}
+
+/**
+ * Clean the index without touching entries that are not modified between
+ * `head` and `remote`.
+ */
+static int clean_index(const unsigned char *head, const unsigned char *remote)
+{
+ struct lock_file *lock_file;
+ struct tree *head_tree, *remote_tree, *index_tree;
+ unsigned char index[GIT_SHA1_RAWSZ];
+ struct pathspec pathspec;
+
+ head_tree = parse_tree_indirect(head);
+ if (!head_tree)
+ return error(_("Could not parse object '%s'."), sha1_to_hex(head));
+
+ remote_tree = parse_tree_indirect(remote);
+ if (!remote_tree)
+ return error(_("Could not parse object '%s'."), sha1_to_hex(remote));
+
+ read_cache_unmerged();
+
+ if (fast_forward_to(head_tree, head_tree, 1))
+ return -1;
+
+ if (write_cache_as_tree(index, 0, NULL))
+ return -1;
+
+ index_tree = parse_tree_indirect(index);
+ if (!index_tree)
+ return error(_("Could not parse object '%s'."), sha1_to_hex(index));
+
+ if (fast_forward_to(index_tree, remote_tree, 0))
+ return -1;
+
+ memset(&pathspec, 0, sizeof(pathspec));
+
+ lock_file = xcalloc(1, sizeof(struct lock_file));
+ hold_locked_index(lock_file, 1);
+
+ if (read_tree(remote_tree, 0, &pathspec)) {
+ rollback_lock_file(lock_file);
+ return -1;
+ }
+
+ if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+ die(_("unable to write new index file"));
+
+ remove_branch_state();
+
+ return 0;
+}
+
+/**
+ * Resume the current am session by skipping the current patch.
+ */
+static void am_skip(struct am_state *state)
+{
+ unsigned char head[GIT_SHA1_RAWSZ];
+
+ if (get_sha1("HEAD", head))
+ hashcpy(head, EMPTY_TREE_SHA1_BIN);
+
+ if (clean_index(head, head))
+ die(_("failed to clean index"));
+
+ am_next(state);
+ am_run(state, 0);
+}
+
+/**
* parse_options() callback that validates and sets opt->value to the
* PATCH_FORMAT_* enum value corresponding to `arg`.
*/
@@ -885,7 +997,8 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
enum resume_mode {
RESUME_FALSE = 0,
RESUME_APPLY,
- RESUME_RESOLVED
+ RESUME_RESOLVED,
+ RESUME_SKIP
};
int cmd_am(int argc, const char **argv, const char *prefix)
@@ -896,7 +1009,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
const char * const usage[] = {
N_("git am [options] [(<mbox>|<Maildir>)...]"),
- N_("git am [options] --continue"),
+ N_("git am [options] (--continue | --skip)"),
NULL
};
@@ -910,6 +1023,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
OPT_CMDMODE('r', "resolved", &resume,
N_("synonyms for --continue"),
RESUME_RESOLVED),
+ OPT_CMDMODE(0, "skip", &resume,
+ N_("skip the current patch"),
+ RESUME_SKIP),
OPT_END()
};
@@ -971,6 +1087,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
case RESUME_RESOLVED:
am_resolve(&state);
break;
+ case RESUME_SKIP:
+ am_skip(&state);
+ break;
default:
die("BUG: invalid resume value");
}
--
2.5.0.rc2.110.gb39b692
next prev parent reply other threads:[~2015-07-19 16:11 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-19 16:09 [PATCH v6 00/45] Make git-am a builtin Paul Tan
2015-07-19 16:09 ` [PATCH v6 01/45] wrapper: implement xopen() Paul Tan
2015-07-19 16:09 ` [PATCH v6 02/45] wrapper: implement xfopen() Paul Tan
2015-07-19 16:09 ` [PATCH v6 03/45] builtin-am: implement skeletal builtin am Paul Tan
2015-07-19 16:09 ` [PATCH v6 04/45] builtin-am: implement patch queue mechanism Paul Tan
2015-07-19 16:09 ` [PATCH v6 05/45] builtin-am: split out mbox/maildir patches with git-mailsplit Paul Tan
2015-07-19 16:09 ` [PATCH v6 06/45] builtin-am: auto-detect mbox patches Paul Tan
2015-07-19 16:09 ` [PATCH v6 07/45] builtin-am: extract patch and commit info with git-mailinfo Paul Tan
2015-07-19 16:10 ` [PATCH v6 08/45] builtin-am: apply patch with git-apply Paul Tan
2015-07-19 16:10 ` [PATCH v6 09/45] builtin-am: implement committing applied patch Paul Tan
2015-07-19 16:10 ` [PATCH v6 10/45] builtin-am: refuse to apply patches if index is dirty Paul Tan
2015-07-19 16:10 ` [PATCH v6 11/45] builtin-am: implement --resolved/--continue Paul Tan
2015-07-19 16:10 ` [PATCH v6 12/45] builtin-am: don't parse mail when resuming Paul Tan
2015-07-19 16:10 ` Paul Tan [this message]
2015-07-19 16:10 ` [PATCH v6 14/45] builtin-am: implement --abort Paul Tan
2015-07-31 23:42 ` Stefan Beller
2015-07-19 16:10 ` [PATCH v6 15/45] builtin-am: reject patches when there's a session in progress Paul Tan
2015-07-19 16:10 ` [PATCH v6 16/45] builtin-am: implement -q/--quiet Paul Tan
2015-07-19 16:10 ` [PATCH v6 17/45] builtin-am: exit with user friendly message on failure Paul Tan
2015-07-19 16:10 ` [PATCH v6 18/45] builtin-am: implement -s/--signoff Paul Tan
2015-07-19 16:10 ` [PATCH v6 19/45] cache-tree: introduce write_index_as_tree() Paul Tan
2015-07-19 16:10 ` [PATCH v6 20/45] builtin-am: implement --3way, am.threeWay Paul Tan
2015-07-19 16:10 ` [PATCH v6 21/45] builtin-am: implement --rebasing mode Paul Tan
2015-07-19 16:10 ` [PATCH v6 22/45] builtin-am: bypass git-mailinfo when --rebasing Paul Tan
2015-07-19 16:10 ` [PATCH v6 23/45] builtin-am: handle stray state directory Paul Tan
2015-07-19 16:10 ` [PATCH v6 24/45] builtin-am: implement -u/--utf8 Paul Tan
2015-07-19 16:10 ` [PATCH v6 25/45] builtin-am: implement -k/--keep, --keep-non-patch Paul Tan
2015-07-19 16:10 ` [PATCH v6 26/45] builtin-am: implement --[no-]message-id, am.messageid Paul Tan
2015-07-19 16:10 ` [PATCH v6 27/45] builtin-am: support --keep-cr, am.keepcr Paul Tan
2015-07-19 16:10 ` [PATCH v6 28/45] builtin-am: implement --[no-]scissors Paul Tan
2015-07-19 16:10 ` [PATCH v6 29/45] builtin-am: pass git-apply's options to git-apply Paul Tan
2015-07-19 16:10 ` [PATCH v6 30/45] builtin-am: implement --ignore-date Paul Tan
2015-07-19 16:10 ` [PATCH v6 31/45] builtin-am: implement --committer-date-is-author-date Paul Tan
2015-07-19 16:10 ` [PATCH v6 32/45] builtin-am: implement -S/--gpg-sign, commit.gpgsign Paul Tan
2015-07-19 16:10 ` [PATCH v6 33/45] builtin-am: invoke post-rewrite hook Paul Tan
2015-07-19 16:10 ` [PATCH v6 34/45] builtin-am: support automatic notes copying Paul Tan
2015-07-19 16:10 ` [PATCH v6 35/45] builtin-am: invoke applypatch-msg hook Paul Tan
2015-07-19 16:10 ` [PATCH v6 36/45] builtin-am: invoke pre-applypatch hook Paul Tan
2015-07-19 16:10 ` [PATCH v6 37/45] builtin-am: invoke post-applypatch hook Paul Tan
2015-07-19 16:10 ` [PATCH v6 38/45] builtin-am: rerere support Paul Tan
2015-07-19 16:10 ` [PATCH v6 39/45] builtin-am: support and auto-detect StGit patches Paul Tan
2015-07-19 16:10 ` [PATCH v6 40/45] builtin-am: support and auto-detect StGit series files Paul Tan
2015-07-19 16:10 ` [PATCH v6 41/45] builtin-am: support and auto-detect mercurial patches Paul Tan
2015-07-19 16:10 ` [PATCH v6 42/45] builtin-am: implement -i/--interactive Paul Tan
2015-07-19 16:10 ` [PATCH v6 43/45] builtin-am: implement legacy -b/--binary option Paul Tan
2015-07-19 16:10 ` [PATCH v6 44/45] builtin-am: check for valid committer ident Paul Tan
2015-07-19 16:10 ` [PATCH v6 45/45] builtin-am: remove redirection to git-am.sh Paul Tan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1437322237-29863-14-git-send-email-pyokagan@gmail.com \
--to=pyokagan@gmail.com \
--cc=git@vger.kernel.org \
--cc=johannes.schindelin@gmx.de \
--cc=sbeller@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).