Merge branch 'pw/rebase-of-a-tag-fix'
"git rebase <upstream> <tag>" failed when aborted in the middle, as it mistakenly tried to write the tag object instead of peeling it to HEAD. * pw/rebase-of-a-tag-fix: rebase: dereference tags rebase: use lookup_commit_reference_by_name() rebase: use our standard error return value t3407: rework rebase --quit tests t3407: strengthen rebase --abort tests t3407: use test_path_is_missing t3407: rename a variable t3407: use test_cmp_rev t3407: use test_commit t3407: run tests in $TEST_DIRECTORY
This commit is contained in:
@ -765,17 +765,6 @@ static int finish_rebase(struct rebase_options *opts)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct commit *peel_committish(const char *name)
|
|
||||||
{
|
|
||||||
struct object *obj;
|
|
||||||
struct object_id oid;
|
|
||||||
|
|
||||||
if (get_oid(name, &oid))
|
|
||||||
return NULL;
|
|
||||||
obj = parse_object(the_repository, &oid);
|
|
||||||
return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void add_var(struct strbuf *buf, const char *name, const char *value)
|
static void add_var(struct strbuf *buf, const char *name, const char *value)
|
||||||
{
|
{
|
||||||
if (!value)
|
if (!value)
|
||||||
@ -1580,7 +1569,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
die(_("could not move back to %s"),
|
die(_("could not move back to %s"),
|
||||||
oid_to_hex(&options.orig_head));
|
oid_to_hex(&options.orig_head));
|
||||||
remove_branch_state(the_repository, 0);
|
remove_branch_state(the_repository, 0);
|
||||||
ret = !!finish_rebase(&options);
|
ret = finish_rebase(&options);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
case ACTION_QUIT: {
|
case ACTION_QUIT: {
|
||||||
@ -1589,11 +1578,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
struct replay_opts replay = REPLAY_OPTS_INIT;
|
struct replay_opts replay = REPLAY_OPTS_INIT;
|
||||||
|
|
||||||
replay.action = REPLAY_INTERACTIVE_REBASE;
|
replay.action = REPLAY_INTERACTIVE_REBASE;
|
||||||
ret = !!sequencer_remove_state(&replay);
|
ret = sequencer_remove_state(&replay);
|
||||||
} else {
|
} else {
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
strbuf_addstr(&buf, options.state_dir);
|
strbuf_addstr(&buf, options.state_dir);
|
||||||
ret = !!remove_dir_recursively(&buf, 0);
|
ret = remove_dir_recursively(&buf, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
error(_("could not remove '%s'"),
|
error(_("could not remove '%s'"),
|
||||||
options.state_dir);
|
options.state_dir);
|
||||||
@ -1851,7 +1840,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
if (!strcmp(options.upstream_name, "-"))
|
if (!strcmp(options.upstream_name, "-"))
|
||||||
options.upstream_name = "@{-1}";
|
options.upstream_name = "@{-1}";
|
||||||
}
|
}
|
||||||
options.upstream = peel_committish(options.upstream_name);
|
options.upstream =
|
||||||
|
lookup_commit_reference_by_name(options.upstream_name);
|
||||||
if (!options.upstream)
|
if (!options.upstream)
|
||||||
die(_("invalid upstream '%s'"), options.upstream_name);
|
die(_("invalid upstream '%s'"), options.upstream_name);
|
||||||
options.upstream_arg = options.upstream_name;
|
options.upstream_arg = options.upstream_name;
|
||||||
@ -1894,7 +1884,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
options.onto = lookup_commit_or_die(&merge_base,
|
options.onto = lookup_commit_or_die(&merge_base,
|
||||||
options.onto_name);
|
options.onto_name);
|
||||||
} else {
|
} else {
|
||||||
options.onto = peel_committish(options.onto_name);
|
options.onto =
|
||||||
|
lookup_commit_reference_by_name(options.onto_name);
|
||||||
if (!options.onto)
|
if (!options.onto)
|
||||||
die(_("Does not point to a valid commit '%s'"),
|
die(_("Does not point to a valid commit '%s'"),
|
||||||
options.onto_name);
|
options.onto_name);
|
||||||
@ -1919,13 +1910,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
die_if_checked_out(buf.buf, 1);
|
die_if_checked_out(buf.buf, 1);
|
||||||
options.head_name = xstrdup(buf.buf);
|
options.head_name = xstrdup(buf.buf);
|
||||||
/* If not is it a valid ref (branch or commit)? */
|
/* If not is it a valid ref (branch or commit)? */
|
||||||
} else if (!get_oid(branch_name, &options.orig_head) &&
|
} else {
|
||||||
lookup_commit_reference(the_repository,
|
struct commit *commit =
|
||||||
&options.orig_head))
|
lookup_commit_reference_by_name(branch_name);
|
||||||
|
if (!commit)
|
||||||
|
die(_("no such branch/commit '%s'"),
|
||||||
|
branch_name);
|
||||||
|
oidcpy(&options.orig_head, &commit->object.oid);
|
||||||
options.head_name = NULL;
|
options.head_name = NULL;
|
||||||
else
|
}
|
||||||
die(_("no such branch/commit '%s'"),
|
|
||||||
branch_name);
|
|
||||||
} else if (argc == 0) {
|
} else if (argc == 0) {
|
||||||
/* Do not need to switch branches, we are already on it. */
|
/* Do not need to switch branches, we are already on it. */
|
||||||
options.head_name =
|
options.head_name =
|
||||||
@ -1965,7 +1958,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
if (require_clean_work_tree(the_repository, "rebase",
|
if (require_clean_work_tree(the_repository, "rebase",
|
||||||
_("Please commit or stash them."), 1, 1)) {
|
_("Please commit or stash them."), 1, 1)) {
|
||||||
ret = 1;
|
ret = -1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2000,7 +1993,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
|
RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
|
||||||
NULL, buf.buf,
|
NULL, buf.buf,
|
||||||
DEFAULT_REFLOG_ACTION) < 0) {
|
DEFAULT_REFLOG_ACTION) < 0) {
|
||||||
ret = !!error(_("could not switch to "
|
ret = error(_("could not switch to "
|
||||||
"%s"),
|
"%s"),
|
||||||
options.switch_to);
|
options.switch_to);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2015,7 +2008,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
else
|
else
|
||||||
printf(_("Current branch %s is up to date.\n"),
|
printf(_("Current branch %s is up to date.\n"),
|
||||||
branch_name);
|
branch_name);
|
||||||
ret = !!finish_rebase(&options);
|
ret = finish_rebase(&options);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (!(options.flags & REBASE_NO_QUIET))
|
} else if (!(options.flags & REBASE_NO_QUIET))
|
||||||
; /* be quiet */
|
; /* be quiet */
|
||||||
@ -2093,7 +2086,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
RESET_HEAD_REFS_ONLY, "HEAD", msg.buf,
|
RESET_HEAD_REFS_ONLY, "HEAD", msg.buf,
|
||||||
DEFAULT_REFLOG_ACTION);
|
DEFAULT_REFLOG_ACTION);
|
||||||
strbuf_release(&msg);
|
strbuf_release(&msg);
|
||||||
ret = !!finish_rebase(&options);
|
ret = finish_rebase(&options);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2107,7 +2100,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
|
|||||||
options.revisions = revisions.buf;
|
options.revisions = revisions.buf;
|
||||||
|
|
||||||
run_rebase:
|
run_rebase:
|
||||||
ret = !!run_specific_rebase(&options, action);
|
ret = run_specific_rebase(&options, action);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
@ -2118,5 +2111,5 @@ cleanup:
|
|||||||
free(options.strategy);
|
free(options.strategy);
|
||||||
strbuf_release(&options.git_format_patch_opt);
|
strbuf_release(&options.git_format_patch_opt);
|
||||||
free(squash_onto_name);
|
free(squash_onto_name);
|
||||||
return ret;
|
return !!ret;
|
||||||
}
|
}
|
||||||
|
@ -7,77 +7,77 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|||||||
|
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
### Test that we handle space characters properly
|
|
||||||
work_dir="$(pwd)/test dir"
|
|
||||||
|
|
||||||
test_expect_success setup '
|
test_expect_success setup '
|
||||||
mkdir -p "$work_dir" &&
|
test_commit a a a &&
|
||||||
cd "$work_dir" &&
|
|
||||||
git init &&
|
|
||||||
echo a > a &&
|
|
||||||
git add a &&
|
|
||||||
git commit -m a &&
|
|
||||||
git branch to-rebase &&
|
git branch to-rebase &&
|
||||||
|
|
||||||
echo b > a &&
|
test_commit --annotate b a b &&
|
||||||
git commit -a -m b &&
|
test_commit --annotate c a c &&
|
||||||
echo c > a &&
|
|
||||||
git commit -a -m c &&
|
|
||||||
|
|
||||||
git checkout to-rebase &&
|
git checkout to-rebase &&
|
||||||
echo d > a &&
|
test_commit "merge should fail on this" a d d &&
|
||||||
git commit -a -m "merge should fail on this" &&
|
test_commit --annotate "merge should fail on this, too" a e pre-rebase
|
||||||
echo e > a &&
|
|
||||||
git commit -a -m "merge should fail on this, too" &&
|
|
||||||
git branch pre-rebase
|
|
||||||
'
|
'
|
||||||
|
|
||||||
|
# Check that HEAD is equal to "pre-rebase" and the current branch is
|
||||||
|
# "to-rebase"
|
||||||
|
check_head() {
|
||||||
|
test_cmp_rev HEAD pre-rebase^{commit} &&
|
||||||
|
test "$(git symbolic-ref HEAD)" = refs/heads/to-rebase
|
||||||
|
}
|
||||||
|
|
||||||
testrebase() {
|
testrebase() {
|
||||||
type=$1
|
type=$1
|
||||||
dotest=$2
|
state_dir=$2
|
||||||
|
|
||||||
test_expect_success "rebase$type --abort" '
|
test_expect_success "rebase$type --abort" '
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
# Clean up the state from the previous one
|
||||||
git reset --hard pre-rebase &&
|
git reset --hard pre-rebase &&
|
||||||
test_must_fail git rebase$type main &&
|
test_must_fail git rebase$type main &&
|
||||||
test_path_is_dir "$dotest" &&
|
test_path_is_dir "$state_dir" &&
|
||||||
git rebase --abort &&
|
git rebase --abort &&
|
||||||
test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
|
check_head &&
|
||||||
test ! -d "$dotest"
|
test_path_is_missing "$state_dir"
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "rebase$type --abort after --skip" '
|
test_expect_success "rebase$type --abort after --skip" '
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
# Clean up the state from the previous one
|
||||||
git reset --hard pre-rebase &&
|
git reset --hard pre-rebase &&
|
||||||
test_must_fail git rebase$type main &&
|
test_must_fail git rebase$type main &&
|
||||||
test_path_is_dir "$dotest" &&
|
test_path_is_dir "$state_dir" &&
|
||||||
test_must_fail git rebase --skip &&
|
test_must_fail git rebase --skip &&
|
||||||
test $(git rev-parse HEAD) = $(git rev-parse main) &&
|
test_cmp_rev HEAD main &&
|
||||||
git rebase --abort &&
|
git rebase --abort &&
|
||||||
test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
|
check_head &&
|
||||||
test ! -d "$dotest"
|
test_path_is_missing "$state_dir"
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "rebase$type --abort after --continue" '
|
test_expect_success "rebase$type --abort after --continue" '
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
# Clean up the state from the previous one
|
||||||
git reset --hard pre-rebase &&
|
git reset --hard pre-rebase &&
|
||||||
test_must_fail git rebase$type main &&
|
test_must_fail git rebase$type main &&
|
||||||
test_path_is_dir "$dotest" &&
|
test_path_is_dir "$state_dir" &&
|
||||||
echo c > a &&
|
echo c > a &&
|
||||||
echo d >> a &&
|
echo d >> a &&
|
||||||
git add a &&
|
git add a &&
|
||||||
test_must_fail git rebase --continue &&
|
test_must_fail git rebase --continue &&
|
||||||
test $(git rev-parse HEAD) != $(git rev-parse main) &&
|
test_cmp_rev ! HEAD main &&
|
||||||
git rebase --abort &&
|
git rebase --abort &&
|
||||||
test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
|
check_head &&
|
||||||
test ! -d "$dotest"
|
test_path_is_missing "$state_dir"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success "rebase$type --abort when checking out a tag" '
|
||||||
|
test_when_finished "git symbolic-ref HEAD refs/heads/to-rebase" &&
|
||||||
|
git reset --hard a -- &&
|
||||||
|
test_must_fail git rebase$type --onto b c pre-rebase &&
|
||||||
|
test_cmp_rev HEAD b^{commit} &&
|
||||||
|
git rebase --abort &&
|
||||||
|
test_cmp_rev HEAD pre-rebase^{commit} &&
|
||||||
|
! git symbolic-ref HEAD
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "rebase$type --abort does not update reflog" '
|
test_expect_success "rebase$type --abort does not update reflog" '
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
# Clean up the state from the previous one
|
||||||
git reset --hard pre-rebase &&
|
git reset --hard pre-rebase &&
|
||||||
git reflog show to-rebase > reflog_before &&
|
git reflog show to-rebase > reflog_before &&
|
||||||
@ -89,7 +89,6 @@ testrebase() {
|
|||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'rebase --abort can not be used with other options' '
|
test_expect_success 'rebase --abort can not be used with other options' '
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
# Clean up the state from the previous one
|
||||||
git reset --hard pre-rebase &&
|
git reset --hard pre-rebase &&
|
||||||
test_must_fail git rebase$type main &&
|
test_must_fail git rebase$type main &&
|
||||||
@ -97,33 +96,21 @@ testrebase() {
|
|||||||
test_must_fail git rebase --abort -v &&
|
test_must_fail git rebase --abort -v &&
|
||||||
git rebase --abort
|
git rebase --abort
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success "rebase$type --quit" '
|
||||||
|
test_when_finished "git symbolic-ref HEAD refs/heads/to-rebase" &&
|
||||||
|
# Clean up the state from the previous one
|
||||||
|
git reset --hard pre-rebase &&
|
||||||
|
test_must_fail git rebase$type main &&
|
||||||
|
test_path_is_dir $state_dir &&
|
||||||
|
head_before=$(git rev-parse HEAD) &&
|
||||||
|
git rebase --quit &&
|
||||||
|
test_cmp_rev HEAD $head_before &&
|
||||||
|
test_path_is_missing .git/rebase-apply
|
||||||
|
'
|
||||||
}
|
}
|
||||||
|
|
||||||
testrebase " --apply" .git/rebase-apply
|
testrebase " --apply" .git/rebase-apply
|
||||||
testrebase " --merge" .git/rebase-merge
|
testrebase " --merge" .git/rebase-merge
|
||||||
|
|
||||||
test_expect_success 'rebase --apply --quit' '
|
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
|
||||||
git reset --hard pre-rebase &&
|
|
||||||
test_must_fail git rebase --apply main &&
|
|
||||||
test_path_is_dir .git/rebase-apply &&
|
|
||||||
head_before=$(git rev-parse HEAD) &&
|
|
||||||
git rebase --quit &&
|
|
||||||
test $(git rev-parse HEAD) = $head_before &&
|
|
||||||
test ! -d .git/rebase-apply
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'rebase --merge --quit' '
|
|
||||||
cd "$work_dir" &&
|
|
||||||
# Clean up the state from the previous one
|
|
||||||
git reset --hard pre-rebase &&
|
|
||||||
test_must_fail git rebase --merge main &&
|
|
||||||
test_path_is_dir .git/rebase-merge &&
|
|
||||||
head_before=$(git rev-parse HEAD) &&
|
|
||||||
git rebase --quit &&
|
|
||||||
test $(git rev-parse HEAD) = $head_before &&
|
|
||||||
test ! -d .git/rebase-merge
|
|
||||||
'
|
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user