Skip to content

Commit cb18484

Browse files
phillipwoodgitster
authored andcommitted
wt-status: avoid passing NULL worktree
In preparation for removing the repository argument from worktree_git_path() add a function to construct a "struct worktree" from a "struct repository" using its "gitdir" and "worktree" members. This function is then used to avoid passing a NULL worktree to wt_status_check_bisect() and wt_status_check_rebase(). In general the "struct worktree" returned may not correspond to the "current" worktree defined by is_current_worktree() as that function uses "the_repository" rather than "wt->repo" when deciding which worktree is "current". In practice the "struct repository" we pass corresponds to "the_repository" as we only ever operate on a single repository at the moment. wt_status_check_bisect() and wt_status_check_rebase() have the following callers: - branch.c:prepare_checked_out_branches() which loops over all worktrees. - worktree.c:is_worktree_being_rebased() which is called from builtin/branch.c:reject_rebase_or_bisect_branch() that loops over all worktrees and worktree.c:is_shared_symref() which dereferences wt earlier in the function. - wt-status:wt_status_get_state() which is updated to avoid passing a NULL worktree by this patch. This updates the only callers that pass a NULL worktree to worktree_git_path(). A new test is added to check that "git status" detects a rebase in a linked worktree. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 67ad421 commit cb18484

4 files changed

Lines changed: 47 additions & 3 deletions

File tree

t/t7512-status-help.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,15 @@ EOF
594594
test_cmp expected actual
595595
'
596596

597+
test_expect_success 'rebase in a linked worktree' '
598+
test_might_fail git rebase --abort &&
599+
git worktree add wt &&
600+
test_when_finished "test_might_fail git -C wt rebase --abort;
601+
git worktree remove wt" &&
602+
GIT_SEQUENCE_EDITOR="echo break >" git -C wt rebase -i HEAD &&
603+
git -C wt status >actual &&
604+
test_grep "interactive rebase in progress" actual
605+
'
597606

598607
test_expect_success 'prepare am_session' '
599608
git reset --hard main &&

worktree.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,26 @@ static int is_current_worktree(struct worktree *wt)
6666
return is_current;
6767
}
6868

69+
struct worktree *get_worktree_from_repository(struct repository *repo)
70+
{
71+
struct worktree *wt = xcalloc(1, sizeof(*wt));
72+
char *gitdir = absolute_pathdup(repo->gitdir);
73+
char *commondir = absolute_pathdup(repo->commondir);
74+
75+
wt->repo = repo;
76+
wt->path = absolute_pathdup(repo->worktree ? repo->worktree
77+
: repo->gitdir);
78+
wt->is_bare = !repo->worktree;
79+
if (fspathcmp(gitdir, commondir))
80+
wt->id = xstrdup(find_last_dir_sep(gitdir) + 1);
81+
wt->is_current = is_current_worktree(wt);
82+
add_head_info(wt);
83+
84+
free(gitdir);
85+
free(commondir);
86+
return wt;
87+
}
88+
6989
/*
7090
* When in a secondary worktree, and when extensions.worktreeConfig
7191
* is true, only $commondir/config and $commondir/worktrees/<id>/

worktree.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ struct worktree **get_worktrees(void);
3838
*/
3939
struct worktree **get_worktrees_without_reading_head(void);
4040

41+
/*
42+
* Construct a struct worktree corresponding to repo->gitdir and
43+
* repo->worktree.
44+
*/
45+
struct worktree *get_worktree_from_repository(struct repository *repo);
46+
4147
/*
4248
* Returns 1 if linked worktrees exist, 0 otherwise.
4349
*/

wt-status.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,9 @@ int wt_status_check_rebase(const struct worktree *wt,
17231723
{
17241724
struct stat st;
17251725

1726+
if (!wt)
1727+
BUG("wt_status_check_rebase() called with NULL worktree");
1728+
17261729
if (!stat(worktree_git_path(the_repository, wt, "rebase-apply"), &st)) {
17271730
if (!stat(worktree_git_path(the_repository, wt, "rebase-apply/applying"), &st)) {
17281731
state->am_in_progress = 1;
@@ -1750,6 +1753,9 @@ int wt_status_check_bisect(const struct worktree *wt,
17501753
{
17511754
struct stat st;
17521755

1756+
if (!wt)
1757+
BUG("wt_status_check_bisect() called with NULL worktree");
1758+
17531759
if (!stat(worktree_git_path(the_repository, wt, "BISECT_LOG"), &st)) {
17541760
state->bisect_in_progress = 1;
17551761
state->bisecting_from = get_branch(wt, "BISECT_START");
@@ -1795,18 +1801,19 @@ void wt_status_get_state(struct repository *r,
17951801
struct stat st;
17961802
struct object_id oid;
17971803
enum replay_action action;
1804+
struct worktree *wt = get_worktree_from_repository(r);
17981805

17991806
if (!stat(git_path_merge_head(r), &st)) {
1800-
wt_status_check_rebase(NULL, state);
1807+
wt_status_check_rebase(wt, state);
18011808
state->merge_in_progress = 1;
1802-
} else if (wt_status_check_rebase(NULL, state)) {
1809+
} else if (wt_status_check_rebase(wt, state)) {
18031810
; /* all set */
18041811
} else if (refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
18051812
!repo_get_oid(r, "CHERRY_PICK_HEAD", &oid)) {
18061813
state->cherry_pick_in_progress = 1;
18071814
oidcpy(&state->cherry_pick_head_oid, &oid);
18081815
}
1809-
wt_status_check_bisect(NULL, state);
1816+
wt_status_check_bisect(wt, state);
18101817
if (refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD") &&
18111818
!repo_get_oid(r, "REVERT_HEAD", &oid)) {
18121819
state->revert_in_progress = 1;
@@ -1824,6 +1831,8 @@ void wt_status_get_state(struct repository *r,
18241831
if (get_detached_from)
18251832
wt_status_get_detached_from(r, state);
18261833
wt_status_check_sparse_checkout(r, state);
1834+
1835+
free_worktree(wt);
18271836
}
18281837

18291838
static void wt_longstatus_print_state(struct wt_status *s)

0 commit comments

Comments
 (0)