@@ -310,21 +310,23 @@ void remove_branch_state(void)
310310 unlink (git_path ("SQUASH_MSG" ));
311311}
312312
313- static void check_linked_checkout (const char * branch , const char * id )
313+ static char * find_linked_symref (const char * symref , const char * branch ,
314+ const char * id )
314315{
315316 struct strbuf sb = STRBUF_INIT ;
316317 struct strbuf path = STRBUF_INIT ;
317318 struct strbuf gitdir = STRBUF_INIT ;
319+ char * existing = NULL ;
318320
319321 /*
320- * $GIT_COMMON_DIR/HEAD is practically outside
321- * $GIT_DIR so resolve_ref_unsafe() won't work (it
322- * uses git_path). Parse the ref ourselves.
322+ * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside
323+ * $GIT_DIR so resolve_ref_unsafe() won't work (it uses
324+ * git_path). Parse the ref ourselves.
323325 */
324326 if (id )
325- strbuf_addf (& path , "%s/worktrees/%s/HEAD " , get_git_common_dir (), id );
327+ strbuf_addf (& path , "%s/worktrees/%s/%s " , get_git_common_dir (), id , symref );
326328 else
327- strbuf_addf (& path , "%s/HEAD " , get_git_common_dir ());
329+ strbuf_addf (& path , "%s/%s " , get_git_common_dir (), symref );
328330
329331 if (!strbuf_readlink (& sb , path .buf , 0 )) {
330332 if (!starts_with (sb .buf , "refs/" ) ||
@@ -346,33 +348,53 @@ static void check_linked_checkout(const char *branch, const char *id)
346348 strbuf_rtrim (& gitdir );
347349 } else
348350 strbuf_addstr (& gitdir , get_git_common_dir ());
349- skip_prefix (branch , "refs/heads/" , & branch );
350351 strbuf_strip_suffix (& gitdir , ".git" );
351- die (_ ("'%s' is already checked out at '%s'" ), branch , gitdir .buf );
352+
353+ existing = strbuf_detach (& gitdir , NULL );
352354done :
353355 strbuf_release (& path );
354356 strbuf_release (& sb );
355357 strbuf_release (& gitdir );
358+
359+ return existing ;
356360}
357361
358- void die_if_checked_out (const char * branch )
362+ char * find_shared_symref (const char * symref , const char * target )
359363{
360364 struct strbuf path = STRBUF_INIT ;
361365 DIR * dir ;
362366 struct dirent * d ;
367+ char * existing ;
363368
364- check_linked_checkout (branch , NULL );
369+ if ((existing = find_linked_symref (symref , target , NULL )))
370+ return existing ;
365371
366372 strbuf_addf (& path , "%s/worktrees" , get_git_common_dir ());
367373 dir = opendir (path .buf );
368374 strbuf_release (& path );
369375 if (!dir )
370- return ;
376+ return NULL ;
371377
372378 while ((d = readdir (dir )) != NULL ) {
373379 if (!strcmp (d -> d_name , "." ) || !strcmp (d -> d_name , ".." ))
374380 continue ;
375- check_linked_checkout (branch , d -> d_name );
381+ existing = find_linked_symref (symref , target , d -> d_name );
382+ if (existing )
383+ goto done ;
376384 }
385+ done :
377386 closedir (dir );
387+
388+ return existing ;
389+ }
390+
391+ void die_if_checked_out (const char * branch )
392+ {
393+ char * existing ;
394+
395+ existing = find_shared_symref ("HEAD" , branch );
396+ if (existing ) {
397+ skip_prefix (branch , "refs/heads/" , & branch );
398+ die (_ ("'%s' is already checked out at '%s'" ), branch , existing );
399+ }
378400}
0 commit comments