read_state_file(&sb, state, "utf8", 1);
state->utf8 = !strcmp(sb.buf, "t");
+ if (file_exists(am_path(state, "rerere-autoupdate"))) {
+ read_state_file(&sb, state, "rerere-autoupdate", 1);
+ state->allow_rerere_autoupdate = strcmp(sb.buf, "t") ?
+ RERERE_NOAUTOUPDATE : RERERE_AUTOUPDATE;
+ } else {
+ state->allow_rerere_autoupdate = 0;
+ }
+
read_state_file(&sb, state, "keep", 1);
if (!strcmp(sb.buf, "t"))
state->keep = KEEP_TRUE;
write_state_bool(state, "sign", state->signoff);
write_state_bool(state, "utf8", state->utf8);
+ if (state->allow_rerere_autoupdate)
+ write_state_bool(state, "rerere-autoupdate",
+ state->allow_rerere_autoupdate == RERERE_AUTOUPDATE);
+
switch (state->keep) {
case KEEP_FALSE:
str = "f";
"--strategy-option", opts->xopts ? 1 : 0,
"-x", opts->record_origin,
"--ff", opts->allow_ff,
+ "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,
+ "--no-rerere-autoupdate", opts->allow_rerere_auto == RERERE_NOAUTOUPDATE,
NULL);
}
# itself well to recording empty patches. fortunately, cherry-pick
# makes this easy
git cherry-pick ${gpg_sign_opt:+"$gpg_sign_opt"} --allow-empty \
- --right-only "$revisions" \
+ $allow_rerere_autoupdate --right-only "$revisions" \
${restrict_revision+^$restrict_revision}
ret=$?
else
fi
git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
+ $allow_rerere_autoupdate \
${gpg_sign_opt:+"$gpg_sign_opt"} <"$GIT_DIR/rebased-patches"
ret=$?
test -d "$rewritten" &&
pick_one_preserving_merges "$@" && return
- output eval git cherry-pick \
+ output eval git cherry-pick $allow_rerere_autoupdate \
${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
"$strategy_args" $empty_args $ff "$@"
merge_args="--no-log --no-ff"
if ! do_with_author output eval \
'git merge ${gpg_sign_opt:+"$gpg_sign_opt"} \
- $merge_args $strategy_args -m "$msg_content" $new_parents'
+ $allow_rerere_autoupdate $merge_args \
+ $strategy_args -m "$msg_content" $new_parents'
then
printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
die_with_patch $sha1 "$(eval_gettext "Error redoing merge \$sha1")"
echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
;;
*)
- output eval git cherry-pick \
+ output eval git cherry-pick $allow_rerere_autoupdate \
${gpg_sign_opt:+$(git rev-parse --sq-quote "$gpg_sign_opt")} \
"$strategy_args" "$@" ||
die_with_patch $sha1 "$(eval_gettext "Could not pick \$sha1")"
static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
+static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
static inline int is_rebase_i(const struct replay_opts *opts)
{
else if (!strcmp(key, "options.strategy-option")) {
ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
opts->xopts[opts->xopts_nr++] = xstrdup(value);
- } else
+ } else if (!strcmp(key, "options.allow-rerere-auto"))
+ opts->allow_rerere_auto =
+ git_config_bool_or_int(key, value, &error_flag) ?
+ RERERE_AUTOUPDATE : RERERE_NOAUTOUPDATE;
+ else
return error(_("invalid key: %s"), key);
if (!error_flag)
free(opts->gpg_sign);
opts->gpg_sign = xstrdup(buf.buf + 2);
}
+ strbuf_reset(&buf);
+ }
+
+ if (read_oneliner(&buf, rebase_path_allow_rerere_autoupdate(), 1)) {
+ if (!strcmp(buf.buf, "--rerere-autoupdate"))
+ opts->allow_rerere_auto = RERERE_AUTOUPDATE;
+ else if (!strcmp(buf.buf, "--no-rerere-autoupdate"))
+ opts->allow_rerere_auto = RERERE_NOAUTOUPDATE;
+ strbuf_reset(&buf);
}
if (file_exists(rebase_path_verbose()))
"options.strategy-option",
opts->xopts[i], "^$", 0);
}
+ if (opts->allow_rerere_auto)
+ res |= git_config_set_in_file_gently(opts_file, "options.allow-rerere-auto",
+ opts->allow_rerere_auto == RERERE_AUTOUPDATE ?
+ "true" : "false");
return res;
}
git rebase --continue
'
-test_expect_success 'non-interactive rebase --continue with rerere enabled' '
- test_config rerere.enabled true &&
- test_when_finished "test_might_fail git rebase --abort" &&
- git reset --hard commit-new-file-F2-on-topic-branch &&
- git checkout master &&
- rm -fr .git/rebase-* &&
-
- test_must_fail git rebase --onto master master topic &&
- echo "Resolved" >F2 &&
- git add F2 &&
- cp F2 F2.expected &&
- git rebase --continue &&
-
- git reset --hard commit-new-file-F2-on-topic-branch &&
- git checkout master &&
- test_must_fail git rebase --onto master master topic &&
- test_cmp F2.expected F2
-'
-
test_expect_success 'rebase --continue can not be used with other options' '
test_must_fail git rebase -v --continue &&
test_must_fail git rebase --continue -v
test -f funny.was.run
'
-test_expect_success 'rebase --continue remembers --rerere-autoupdate' '
+test_expect_success 'setup rerere database' '
rm -fr .git/rebase-* &&
git reset --hard commit-new-file-F3-on-topic-branch &&
git checkout master &&
test_commit "commit-new-file-F3" F3 3 &&
- git config rerere.enabled true &&
+ test_config rerere.enabled true &&
test_must_fail git rebase -m master topic &&
echo "Resolved" >F2 &&
+ cp F2 expected-F2 &&
git add F2 &&
test_must_fail git rebase --continue &&
echo "Resolved" >F3 &&
+ cp F3 expected-F3 &&
git add F3 &&
git rebase --continue &&
- git reset --hard topic@{1} &&
- test_must_fail git rebase -m --rerere-autoupdate master &&
- test "$(cat F2)" = "Resolved" &&
- test_must_fail git rebase --continue &&
- test "$(cat F3)" = "Resolved" &&
- git rebase --continue
+ git reset --hard topic@{1}
'
+prepare () {
+ rm -fr .git/rebase-* &&
+ git reset --hard commit-new-file-F3-on-topic-branch &&
+ git checkout master &&
+ test_config rerere.enabled true
+}
+
+test_rerere_autoupdate () {
+ action=$1 &&
+ test_expect_success "rebase $action --continue remembers --rerere-autoupdate" '
+ prepare &&
+ test_must_fail git rebase $action --rerere-autoupdate master topic &&
+ test_cmp expected-F2 F2 &&
+ git diff-files --quiet &&
+ test_must_fail git rebase --continue &&
+ test_cmp expected-F3 F3 &&
+ git diff-files --quiet &&
+ git rebase --continue
+ '
+
+ test_expect_success "rebase $action --continue honors rerere.autoUpdate" '
+ prepare &&
+ test_config rerere.autoupdate true &&
+ test_must_fail git rebase $action master topic &&
+ test_cmp expected-F2 F2 &&
+ git diff-files --quiet &&
+ test_must_fail git rebase --continue &&
+ test_cmp expected-F3 F3 &&
+ git diff-files --quiet &&
+ git rebase --continue
+ '
+
+ test_expect_success "rebase $action --continue remembers --no-rerere-autoupdate" '
+ prepare &&
+ test_config rerere.autoupdate true &&
+ test_must_fail git rebase $action --no-rerere-autoupdate master topic &&
+ test_cmp expected-F2 F2 &&
+ test_must_fail git diff-files --quiet &&
+ git add F2 &&
+ test_must_fail git rebase --continue &&
+ test_cmp expected-F3 F3 &&
+ test_must_fail git diff-files --quiet &&
+ git add F3 &&
+ git rebase --continue
+ '
+}
+
+test_rerere_autoupdate
+test_rerere_autoupdate -m
+GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR
+test_rerere_autoupdate -i
+test_rerere_autoupdate --preserve-merges
+
test_done
. ./test-lib.sh
test_expect_success setup '
- echo foo >foo &&
- git add foo && test_tick && git commit -q -m 1 &&
- echo foo-master >foo &&
- git add foo && test_tick && git commit -q -m 2 &&
-
- git checkout -b dev HEAD^ &&
- echo foo-dev >foo &&
- git add foo && test_tick && git commit -q -m 3 &&
+ test_commit foo &&
+ test_commit foo-master foo &&
+ test_commit bar-master bar &&
+
+ git checkout -b dev foo &&
+ test_commit foo-dev foo &&
+ test_commit bar-dev bar &&
git config rerere.enabled true
'
'
test_expect_success 'fixup' '
- echo foo-dev >foo &&
- git add foo && test_tick && git commit -q -m 4 &&
- git reset --hard HEAD^ &&
- echo foo-dev >expect
+ echo foo-resolved >foo &&
+ echo bar-resolved >bar &&
+ git commit -am resolved &&
+ cp foo foo-expect &&
+ cp bar bar-expect &&
+ git reset --hard HEAD^
'
-test_expect_success 'cherry-pick conflict' '
- test_must_fail git cherry-pick master &&
- test_cmp expect foo
+test_expect_success 'cherry-pick conflict with --rerere-autoupdate' '
+ test_must_fail git cherry-pick --rerere-autoupdate foo..bar-master &&
+ test_cmp foo-expect foo &&
+ git diff-files --quiet &&
+ test_must_fail git cherry-pick --continue &&
+ test_cmp bar-expect bar &&
+ git diff-files --quiet &&
+ git cherry-pick --continue &&
+ git reset --hard bar-dev
+'
+
+test_expect_success 'cherry-pick conflict repsects rerere.autoUpdate' '
+ test_config rerere.autoUpdate true &&
+ test_must_fail git cherry-pick foo..bar-master &&
+ test_cmp foo-expect foo &&
+ git diff-files --quiet &&
+ test_must_fail git cherry-pick --continue &&
+ test_cmp bar-expect bar &&
+ git diff-files --quiet &&
+ git cherry-pick --continue &&
+ git reset --hard bar-dev
+'
+
+test_expect_success 'cherry-pick conflict with --no-rerere-autoupdate' '
+ test_config rerere.autoUpdate true &&
+ test_must_fail git cherry-pick --no-rerere-autoupdate foo..bar-master &&
+ test_cmp foo-expect foo &&
+ test_must_fail git diff-files --quiet &&
+ git add foo &&
+ test_must_fail git cherry-pick --continue &&
+ test_cmp bar-expect bar &&
+ test_must_fail git diff-files --quiet &&
+ git add bar &&
+ git cherry-pick --continue &&
+ git reset --hard bar-dev
+'
+
+test_expect_success 'cherry-pick --continue rejects --rerere-autoupdate' '
+ test_must_fail git cherry-pick --rerere-autoupdate foo..bar-master &&
+ test_cmp foo-expect foo &&
+ git diff-files --quiet &&
+ test_must_fail git cherry-pick --continue --rerere-autoupdate >actual 2>&1 &&
+ echo "fatal: cherry-pick: --rerere-autoupdate cannot be used with --continue" >expect &&
+ test_i18ncmp expect actual &&
+ test_must_fail git cherry-pick --continue --no-rerere-autoupdate >actual 2>&1 &&
+ echo "fatal: cherry-pick: --no-rerere-autoupdate cannot be used with --continue" >expect &&
+ test_i18ncmp expect actual &&
+ git cherry-pick --abort
'
-test_expect_success 'reconfigure' '
- git config rerere.enabled false &&
- git reset --hard
+test_expect_success 'cherry-pick --rerere-autoupdate more than once' '
+ test_must_fail git cherry-pick --rerere-autoupdate --rerere-autoupdate foo..bar-master &&
+ test_cmp foo-expect foo &&
+ git diff-files --quiet &&
+ git cherry-pick --abort &&
+ test_must_fail git cherry-pick --rerere-autoupdate --no-rerere-autoupdate --rerere-autoupdate foo..bar-master &&
+ test_cmp foo-expect foo &&
+ git diff-files --quiet &&
+ git cherry-pick --abort &&
+ test_must_fail git cherry-pick --rerere-autoupdate --no-rerere-autoupdate foo..bar-master &&
+ test_must_fail git diff-files --quiet &&
+ git cherry-pick --abort
'
test_expect_success 'cherry-pick conflict without rerere' '
+ test_config rerere.enabled false &&
test_must_fail git cherry-pick master &&
test_must_fail test_cmp expect foo
'