summaryrefslogtreecommitdiff
path: root/sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sequencer.c')
-rw-r--r--sequencer.c126
1 files changed, 75 insertions, 51 deletions
diff --git a/sequencer.c b/sequencer.c
index d76cbded00..8909a46770 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -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;
@@ -314,9 +329,8 @@ int sequencer_remove_state(struct replay_opts *opts)
}
}
- free(opts->committer_name);
- free(opts->committer_email);
free(opts->gpg_sign);
+ free(opts->default_strategy);
free(opts->strategy);
for (i = 0; i < opts->xopts_nr; i++)
free(opts->xopts[i]);
@@ -595,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;
@@ -620,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;
@@ -1460,8 +1490,8 @@ static int try_to_commit(struct repository *r,
} else {
reset_ident_date();
}
- committer = fmt_ident(opts->committer_name,
- opts->committer_email,
+ committer = fmt_ident(getenv("GIT_COMMITTER_NAME"),
+ getenv("GIT_COMMITTER_EMAIL"),
WANT_COMMITTER_IDENT,
opts->ignore_date ? NULL : date.buf,
IDENT_STRICT);
@@ -1991,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)
@@ -2653,7 +2686,7 @@ static int read_populate_opts(struct replay_opts *opts)
}
if (read_oneliner(&buf, rebase_path_squash_onto(), 0)) {
- if (get_oid_hex(buf.buf, &opts->squash_onto) < 0) {
+ if (get_oid_committish(buf.buf, &opts->squash_onto) < 0) {
ret = error(_("unusable squash-onto"));
goto done_rebase_i;
}
@@ -2692,7 +2725,7 @@ static void write_strategy_opts(struct replay_opts *opts)
}
int write_basic_state(struct replay_opts *opts, const char *head_name,
- struct commit *onto, const char *orig_head)
+ struct commit *onto, const struct object_id *orig_head)
{
if (head_name)
write_file(rebase_path_head_name(), "%s\n", head_name);
@@ -2700,7 +2733,8 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
write_file(rebase_path_onto(), "%s\n",
oid_to_hex(&onto->object.oid));
if (orig_head)
- write_file(rebase_path_orig_head(), "%s\n", orig_head);
+ write_file(rebase_path_orig_head(), "%s\n",
+ oid_to_hex(orig_head));
if (opts->quiet)
write_file(rebase_path_quiet(), "%s", "");
@@ -3485,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;
@@ -3677,7 +3713,9 @@ static int do_merge(struct repository *r,
strvec_push(&cmd.args, "-F");
strvec_push(&cmd.args, git_path_merge_msg(r));
if (opts->gpg_sign)
- strvec_push(&cmd.args, opts->gpg_sign);
+ strvec_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+ else
+ strvec_push(&cmd.args, "--no-gpg-sign");
/* Add the tips to be merged */
for (j = to_merge; j; j = j->next)
@@ -3689,7 +3727,6 @@ static int do_merge(struct repository *r,
NULL, 0);
rollback_lock_file(&lock);
- rollback_lock_file(&lock);
ret = run_command(&cmd);
/* force re-reading of the cache */
@@ -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);
@@ -3965,21 +4015,17 @@ static int run_git_checkout(struct repository *r, struct replay_opts *opts,
static int checkout_onto(struct repository *r, struct replay_opts *opts,
const char *onto_name, const struct object_id *onto,
- const char *orig_head)
+ const struct object_id *orig_head)
{
- struct object_id oid;
const char *action = reflog_message(opts, "start", "checkout %s", onto_name);
- if (get_oid(orig_head, &oid))
- return error(_("%s: not a valid OID"), orig_head);
-
if (run_git_checkout(r, opts, oid_to_hex(onto), action)) {
apply_autostash(rebase_path_autostash());
sequencer_remove_state(opts);
return error(_("could not detach HEAD"));
}
- return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
+ return update_ref(NULL, "ORIG_HEAD", orig_head, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
}
static int stopped_at_head(struct repository *r)
@@ -4467,22 +4513,6 @@ static int commit_staged_changes(struct repository *r,
return 0;
}
-static int init_committer(struct replay_opts *opts)
-{
- struct ident_split id;
- const char *committer;
-
- committer = git_committer_info(IDENT_STRICT);
- if (split_ident_line(&id, committer, strlen(committer)) < 0)
- return error(_("invalid committer '%s'"), committer);
- opts->committer_name =
- xmemdupz(id.name_begin, id.name_end - id.name_begin);
- opts->committer_email =
- xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
-
- return 0;
-}
-
int sequencer_continue(struct repository *r, struct replay_opts *opts)
{
struct todo_list todo_list = TODO_LIST_INIT;
@@ -4494,9 +4524,6 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
if (read_populate_opts(opts))
return -1;
if (is_rebase_i(opts)) {
- if (opts->committer_date_is_author_date && init_committer(opts))
- return -1;
-
if ((res = read_populate_todo(r, &todo_list, opts)))
goto release_todo_list;
@@ -5058,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;
@@ -5314,7 +5341,7 @@ static int skip_unnecessary_picks(struct repository *r,
int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
const char *shortrevisions, const char *onto_name,
- struct commit *onto, const char *orig_head,
+ struct commit *onto, const struct object_id *orig_head,
struct string_list *commands, unsigned autosquash,
struct todo_list *todo_list)
{
@@ -5391,9 +5418,6 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
res = -1;
- if (opts->committer_date_is_author_date && init_committer(opts))
- goto cleanup;
-
if (checkout_onto(r, opts, onto_name, &oid, orig_head))
goto cleanup;
@@ -5577,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);