Skip to content

Commit 7fefa1b

Browse files
committed
Merge branch 'ds/branch-checked-out' into ds/rebase-update-ref
* ds/branch-checked-out: branch: drop unused worktrees variable fetch: stop passing around unused worktrees variable branch: fix branch_checked_out() leaks branch: use branch_checked_out() when deleting refs fetch: use new branch_checked_out() and add tests branch: check for bisects and rebases branch: add branch_checked_out() helper
2 parents e4a4b31 + 9bef0b1 commit 7fefa1b

File tree

5 files changed

+224
-45
lines changed

5 files changed

+224
-45
lines changed

branch.c

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "worktree.h"
1111
#include "submodule-config.h"
1212
#include "run-command.h"
13+
#include "strmap.h"
1314

1415
struct tracking {
1516
struct refspec_item spec;
@@ -369,6 +370,70 @@ int validate_branchname(const char *name, struct strbuf *ref)
369370
return ref_exists(ref->buf);
370371
}
371372

373+
static int initialized_checked_out_branches;
374+
static struct strmap current_checked_out_branches = STRMAP_INIT;
375+
376+
static void prepare_checked_out_branches(void)
377+
{
378+
int i = 0;
379+
struct worktree **worktrees;
380+
381+
if (initialized_checked_out_branches)
382+
return;
383+
initialized_checked_out_branches = 1;
384+
385+
worktrees = get_worktrees();
386+
387+
while (worktrees[i]) {
388+
char *old;
389+
struct wt_status_state state = { 0 };
390+
struct worktree *wt = worktrees[i++];
391+
392+
if (wt->is_bare)
393+
continue;
394+
395+
if (wt->head_ref) {
396+
old = strmap_put(&current_checked_out_branches,
397+
wt->head_ref,
398+
xstrdup(wt->path));
399+
free(old);
400+
}
401+
402+
if (wt_status_check_rebase(wt, &state) &&
403+
(state.rebase_in_progress || state.rebase_interactive_in_progress) &&
404+
state.branch) {
405+
struct strbuf ref = STRBUF_INIT;
406+
strbuf_addf(&ref, "refs/heads/%s", state.branch);
407+
old = strmap_put(&current_checked_out_branches,
408+
ref.buf,
409+
xstrdup(wt->path));
410+
free(old);
411+
strbuf_release(&ref);
412+
}
413+
wt_status_state_free_buffers(&state);
414+
415+
if (wt_status_check_bisect(wt, &state) &&
416+
state.branch) {
417+
struct strbuf ref = STRBUF_INIT;
418+
strbuf_addf(&ref, "refs/heads/%s", state.branch);
419+
old = strmap_put(&current_checked_out_branches,
420+
ref.buf,
421+
xstrdup(wt->path));
422+
free(old);
423+
strbuf_release(&ref);
424+
}
425+
wt_status_state_free_buffers(&state);
426+
}
427+
428+
free_worktrees(worktrees);
429+
}
430+
431+
const char *branch_checked_out(const char *refname)
432+
{
433+
prepare_checked_out_branches();
434+
return strmap_get(&current_checked_out_branches, refname);
435+
}
436+
372437
/*
373438
* Check if a branch 'name' can be created as a new branch; die otherwise.
374439
* 'force' can be used when it is OK for the named branch already exists.
@@ -377,23 +442,18 @@ int validate_branchname(const char *name, struct strbuf *ref)
377442
*/
378443
int validate_new_branchname(const char *name, struct strbuf *ref, int force)
379444
{
380-
struct worktree **worktrees;
381-
const struct worktree *wt;
382-
445+
const char *path;
383446
if (!validate_branchname(name, ref))
384447
return 0;
385448

386449
if (!force)
387450
die(_("a branch named '%s' already exists"),
388451
ref->buf + strlen("refs/heads/"));
389452

390-
worktrees = get_worktrees();
391-
wt = find_shared_symref(worktrees, "HEAD", ref->buf);
392-
if (wt && !wt->is_bare)
453+
if ((path = branch_checked_out(ref->buf)))
393454
die(_("cannot force update the branch '%s' "
394455
"checked out at '%s'"),
395-
ref->buf + strlen("refs/heads/"), wt->path);
396-
free_worktrees(worktrees);
456+
ref->buf + strlen("refs/heads/"), path);
397457

398458
return 1;
399459
}

branch.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ void create_branches_recursively(struct repository *r, const char *name,
101101
const char *tracking_name, int force,
102102
int reflog, int quiet, enum branch_track track,
103103
int dry_run);
104+
105+
/*
106+
* If the branch at 'refname' is currently checked out in a worktree,
107+
* then return the path to that worktree.
108+
*/
109+
const char *branch_checked_out(const char *refname);
110+
104111
/*
105112
* Check if 'name' can be a valid name for a branch; die otherwise.
106113
* Return 1 if the named branch already exists; return 0 otherwise.

builtin/branch.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,6 @@ static void delete_branch_config(const char *branchname)
204204
static int delete_branches(int argc, const char **argv, int force, int kinds,
205205
int quiet)
206206
{
207-
struct worktree **worktrees;
208207
struct commit *head_rev = NULL;
209208
struct object_id oid;
210209
char *name = NULL;
@@ -242,8 +241,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
242241
die(_("Couldn't look up commit object for HEAD"));
243242
}
244243

245-
worktrees = get_worktrees();
246-
247244
for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
248245
char *target = NULL;
249246
int flags = 0;
@@ -253,12 +250,11 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
253250
name = mkpathdup(fmt, bname.buf);
254251

255252
if (kinds == FILTER_REFS_BRANCHES) {
256-
const struct worktree *wt =
257-
find_shared_symref(worktrees, "HEAD", name);
258-
if (wt) {
253+
const char *path;
254+
if ((path = branch_checked_out(name))) {
259255
error(_("Cannot delete branch '%s' "
260256
"checked out at '%s'"),
261-
bname.buf, wt->path);
257+
bname.buf, path);
262258
ret = 1;
263259
continue;
264260
}
@@ -315,7 +311,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
315311

316312
free(name);
317313
strbuf_release(&bname);
318-
free_worktrees(worktrees);
319314

320315
return ret;
321316
}

builtin/fetch.c

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -881,11 +881,9 @@ static void format_display(struct strbuf *display, char code,
881881
static int update_local_ref(struct ref *ref,
882882
struct ref_transaction *transaction,
883883
const char *remote, const struct ref *remote_ref,
884-
struct strbuf *display, int summary_width,
885-
struct worktree **worktrees)
884+
struct strbuf *display, int summary_width)
886885
{
887886
struct commit *current = NULL, *updated;
888-
const struct worktree *wt;
889887
const char *pretty_ref = prettify_refname(ref->name);
890888
int fast_forward = 0;
891889

@@ -900,16 +898,14 @@ static int update_local_ref(struct ref *ref,
900898
}
901899

902900
if (!update_head_ok &&
903-
(wt = find_shared_symref(worktrees, "HEAD", ref->name)) &&
904-
!wt->is_bare && !is_null_oid(&ref->old_oid)) {
901+
!is_null_oid(&ref->old_oid) &&
902+
branch_checked_out(ref->name)) {
905903
/*
906904
* If this is the head, and it's not okay to update
907905
* the head, and the old value of the head isn't empty...
908906
*/
909907
format_display(display, '!', _("[rejected]"),
910-
wt->is_current ?
911-
_("can't fetch in current branch") :
912-
_("checked out in another worktree"),
908+
_("can't fetch into checked-out branch"),
913909
remote, pretty_ref, summary_width);
914910
return 1;
915911
}
@@ -1110,7 +1106,7 @@ N_("it took %.2f seconds to check forced updates; you can use\n"
11101106
static int store_updated_refs(const char *raw_url, const char *remote_name,
11111107
int connectivity_checked,
11121108
struct ref_transaction *transaction, struct ref *ref_map,
1113-
struct fetch_head *fetch_head, struct worktree **worktrees)
1109+
struct fetch_head *fetch_head)
11141110
{
11151111
int url_len, i, rc = 0;
11161112
struct strbuf note = STRBUF_INIT, err = STRBUF_INIT;
@@ -1240,8 +1236,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
12401236
strbuf_reset(&note);
12411237
if (ref) {
12421238
rc |= update_local_ref(ref, transaction, what,
1243-
rm, &note, summary_width,
1244-
worktrees);
1239+
rm, &note, summary_width);
12451240
free(ref);
12461241
} else if (write_fetch_head || dry_run) {
12471242
/*
@@ -1332,8 +1327,7 @@ static int check_exist_and_connected(struct ref *ref_map)
13321327
static int fetch_and_consume_refs(struct transport *transport,
13331328
struct ref_transaction *transaction,
13341329
struct ref *ref_map,
1335-
struct fetch_head *fetch_head,
1336-
struct worktree **worktrees)
1330+
struct fetch_head *fetch_head)
13371331
{
13381332
int connectivity_checked = 1;
13391333
int ret;
@@ -1356,7 +1350,7 @@ static int fetch_and_consume_refs(struct transport *transport,
13561350
trace2_region_enter("fetch", "consume_refs", the_repository);
13571351
ret = store_updated_refs(transport->url, transport->remote->name,
13581352
connectivity_checked, transaction, ref_map,
1359-
fetch_head, worktrees);
1353+
fetch_head);
13601354
trace2_region_leave("fetch", "consume_refs", the_repository);
13611355

13621356
out:
@@ -1434,19 +1428,16 @@ static int prune_refs(struct refspec *rs,
14341428
return result;
14351429
}
14361430

1437-
static void check_not_current_branch(struct ref *ref_map,
1438-
struct worktree **worktrees)
1431+
static void check_not_current_branch(struct ref *ref_map)
14391432
{
1440-
const struct worktree *wt;
1433+
const char *path;
14411434
for (; ref_map; ref_map = ref_map->next)
14421435
if (ref_map->peer_ref &&
14431436
starts_with(ref_map->peer_ref->name, "refs/heads/") &&
1444-
(wt = find_shared_symref(worktrees, "HEAD",
1445-
ref_map->peer_ref->name)) &&
1446-
!wt->is_bare)
1437+
(path = branch_checked_out(ref_map->peer_ref->name)))
14471438
die(_("refusing to fetch into branch '%s' "
14481439
"checked out at '%s'"),
1449-
ref_map->peer_ref->name, wt->path);
1440+
ref_map->peer_ref->name, path);
14501441
}
14511442

14521443
static int truncate_fetch_head(void)
@@ -1549,8 +1540,7 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
15491540
static int backfill_tags(struct transport *transport,
15501541
struct ref_transaction *transaction,
15511542
struct ref *ref_map,
1552-
struct fetch_head *fetch_head,
1553-
struct worktree **worktrees)
1543+
struct fetch_head *fetch_head)
15541544
{
15551545
int retcode, cannot_reuse;
15561546

@@ -1571,7 +1561,7 @@ static int backfill_tags(struct transport *transport,
15711561
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
15721562
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
15731563
transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
1574-
retcode = fetch_and_consume_refs(transport, transaction, ref_map, fetch_head, worktrees);
1564+
retcode = fetch_and_consume_refs(transport, transaction, ref_map, fetch_head);
15751565

15761566
if (gsecondary) {
15771567
transport_disconnect(gsecondary);
@@ -1592,7 +1582,6 @@ static int do_fetch(struct transport *transport,
15921582
struct transport_ls_refs_options transport_ls_refs_options =
15931583
TRANSPORT_LS_REFS_OPTIONS_INIT;
15941584
int must_list_refs = 1;
1595-
struct worktree **worktrees = get_worktrees();
15961585
struct fetch_head fetch_head = { 0 };
15971586
struct strbuf err = STRBUF_INIT;
15981587

@@ -1650,7 +1639,7 @@ static int do_fetch(struct transport *transport,
16501639
ref_map = get_ref_map(transport->remote, remote_refs, rs,
16511640
tags, &autotags);
16521641
if (!update_head_ok)
1653-
check_not_current_branch(ref_map, worktrees);
1642+
check_not_current_branch(ref_map);
16541643

16551644
retcode = open_fetch_head(&fetch_head);
16561645
if (retcode)
@@ -1683,7 +1672,7 @@ static int do_fetch(struct transport *transport,
16831672
retcode = 1;
16841673
}
16851674

1686-
if (fetch_and_consume_refs(transport, transaction, ref_map, &fetch_head, worktrees)) {
1675+
if (fetch_and_consume_refs(transport, transaction, ref_map, &fetch_head)) {
16871676
retcode = 1;
16881677
goto cleanup;
16891678
}
@@ -1706,7 +1695,7 @@ static int do_fetch(struct transport *transport,
17061695
* the transaction and don't commit anything.
17071696
*/
17081697
if (backfill_tags(transport, transaction, tags_ref_map,
1709-
&fetch_head, worktrees))
1698+
&fetch_head))
17101699
retcode = 1;
17111700
}
17121701

@@ -1791,7 +1780,6 @@ static int do_fetch(struct transport *transport,
17911780
close_fetch_head(&fetch_head);
17921781
strbuf_release(&err);
17931782
free_refs(ref_map);
1794-
free_worktrees(worktrees);
17951783
return retcode;
17961784
}
17971785

0 commit comments

Comments
 (0)