]> git.ipfire.org Git - thirdparty/git.git/blobdiff - sequencer.c
Merge branch 'bl/cherry-pick-empty'
[thirdparty/git.git] / sequencer.c
index 5c6f541126c74bb1c70adef36520213b31d3265b..fa838f264f5a98f48b923b0831782a864a5ccb0f 100644 (file)
@@ -332,7 +332,7 @@ static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob,
                sb->buf[sb->len - ignore_footer] = '\0';
        }
 
-       trailer_info_get(&info, sb->buf, &opts);
+       trailer_info_get(&opts, sb->buf, &info);
 
        if (ignore_footer)
                sb->buf[sb->len - ignore_footer] = saved_char;
@@ -461,13 +461,25 @@ static void free_message(struct commit *commit, struct commit_message *msg)
        repo_unuse_commit_buffer(the_repository, commit, msg->message);
 }
 
+const char *rebase_resolvemsg =
+N_("Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run "
+"\"git rebase --abort\".");
+
 static void print_advice(struct repository *r, int show_hint,
                         struct replay_opts *opts)
 {
-       char *msg = getenv("GIT_CHERRY_PICK_HELP");
+       const char *msg;
+
+       if (is_rebase_i(opts))
+               msg = rebase_resolvemsg;
+       else
+               msg = getenv("GIT_CHERRY_PICK_HELP");
 
        if (msg) {
-               advise("%s\n", msg);
+               advise_if_enabled(ADVICE_MERGE_CONFLICT, "%s", msg);
                /*
                 * A conflict has occurred but the porcelain
                 * (typically rebase --interactive) wants to take care
@@ -480,22 +492,25 @@ static void print_advice(struct repository *r, int show_hint,
 
        if (show_hint) {
                if (opts->no_commit)
-                       advise(_("after resolving the conflicts, mark the corrected paths\n"
-                                "with 'git add <paths>' or 'git rm <paths>'"));
+                       advise_if_enabled(ADVICE_MERGE_CONFLICT,
+                                         _("after resolving the conflicts, mark the corrected paths\n"
+                                           "with 'git add <paths>' or 'git rm <paths>'"));
                else if (opts->action == REPLAY_PICK)
-                       advise(_("After resolving the conflicts, mark them with\n"
-                                "\"git add/rm <pathspec>\", then run\n"
-                                "\"git cherry-pick --continue\".\n"
-                                "You can instead skip this commit with \"git cherry-pick --skip\".\n"
-                                "To abort and get back to the state before \"git cherry-pick\",\n"
-                                "run \"git cherry-pick --abort\"."));
+                       advise_if_enabled(ADVICE_MERGE_CONFLICT,
+                                         _("After resolving the conflicts, mark them with\n"
+                                           "\"git add/rm <pathspec>\", then run\n"
+                                           "\"git cherry-pick --continue\".\n"
+                                           "You can instead skip this commit with \"git cherry-pick --skip\".\n"
+                                           "To abort and get back to the state before \"git cherry-pick\",\n"
+                                           "run \"git cherry-pick --abort\"."));
                else if (opts->action == REPLAY_REVERT)
-                       advise(_("After resolving the conflicts, mark them with\n"
-                                "\"git add/rm <pathspec>\", then run\n"
-                                "\"git revert --continue\".\n"
-                                "You can instead skip this commit with \"git revert --skip\".\n"
-                                "To abort and get back to the state before \"git revert\",\n"
-                                "run \"git revert --abort\"."));
+                       advise_if_enabled(ADVICE_MERGE_CONFLICT,
+                                         _("After resolving the conflicts, mark them with\n"
+                                           "\"git add/rm <pathspec>\", then run\n"
+                                           "\"git revert --continue\".\n"
+                                           "You can instead skip this commit with \"git revert --skip\".\n"
+                                           "To abort and get back to the state before \"git revert\",\n"
+                                           "run \"git revert --abort\"."));
                else
                        BUG("unexpected pick action in print_advice()");
        }
@@ -772,29 +787,42 @@ static struct object_id *get_cache_tree_oid(struct index_state *istate)
 static int is_index_unchanged(struct repository *r)
 {
        struct object_id head_oid, *cache_tree_oid;
+       const struct object_id *head_tree_oid;
        struct commit *head_commit;
        struct index_state *istate = r->index;
+       const char *head_name;
+
+       if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) {
+               /* Check to see if this is an unborn branch */
+               head_name = resolve_ref_unsafe("HEAD",
+                       RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+                       &head_oid, NULL);
+               if (!head_name ||
+                       !starts_with(head_name, "refs/heads/") ||
+                       !is_null_oid(&head_oid))
+                       return error(_("could not resolve HEAD commit"));
+               head_tree_oid = the_hash_algo->empty_tree;
+       } else {
+               head_commit = lookup_commit(r, &head_oid);
 
-       if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
-               return error(_("could not resolve HEAD commit"));
-
-       head_commit = lookup_commit(r, &head_oid);
+               /*
+                * If head_commit is NULL, check_commit, called from
+                * lookup_commit, would have indicated that head_commit is not
+                * a commit object already.  repo_parse_commit() will return failure
+                * without further complaints in such a case.  Otherwise, if
+                * the commit is invalid, repo_parse_commit() will complain.  So
+                * there is nothing for us to say here.  Just return failure.
+                */
+               if (repo_parse_commit(r, head_commit))
+                       return -1;
 
-       /*
-        * If head_commit is NULL, check_commit, called from
-        * lookup_commit, would have indicated that head_commit is not
-        * a commit object already.  repo_parse_commit() will return failure
-        * without further complaints in such a case.  Otherwise, if
-        * the commit is invalid, repo_parse_commit() will complain.  So
-        * there is nothing for us to say here.  Just return failure.
-        */
-       if (repo_parse_commit(r, head_commit))
-               return -1;
+               head_tree_oid = get_commit_tree_oid(head_commit);
+       }
 
        if (!(cache_tree_oid = get_cache_tree_oid(istate)))
                return -1;
 
-       return oideq(cache_tree_oid, get_commit_tree_oid(head_commit));
+       return oideq(cache_tree_oid, head_tree_oid);
 }
 
 static int write_author_script(const char *message)
@@ -1721,34 +1749,25 @@ static int allow_empty(struct repository *r,
        int index_unchanged, originally_empty;
 
        /*
-        * Four cases:
-        *
-        * (1) we do not allow empty at all and error out.
-        *
-        * (2) we allow ones that were initially empty, and
-        *     just drop the ones that become empty
+        * For a commit that is initially empty, allow_empty determines if it
+        * should be kept or not
         *
-        * (3) we allow ones that were initially empty, but
-        *     halt for the ones that become empty;
-        *
-        * (4) we allow both.
+        * For a commit that becomes empty, keep_redundant_commits and
+        * drop_redundant_commits determine whether the commit should be kept or
+        * dropped. If neither is specified, halt.
         */
-       if (!opts->allow_empty)
-               return 0; /* let "git commit" barf as necessary */
-
        index_unchanged = is_index_unchanged(r);
        if (index_unchanged < 0)
                return index_unchanged;
        if (!index_unchanged)
                return 0; /* we do not have to say --allow-empty */
 
-       if (opts->keep_redundant_commits)
-               return 1;
-
        originally_empty = is_original_commit_empty(commit);
        if (originally_empty < 0)
                return originally_empty;
        if (originally_empty)
+               return opts->allow_empty;
+       else if (opts->keep_redundant_commits)
                return 1;
        else if (opts->drop_redundant_commits)
                return 2;
@@ -2928,6 +2947,9 @@ static int populate_opts_cb(const char *key, const char *value,
        else if (!strcmp(key, "options.allow-empty-message"))
                opts->allow_empty_message =
                        git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
+       else if (!strcmp(key, "options.drop-redundant-commits"))
+               opts->drop_redundant_commits =
+                       git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
        else if (!strcmp(key, "options.keep-redundant-commits"))
                opts->keep_redundant_commits =
                        git_config_bool_or_int(key, value, ctx->kvi, &error_flag);
@@ -3472,6 +3494,9 @@ static int save_opts(struct replay_opts *opts)
        if (opts->allow_empty_message)
                res |= git_config_set_in_file_gently(opts_file,
                                "options.allow-empty-message", "true");
+       if (opts->drop_redundant_commits)
+               res |= git_config_set_in_file_gently(opts_file,
+                               "options.drop-redundant-commits", "true");
        if (opts->keep_redundant_commits)
                res |= git_config_set_in_file_gently(opts_file,
                                "options.keep-redundant-commits", "true");