worktree: refactor find_linked_symref function
Refactoring will help transition this code to provide additional useful worktree functions. Signed-off-by: Michael Rappazzo <rappazzo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Rappazzo committed
Oct 8, 2015 at 13:01 UTC
1ceb7f90674897a24a9f2a56abf7d26297761f18
1 file changed
+69
-27
worktree.c
+69
-27
@@ -3,6 +3,64 @@
3
#include "strbuf.h"
4
#include "worktree.h"
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
+
64
static char *find_linked_symref(const char *symref, const char *branch,
65
const char *id)
66
{
@@ -11,36 +69,20 @@ static char *find_linked_symref(const char *symref, const char *branch,
69
struct strbuf gitdir = STRBUF_INIT;
70
char *existing = NULL;
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");
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)
78
goto done;
79
if (strcmp(sb.buf, branch))
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);
86
strbuf_strip_suffix(&gitdir, ".git");
87
88
existing = strbuf_detach(&gitdir, NULL);
@@ -59,7 +101,7 @@ char *find_shared_symref(const char *symref, const char *target)
101
struct dirent *d;
102
char *existing;
103
62
- if ((existing = find_linked_symref(symref, target, NULL)))
104
+ if ((existing = find_main_symref(symref, target)))
105
return existing;
106
107
strbuf_addf(&path, "%s/worktrees", get_git_common_dir());