3
3
#include "strbuf.h"
4
4
#include "worktree.h"
5
5
6
+ /*
7
+ * read 'path_to_ref' into 'ref'. Also if is_detached is not NULL,
8
+ * set is_detached to 1 (0) if the ref is detatched (is not detached).
9
+ *
10
+ * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside $GIT_DIR so
11
+ * for linked worktrees, `resolve_ref_unsafe()` won't work (it uses
12
+ * git_path). Parse the ref ourselves.
13
+ *
14
+ * return -1 if the ref is not a proper ref, 0 otherwise (success)
15
+ */
16
+ static int parse_ref (char * path_to_ref , struct strbuf * ref , int * is_detached )
17
+ {
18
+ if (is_detached )
19
+ * is_detached = 0 ;
20
+ if (!strbuf_readlink (ref , path_to_ref , 0 )) {
21
+ /* HEAD is symbolic link */
22
+ if (!starts_with (ref -> buf , "refs/" ) ||
23
+ check_refname_format (ref -> buf , 0 ))
24
+ return -1 ;
25
+ } else if (strbuf_read_file (ref , path_to_ref , 0 ) >= 0 ) {
26
+ /* textual symref or detached */
27
+ if (!starts_with (ref -> buf , "ref:" )) {
28
+ if (is_detached )
29
+ * is_detached = 1 ;
30
+ } else {
31
+ strbuf_remove (ref , 0 , strlen ("ref:" ));
32
+ strbuf_trim (ref );
33
+ if (check_refname_format (ref -> buf , 0 ))
34
+ return -1 ;
35
+ }
36
+ } else
37
+ return -1 ;
38
+ return 0 ;
39
+ }
40
+
41
+ static char * find_main_symref (const char * symref , const char * branch )
42
+ {
43
+ struct strbuf sb = STRBUF_INIT ;
44
+ struct strbuf path = STRBUF_INIT ;
45
+ struct strbuf gitdir = STRBUF_INIT ;
46
+ char * existing = NULL ;
47
+
48
+ strbuf_addf (& path , "%s/%s" , get_git_common_dir (), symref );
49
+ if (parse_ref (path .buf , & sb , NULL ) < 0 )
50
+ goto done ;
51
+ if (strcmp (sb .buf , branch ))
52
+ goto done ;
53
+ strbuf_addstr (& gitdir , get_git_common_dir ());
54
+ strbuf_strip_suffix (& gitdir , ".git" );
55
+ existing = strbuf_detach (& gitdir , NULL );
56
+ done :
57
+ strbuf_release (& path );
58
+ strbuf_release (& sb );
59
+ strbuf_release (& gitdir );
60
+
61
+ return existing ;
62
+ }
63
+
6
64
static char * find_linked_symref (const char * symref , const char * branch ,
7
65
const char * id )
8
66
{
@@ -11,36 +69,20 @@ static char *find_linked_symref(const char *symref, const char *branch,
11
69
struct strbuf gitdir = STRBUF_INIT ;
12
70
char * existing = NULL ;
13
71
14
- /*
15
- * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside
16
- * $GIT_DIR so resolve_ref_unsafe() won't work (it uses
17
- * git_path). Parse the ref ourselves.
18
- */
19
- if (id )
20
- strbuf_addf (& path , "%s/worktrees/%s/%s" , get_git_common_dir (), id , symref );
21
- else
22
- strbuf_addf (& path , "%s/%s" , get_git_common_dir (), symref );
72
+ if (!id )
73
+ die ("Missing linked worktree name" );
23
74
24
- if (!strbuf_readlink (& sb , path .buf , 0 )) {
25
- if (!starts_with (sb .buf , "refs/" ) ||
26
- check_refname_format (sb .buf , 0 ))
27
- goto done ;
28
- } else if (strbuf_read_file (& sb , path .buf , 0 ) >= 0 &&
29
- starts_with (sb .buf , "ref:" )) {
30
- strbuf_remove (& sb , 0 , strlen ("ref:" ));
31
- strbuf_trim (& sb );
32
- } else
75
+ strbuf_addf (& path , "%s/worktrees/%s/%s" , get_git_common_dir (), id , symref );
76
+
77
+ if (parse_ref (path .buf , & sb , NULL ) < 0 )
33
78
goto done ;
34
79
if (strcmp (sb .buf , branch ))
35
80
goto done ;
36
- if (id ) {
37
- strbuf_reset (& path );
38
- strbuf_addf (& path , "%s/worktrees/%s/gitdir" , get_git_common_dir (), id );
39
- if (strbuf_read_file (& gitdir , path .buf , 0 ) <= 0 )
40
- goto done ;
41
- strbuf_rtrim (& gitdir );
42
- } else
43
- strbuf_addstr (& gitdir , get_git_common_dir ());
81
+ strbuf_reset (& path );
82
+ strbuf_addf (& path , "%s/worktrees/%s/gitdir" , get_git_common_dir (), id );
83
+ if (strbuf_read_file (& gitdir , path .buf , 0 ) <= 0 )
84
+ goto done ;
85
+ strbuf_rtrim (& gitdir );
44
86
strbuf_strip_suffix (& gitdir , ".git" );
45
87
46
88
existing = strbuf_detach (& gitdir , NULL );
@@ -59,7 +101,7 @@ char *find_shared_symref(const char *symref, const char *target)
59
101
struct dirent * d ;
60
102
char * existing ;
61
103
62
- if ((existing = find_linked_symref (symref , target , NULL )))
104
+ if ((existing = find_main_symref (symref , target )))
63
105
return existing ;
64
106
65
107
strbuf_addf (& path , "%s/worktrees" , get_git_common_dir ());
0 commit comments