@@ -310,21 +310,23 @@ void remove_branch_state(void)
310
310
unlink (git_path ("SQUASH_MSG" ));
311
311
}
312
312
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 )
314
315
{
315
316
struct strbuf sb = STRBUF_INIT ;
316
317
struct strbuf path = STRBUF_INIT ;
317
318
struct strbuf gitdir = STRBUF_INIT ;
319
+ char * existing = NULL ;
318
320
319
321
/*
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.
323
325
*/
324
326
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 );
326
328
else
327
- strbuf_addf (& path , "%s/HEAD " , get_git_common_dir ());
329
+ strbuf_addf (& path , "%s/%s " , get_git_common_dir (), symref );
328
330
329
331
if (!strbuf_readlink (& sb , path .buf , 0 )) {
330
332
if (!starts_with (sb .buf , "refs/" ) ||
@@ -346,33 +348,53 @@ static void check_linked_checkout(const char *branch, const char *id)
346
348
strbuf_rtrim (& gitdir );
347
349
} else
348
350
strbuf_addstr (& gitdir , get_git_common_dir ());
349
- skip_prefix (branch , "refs/heads/" , & branch );
350
351
strbuf_strip_suffix (& gitdir , ".git" );
351
- die (_ ("'%s' is already checked out at '%s'" ), branch , gitdir .buf );
352
+
353
+ existing = strbuf_detach (& gitdir , NULL );
352
354
done :
353
355
strbuf_release (& path );
354
356
strbuf_release (& sb );
355
357
strbuf_release (& gitdir );
358
+
359
+ return existing ;
356
360
}
357
361
358
- void die_if_checked_out (const char * branch )
362
+ char * find_shared_symref (const char * symref , const char * target )
359
363
{
360
364
struct strbuf path = STRBUF_INIT ;
361
365
DIR * dir ;
362
366
struct dirent * d ;
367
+ char * existing ;
363
368
364
- check_linked_checkout (branch , NULL );
369
+ if ((existing = find_linked_symref (symref , target , NULL )))
370
+ return existing ;
365
371
366
372
strbuf_addf (& path , "%s/worktrees" , get_git_common_dir ());
367
373
dir = opendir (path .buf );
368
374
strbuf_release (& path );
369
375
if (!dir )
370
- return ;
376
+ return NULL ;
371
377
372
378
while ((d = readdir (dir )) != NULL ) {
373
379
if (!strcmp (d -> d_name , "." ) || !strcmp (d -> d_name , ".." ))
374
380
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 ;
376
384
}
385
+ done :
377
386
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
+ }
378
400
}
0 commit comments