Merge branch 'rs/branch-delete-bisect-warning'
'git branch -d' has been taught to report when a branch cannot be deleted because it is being used in an active bisect run. * rs/branch-delete-bisect-warning: branch: report active bisect run when rejecting deletemain
commit
67b1d2fa43
80
branch.c
80
branch.c
|
|
@ -385,6 +385,39 @@ int validate_branchname(const char *name, struct strbuf *ref)
|
||||||
static int initialized_checked_out_branches;
|
static int initialized_checked_out_branches;
|
||||||
static struct strmap current_checked_out_branches = STRMAP_INIT;
|
static struct strmap current_checked_out_branches = STRMAP_INIT;
|
||||||
|
|
||||||
|
enum branch_checkout_kind {
|
||||||
|
BRANCH_CHECKOUT_KIND_CHECKOUT,
|
||||||
|
BRANCH_CHECKOUT_KIND_REBASE,
|
||||||
|
BRANCH_CHECKOUT_KIND_BISECT,
|
||||||
|
BRANCH_CHECKOUT_KIND_UPDATE_REF,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct checked_out_branch {
|
||||||
|
char *refname;
|
||||||
|
char *path;
|
||||||
|
enum branch_checkout_kind kind;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct checked_out_branch *checked_out_branches;
|
||||||
|
static size_t checked_out_branches_alloc, checked_out_branches_nr;
|
||||||
|
|
||||||
|
static void register_checked_out_branch(const char *prefix, const char *name,
|
||||||
|
const char *path,
|
||||||
|
enum branch_checkout_kind kind)
|
||||||
|
{
|
||||||
|
char *refname = xstrfmt("%s%s", prefix, name);
|
||||||
|
char *path_copy = xstrdup(path);
|
||||||
|
|
||||||
|
ALLOC_GROW(checked_out_branches, checked_out_branches_nr + 1,
|
||||||
|
checked_out_branches_alloc);
|
||||||
|
checked_out_branches[checked_out_branches_nr].refname = refname;
|
||||||
|
checked_out_branches[checked_out_branches_nr].path = path_copy;
|
||||||
|
checked_out_branches[checked_out_branches_nr].kind = kind;
|
||||||
|
checked_out_branches_nr++;
|
||||||
|
|
||||||
|
strmap_put(¤t_checked_out_branches, refname, path_copy);
|
||||||
|
}
|
||||||
|
|
||||||
static void prepare_checked_out_branches(void)
|
static void prepare_checked_out_branches(void)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
@ -397,7 +430,7 @@ static void prepare_checked_out_branches(void)
|
||||||
worktrees = get_worktrees(the_repository);
|
worktrees = get_worktrees(the_repository);
|
||||||
|
|
||||||
while (worktrees[i]) {
|
while (worktrees[i]) {
|
||||||
char *old, *wt_gitdir;
|
char *wt_gitdir;
|
||||||
struct wt_status_state state = { 0 };
|
struct wt_status_state state = { 0 };
|
||||||
struct worktree *wt = worktrees[i++];
|
struct worktree *wt = worktrees[i++];
|
||||||
struct string_list update_refs = STRING_LIST_INIT_DUP;
|
struct string_list update_refs = STRING_LIST_INIT_DUP;
|
||||||
|
|
@ -406,34 +439,25 @@ static void prepare_checked_out_branches(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wt->head_ref) {
|
if (wt->head_ref) {
|
||||||
old = strmap_put(¤t_checked_out_branches,
|
register_checked_out_branch("", wt->head_ref, wt->path,
|
||||||
wt->head_ref,
|
BRANCH_CHECKOUT_KIND_CHECKOUT);
|
||||||
xstrdup(wt->path));
|
|
||||||
free(old);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wt_status_check_rebase(wt, &state) &&
|
if (wt_status_check_rebase(wt, &state) &&
|
||||||
(state.rebase_in_progress || state.rebase_interactive_in_progress) &&
|
(state.rebase_in_progress || state.rebase_interactive_in_progress) &&
|
||||||
state.branch) {
|
state.branch) {
|
||||||
struct strbuf ref = STRBUF_INIT;
|
register_checked_out_branch("refs/heads/", state.branch,
|
||||||
strbuf_addf(&ref, "refs/heads/%s", state.branch);
|
wt->path,
|
||||||
old = strmap_put(¤t_checked_out_branches,
|
BRANCH_CHECKOUT_KIND_REBASE);
|
||||||
ref.buf,
|
|
||||||
xstrdup(wt->path));
|
|
||||||
free(old);
|
|
||||||
strbuf_release(&ref);
|
|
||||||
}
|
}
|
||||||
wt_status_state_free_buffers(&state);
|
wt_status_state_free_buffers(&state);
|
||||||
|
|
||||||
if (wt_status_check_bisect(wt, &state) &&
|
if (wt_status_check_bisect(wt, &state) &&
|
||||||
state.bisecting_from) {
|
state.bisecting_from) {
|
||||||
struct strbuf ref = STRBUF_INIT;
|
register_checked_out_branch("refs/heads/",
|
||||||
strbuf_addf(&ref, "refs/heads/%s", state.bisecting_from);
|
state.bisecting_from,
|
||||||
old = strmap_put(¤t_checked_out_branches,
|
wt->path,
|
||||||
ref.buf,
|
BRANCH_CHECKOUT_KIND_BISECT);
|
||||||
xstrdup(wt->path));
|
|
||||||
free(old);
|
|
||||||
strbuf_release(&ref);
|
|
||||||
}
|
}
|
||||||
wt_status_state_free_buffers(&state);
|
wt_status_state_free_buffers(&state);
|
||||||
|
|
||||||
|
|
@ -442,10 +466,9 @@ static void prepare_checked_out_branches(void)
|
||||||
&update_refs)) {
|
&update_refs)) {
|
||||||
struct string_list_item *item;
|
struct string_list_item *item;
|
||||||
for_each_string_list_item(item, &update_refs) {
|
for_each_string_list_item(item, &update_refs) {
|
||||||
old = strmap_put(¤t_checked_out_branches,
|
register_checked_out_branch("", item->string,
|
||||||
item->string,
|
wt->path,
|
||||||
xstrdup(wt->path));
|
BRANCH_CHECKOUT_KIND_UPDATE_REF);
|
||||||
free(old);
|
|
||||||
}
|
}
|
||||||
string_list_clear(&update_refs, 1);
|
string_list_clear(&update_refs, 1);
|
||||||
}
|
}
|
||||||
|
|
@ -462,6 +485,17 @@ const char *branch_checked_out(const char *refname)
|
||||||
return strmap_get(¤t_checked_out_branches, refname);
|
return strmap_get(¤t_checked_out_branches, refname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *branch_bisecting(const char *refname)
|
||||||
|
{
|
||||||
|
prepare_checked_out_branches();
|
||||||
|
for (size_t i = 0; i < checked_out_branches_nr; i++) {
|
||||||
|
if (!strcmp(refname, checked_out_branches[i].refname) &&
|
||||||
|
checked_out_branches[i].kind == BRANCH_CHECKOUT_KIND_BISECT)
|
||||||
|
return checked_out_branches[i].path;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if a branch 'name' can be created as a new branch; die otherwise.
|
* Check if a branch 'name' can be created as a new branch; die otherwise.
|
||||||
* 'force' can be used when it is OK for the named branch already exists.
|
* 'force' can be used when it is OK for the named branch already exists.
|
||||||
|
|
|
||||||
6
branch.h
6
branch.h
|
|
@ -106,6 +106,12 @@ void create_branches_recursively(struct repository *r, const char *name,
|
||||||
*/
|
*/
|
||||||
const char *branch_checked_out(const char *refname);
|
const char *branch_checked_out(const char *refname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the branch at 'refname' is currently used for bisecting in a
|
||||||
|
* worktree, then return the path to that worktree.
|
||||||
|
*/
|
||||||
|
const char *branch_bisecting(const char *refname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if 'name' can be a valid name for a branch; die otherwise.
|
* Check if 'name' can be a valid name for a branch; die otherwise.
|
||||||
* Return 1 if the named branch already exists; return 0 otherwise.
|
* Return 1 if the named branch already exists; return 0 otherwise.
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,13 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
|
||||||
|
|
||||||
if (kinds == FILTER_REFS_BRANCHES) {
|
if (kinds == FILTER_REFS_BRANCHES) {
|
||||||
const char *path;
|
const char *path;
|
||||||
|
if ((path = branch_bisecting(name))) {
|
||||||
|
error(_("cannot delete branch '%s' "
|
||||||
|
"used by worktree at '%s' for bisect"),
|
||||||
|
bname.buf, path);
|
||||||
|
ret = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if ((path = branch_checked_out(name))) {
|
if ((path = branch_checked_out(name))) {
|
||||||
error(_("cannot delete branch '%s' "
|
error(_("cannot delete branch '%s' "
|
||||||
"used by worktree at '%s'"),
|
"used by worktree at '%s'"),
|
||||||
|
|
|
||||||
|
|
@ -930,7 +930,7 @@ test_expect_success 'deleting currently checked out branch fails' '
|
||||||
git worktree add -b my7 my7 &&
|
git worktree add -b my7 my7 &&
|
||||||
test_must_fail git -C my7 branch -d my7 &&
|
test_must_fail git -C my7 branch -d my7 &&
|
||||||
test_must_fail git branch -d my7 2>actual &&
|
test_must_fail git branch -d my7 2>actual &&
|
||||||
test_grep "^error: cannot delete branch .my7. used by worktree at " actual &&
|
test_grep "^error: cannot delete branch '"'"'my7'"'"' used by worktree at '"'.*'\$"'" actual &&
|
||||||
rm -r my7 &&
|
rm -r my7 &&
|
||||||
git worktree prune
|
git worktree prune
|
||||||
'
|
'
|
||||||
|
|
@ -941,7 +941,7 @@ test_expect_success 'deleting in-use branch fails' '
|
||||||
git -C my7 bisect start HEAD HEAD~2 &&
|
git -C my7 bisect start HEAD HEAD~2 &&
|
||||||
test_must_fail git -C my7 branch -d my7 &&
|
test_must_fail git -C my7 branch -d my7 &&
|
||||||
test_must_fail git branch -d my7 2>actual &&
|
test_must_fail git branch -d my7 2>actual &&
|
||||||
test_grep "^error: cannot delete branch .my7. used by worktree at " actual &&
|
test_grep "^error: cannot delete branch '"'"'my7'"'"' used by worktree at '"'.*' for bisect\$"'" actual &&
|
||||||
rm -r my7 &&
|
rm -r my7 &&
|
||||||
git worktree prune
|
git worktree prune
|
||||||
'
|
'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue