]> git.ipfire.org Git - thirdparty/git.git/blobdiff - sequencer.c
Merge branch 'fc/bash-completion-alias-of-alias'
[thirdparty/git.git] / sequencer.c
index 3dce6c963cec91e6b69de360d931a7d9e294db07..8909a467700c506f7068ed566aa7813c093157fd 100644 (file)
@@ -14,7 +14,8 @@
 #include "diff.h"
 #include "revision.h"
 #include "rerere.h"
-#include "merge-recursive.h"
+#include "merge-ort.h"
+#include "merge-ort-wrappers.h"
 #include "refs.h"
 #include "strvec.h"
 #include "quote.h"
@@ -204,6 +205,20 @@ static int git_sequencer_config(const char *k, const char *v, void *cb)
                return 0;
        }
 
+       if (!opts->default_strategy && !strcmp(k, "pull.twohead")) {
+               int ret = git_config_string((const char**)&opts->default_strategy, k, v);
+               if (ret == 0) {
+                       /*
+                        * pull.twohead is allowed to be multi-valued; we only
+                        * care about the first value.
+                        */
+                       char *tmp = strchr(opts->default_strategy, ' ');
+                       if (tmp)
+                               *tmp = '\0';
+               }
+               return ret;
+       }
+
        status = git_gpg_config(k, v, NULL);
        if (status)
                return status;
@@ -315,6 +330,7 @@ int sequencer_remove_state(struct replay_opts *opts)
        }
 
        free(opts->gpg_sign);
+       free(opts->default_strategy);
        free(opts->strategy);
        for (i = 0; i < opts->xopts_nr; i++)
                free(opts->xopts[i]);
@@ -593,8 +609,9 @@ static int do_recursive_merge(struct repository *r,
                              struct replay_opts *opts)
 {
        struct merge_options o;
+       struct merge_result result;
        struct tree *next_tree, *base_tree, *head_tree;
-       int clean;
+       int clean, show_output;
        int i;
        struct lock_file index_lock = LOCK_INIT;
 
@@ -618,12 +635,27 @@ static int do_recursive_merge(struct repository *r,
        for (i = 0; i < opts->xopts_nr; i++)
                parse_merge_opt(&o, opts->xopts[i]);
 
-       clean = merge_trees(&o,
-                           head_tree,
-                           next_tree, base_tree);
-       if (is_rebase_i(opts) && clean <= 0)
-               fputs(o.obuf.buf, stdout);
-       strbuf_release(&o.obuf);
+       if (opts->strategy && !strcmp(opts->strategy, "ort")) {
+               memset(&result, 0, sizeof(result));
+               merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree,
+                                           &result);
+               show_output = !is_rebase_i(opts) || !result.clean;
+               /*
+                * TODO: merge_switch_to_result will update index/working tree;
+                * we only really want to do that if !result.clean || this is
+                * the final patch to be picked.  But determining this is the
+                * final patch would take some work, and "head_tree" would need
+                * to be replace with the tree the index matched before we
+                * started doing any picks.
+                */
+               merge_switch_to_result(&o, head_tree, &result, 1, show_output);
+               clean = result.clean;
+       } else {
+               clean = merge_trees(&o, head_tree, next_tree, base_tree);
+               if (is_rebase_i(opts) && clean <= 0)
+                       fputs(o.obuf.buf, stdout);
+               strbuf_release(&o.obuf);
+       }
        if (clean < 0) {
                rollback_lock_file(&index_lock);
                return clean;
@@ -1989,7 +2021,10 @@ static int do_pick_commit(struct repository *r,
 
        if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
                res = -1;
-       else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
+       else if (!opts->strategy ||
+                !strcmp(opts->strategy, "recursive") ||
+                !strcmp(opts->strategy, "ort") ||
+                command == TODO_REVERT) {
                res = do_recursive_merge(r, base, next, base_label, next_label,
                                         &head, &msgbuf, opts);
                if (res < 0)
@@ -3484,7 +3519,9 @@ static int do_merge(struct repository *r,
        struct commit_list *bases, *j, *reversed = NULL;
        struct commit_list *to_merge = NULL, **tail = &to_merge;
        const char *strategy = !opts->xopts_nr &&
-               (!opts->strategy || !strcmp(opts->strategy, "recursive")) ?
+               (!opts->strategy ||
+                !strcmp(opts->strategy, "recursive") ||
+                !strcmp(opts->strategy, "ort")) ?
                NULL : opts->strategy;
        struct merge_options o;
        int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
@@ -3722,7 +3759,20 @@ static int do_merge(struct repository *r,
        o.branch2 = ref_name.buf;
        o.buffer_output = 2;
 
-       ret = merge_recursive(&o, head_commit, merge_commit, reversed, &i);
+       if (opts->strategy && !strcmp(opts->strategy, "ort")) {
+               /*
+                * TODO: Should use merge_incore_recursive() and
+                * merge_switch_to_result(), skipping the call to
+                * merge_switch_to_result() when we don't actually need to
+                * update the index and working copy immediately.
+                */
+               ret = merge_ort_recursive(&o,
+                                         head_commit, merge_commit, reversed,
+                                         &i);
+       } else {
+               ret = merge_recursive(&o, head_commit, merge_commit, reversed,
+                                     &i);
+       }
        if (ret <= 0)
                fputs(o.obuf.buf, stdout);
        strbuf_release(&o.obuf);
@@ -5035,7 +5085,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,
 
        oidmap_free(&commit2todo, 1);
        oidmap_free(&state.commit2label, 1);
-       hashmap_free_entries(&state.labels, struct labels_entry, entry);
+       hashmap_clear_and_free(&state.labels, struct labels_entry, entry);
        strbuf_release(&state.buf);
 
        return 0;
@@ -5551,7 +5601,7 @@ int todo_list_rearrange_squash(struct todo_list *todo_list)
        for (i = 0; i < todo_list->nr; i++)
                free(subjects[i]);
        free(subjects);
-       hashmap_free_entries(&subject2item, struct subject2item_entry, entry);
+       hashmap_clear_and_free(&subject2item, struct subject2item_entry, entry);
 
        clear_commit_todo_item(&commit_todo);