]> asedeno.scripts.mit.edu Git - git.git/blobdiff - builtin-revert.c
Merge branch 'maint'
[git.git] / builtin-revert.c
index a0586f9753189d13d5af1c790ea875a5f383f34f..0270f9b85a8229d30ab3fab5ce73661f383b005e 100644 (file)
@@ -8,6 +8,9 @@
 #include "exec_cmd.h"
 #include "utf8.h"
 #include "parse-options.h"
+#include "cache-tree.h"
+#include "diff.h"
+#include "revision.h"
 
 /*
  * This implements the builtins revert and cherry-pick.
@@ -30,7 +33,7 @@ static const char * const cherry_pick_usage[] = {
        NULL
 };
 
-static int edit, no_replay, no_commit, mainline;
+static int edit, no_replay, no_commit, mainline, signoff;
 static enum { REVERT, CHERRY_PICK } action;
 static struct commit *commit;
 
@@ -50,6 +53,7 @@ static void parse_args(int argc, const char **argv)
                OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
                OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
                OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
+               OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
                OPT_INTEGER('m', "mainline", &mainline, "parent number"),
                OPT_END(),
        };
@@ -224,6 +228,38 @@ static int merge_recursive(const char *base_sha1,
        return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
 }
 
+static char *help_msg(const unsigned char *sha1)
+{
+       static char helpbuf[1024];
+       char *msg = getenv("GIT_CHERRY_PICK_HELP");
+
+       if (msg)
+               return msg;
+
+       strcpy(helpbuf, "  After resolving the conflicts,\n"
+              "mark the corrected paths with 'git add <paths>' "
+              "or 'git rm <paths>' and commit the result.");
+
+       if (action == CHERRY_PICK) {
+               sprintf(helpbuf + strlen(helpbuf),
+                       "\nWhen commiting, use the option "
+                       "'-c %s' to retain authorship and message.",
+                       find_unique_abbrev(sha1, DEFAULT_ABBREV));
+       }
+       return helpbuf;
+}
+
+static int index_is_dirty(void)
+{
+       struct rev_info rev;
+       init_revisions(&rev, NULL);
+       setup_revisions(0, NULL, &rev, "HEAD");
+       DIFF_OPT_SET(&rev.diffopt, QUIET);
+       DIFF_OPT_SET(&rev.diffopt, EXIT_WITH_STATUS);
+       run_diff_index(&rev, 1);
+       return !!DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES);
+}
+
 static int revert_or_cherry_pick(int argc, const char **argv)
 {
        unsigned char head[20];
@@ -233,7 +269,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
        const char *message, *encoding;
        const char *defmsg = xstrdup(git_path("MERGE_MSG"));
 
-       git_config(git_default_config);
+       git_config(git_default_config, NULL);
        me = action == REVERT ? "revert" : "cherry-pick";
        setenv(GIT_REFLOG_ACTION, me, 0);
        parse_args(argc, argv);
@@ -249,15 +285,14 @@ static int revert_or_cherry_pick(int argc, const char **argv)
                 * that represents the "current" state for merge-recursive
                 * to work on.
                 */
-               if (write_tree(head, 0, NULL))
+               if (write_cache_as_tree(head, 0, NULL))
                        die ("Your index file is unmerged.");
        } else {
-               struct wt_status s;
-
                if (get_sha1("HEAD", head))
                        die ("You do not have a valid HEAD");
-               wt_status_prepare(&s);
-               if (s.commitable)
+               if (read_cache() < 0)
+                       die("could not read the index");
+               if (index_is_dirty())
                        die ("Dirty index: cannot %s", me);
                discard_cache();
        }
@@ -336,7 +371,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
        if (merge_recursive(sha1_to_hex(base->object.sha1),
                                sha1_to_hex(head), "HEAD",
                                sha1_to_hex(next->object.sha1), oneline) ||
-                       write_tree(head, 0, NULL)) {
+                       write_cache_as_tree(head, 0, NULL)) {
                add_to_msg("\nConflicts:\n\n");
                read_cache();
                for (i = 0; i < active_nr;) {
@@ -350,21 +385,13 @@ static int revert_or_cherry_pick(int argc, const char **argv)
                                        i++;
                        }
                }
-               if (close(msg_fd) || commit_lock_file(&msg_file) < 0)
+               if (commit_lock_file(&msg_file) < 0)
                        die ("Error wrapping up %s", defmsg);
-               fprintf(stderr, "Automatic %s failed.  "
-                       "After resolving the conflicts,\n"
-                       "mark the corrected paths with 'git add <paths>' "
-                       "and commit the result.\n", me);
-               if (action == CHERRY_PICK) {
-                       fprintf(stderr, "When commiting, use the option "
-                               "'-c %s' to retain authorship and message.\n",
-                               find_unique_abbrev(commit->object.sha1,
-                                       DEFAULT_ABBREV));
-               }
+               fprintf(stderr, "Automatic %s failed.%s\n",
+                       me, help_msg(commit->object.sha1));
                exit(1);
        }
-       if (close(msg_fd) || commit_lock_file(&msg_file) < 0)
+       if (commit_lock_file(&msg_file) < 0)
                die ("Error wrapping up %s", defmsg);
        fprintf(stderr, "Finished one %s.\n", me);
 
@@ -378,13 +405,21 @@ static int revert_or_cherry_pick(int argc, const char **argv)
         */
 
        if (!no_commit) {
-               if (edit)
-                       return execl_git_cmd("commit", "-n", NULL);
-               else
-                       return execl_git_cmd("commit", "-n", "-F", defmsg, NULL);
+               /* 6 is max possible length of our args array including NULL */
+               const char *args[6];
+               int i = 0;
+               args[i++] = "commit";
+               args[i++] = "-n";
+               if (signoff)
+                       args[i++] = "-s";
+               if (!edit) {
+                       args[i++] = "-F";
+                       args[i++] = defmsg;
+               }
+               args[i] = NULL;
+               return execv_git_cmd(args);
        }
-       if (reencoded_message)
-               free(reencoded_message);
+       free(reencoded_message);
 
        return 0;
 }