branch: make create_branch() always create a branch
With the previous commit, there are no more invocations of create_branch() that do not create a branch because: * BRANCH_TRACK_OVERRIDE is no longer passed * clobber_head_ok = true and force = false is never passed Assert these situations, delete dead code and ensure that we're handling clobber_head_ok and force correctly by introducing tests for `git branch --force`. As a result, create_branch() now always creates a branch. Helped-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Glen Choo <chooglen@google.com> Reviewed-by: Jonathan Tan <jonathantanmy@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
parent
e89f151db1
commit
bc0893cf3b
55
branch.c
55
branch.c
|
@ -429,15 +429,19 @@ void create_branch(struct repository *r,
|
||||||
char *real_ref;
|
char *real_ref;
|
||||||
struct strbuf ref = STRBUF_INIT;
|
struct strbuf ref = STRBUF_INIT;
|
||||||
int forcing = 0;
|
int forcing = 0;
|
||||||
int dont_change_ref = 0;
|
struct ref_transaction *transaction;
|
||||||
|
struct strbuf err = STRBUF_INIT;
|
||||||
|
char *msg;
|
||||||
|
|
||||||
if ((track == BRANCH_TRACK_OVERRIDE || clobber_head_ok)
|
if (track == BRANCH_TRACK_OVERRIDE)
|
||||||
? validate_branchname(name, &ref)
|
BUG("'track' cannot be BRANCH_TRACK_OVERRIDE. Did you mean to call dwim_and_setup_tracking()?");
|
||||||
: validate_new_branchname(name, &ref, force)) {
|
if (clobber_head_ok && !force)
|
||||||
if (!force)
|
BUG("'clobber_head_ok' can only be used with 'force'");
|
||||||
dont_change_ref = 1;
|
|
||||||
else
|
if (clobber_head_ok ?
|
||||||
forcing = 1;
|
validate_branchname(name, &ref) :
|
||||||
|
validate_new_branchname(name, &ref, force)) {
|
||||||
|
forcing = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwim_branch_start(r, start_name, track, &real_ref, &oid);
|
dwim_branch_start(r, start_name, track, &real_ref, &oid);
|
||||||
|
@ -445,27 +449,20 @@ void create_branch(struct repository *r,
|
||||||
if (reflog)
|
if (reflog)
|
||||||
log_all_ref_updates = LOG_REFS_NORMAL;
|
log_all_ref_updates = LOG_REFS_NORMAL;
|
||||||
|
|
||||||
if (!dont_change_ref) {
|
if (forcing)
|
||||||
struct ref_transaction *transaction;
|
msg = xstrfmt("branch: Reset to %s", start_name);
|
||||||
struct strbuf err = STRBUF_INIT;
|
else
|
||||||
char *msg;
|
msg = xstrfmt("branch: Created from %s", start_name);
|
||||||
|
transaction = ref_transaction_begin(&err);
|
||||||
if (forcing)
|
if (!transaction ||
|
||||||
msg = xstrfmt("branch: Reset to %s", start_name);
|
ref_transaction_update(transaction, ref.buf,
|
||||||
else
|
&oid, forcing ? NULL : null_oid(),
|
||||||
msg = xstrfmt("branch: Created from %s", start_name);
|
0, msg, &err) ||
|
||||||
|
ref_transaction_commit(transaction, &err))
|
||||||
transaction = ref_transaction_begin(&err);
|
die("%s", err.buf);
|
||||||
if (!transaction ||
|
ref_transaction_free(transaction);
|
||||||
ref_transaction_update(transaction, ref.buf,
|
strbuf_release(&err);
|
||||||
&oid, forcing ? NULL : null_oid(),
|
free(msg);
|
||||||
0, msg, &err) ||
|
|
||||||
ref_transaction_commit(transaction, &err))
|
|
||||||
die("%s", err.buf);
|
|
||||||
ref_transaction_free(transaction);
|
|
||||||
strbuf_release(&err);
|
|
||||||
free(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (real_ref && track)
|
if (real_ref && track)
|
||||||
setup_tracking(ref.buf + 11, real_ref, track, quiet);
|
setup_tracking(ref.buf + 11, real_ref, track, quiet);
|
||||||
|
|
4
branch.h
4
branch.h
|
@ -52,8 +52,8 @@ void dwim_and_setup_tracking(struct repository *r, const char *new_ref,
|
||||||
*
|
*
|
||||||
* - force enables overwriting an existing (non-head) branch
|
* - force enables overwriting an existing (non-head) branch
|
||||||
*
|
*
|
||||||
* - clobber_head_ok allows the currently checked out (hence existing)
|
* - clobber_head_ok, when enabled with 'force', allows the currently
|
||||||
* branch to be overwritten; without 'force', it has no effect.
|
* checked out (head) branch to be overwritten
|
||||||
*
|
*
|
||||||
* - reflog creates a reflog for the branch
|
* - reflog creates a reflog for the branch
|
||||||
*
|
*
|
||||||
|
|
|
@ -42,6 +42,23 @@ test_expect_success 'git branch abc should create a branch' '
|
||||||
git branch abc && test_path_is_file .git/refs/heads/abc
|
git branch abc && test_path_is_file .git/refs/heads/abc
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git branch abc should fail when abc exists' '
|
||||||
|
test_must_fail git branch abc
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git branch --force abc should fail when abc is checked out' '
|
||||||
|
test_when_finished git switch main &&
|
||||||
|
git switch abc &&
|
||||||
|
test_must_fail git branch --force abc HEAD~1
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git branch --force abc should succeed when abc exists' '
|
||||||
|
git rev-parse HEAD~1 >expect &&
|
||||||
|
git branch --force abc HEAD~1 &&
|
||||||
|
git rev-parse abc >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'git branch a/b/c should create a branch' '
|
test_expect_success 'git branch a/b/c should create a branch' '
|
||||||
git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c
|
git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c
|
||||||
'
|
'
|
||||||
|
|
Loading…
Reference in New Issue