worktree: add top-level worktree.c

worktree.c contains functions to work with and get information from worktrees. This introduction moves functions related to worktrees from branch.c into worktree.c Signed-off-by: Michael Rappazzo <rappazzo@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Rappazzo committed Oct 2, 2015 at 07:55 UTC ac6c561b598ae74d8e752e22607194536000e4db
6 files changed +97 -87
Makefile
+1
@@ -807,6 +807,7 @@ LIB_OBJS += version.o
807 LIB_OBJS += versioncmp.o
808 LIB_OBJS += walker.o
809 LIB_OBJS += wildmatch.o
810 +LIB_OBJS += worktree.o
811 LIB_OBJS += wrapper.o
812 LIB_OBJS += write_or_die.o
813 LIB_OBJS += ws.o
branch.c
+1 -78
@@ -4,6 +4,7 @@
4 #include "refs.h"
5 #include "remote.h"
6 #include "commit.h"
7 +#include "worktree.h"
8
9 struct tracking {
10 struct refspec spec;
@@ -311,84 +312,6 @@ void remove_branch_state(void)
312 unlink(git_path_squash_msg());
313 }
314
314 -static char *find_linked_symref(const char *symref, const char *branch,
315 - const char *id)
316 -{
317 - struct strbuf sb = STRBUF_INIT;
318 - struct strbuf path = STRBUF_INIT;
319 - struct strbuf gitdir = STRBUF_INIT;
320 - char *existing = NULL;
321 -
322 - /*
323 - * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside
324 - * $GIT_DIR so resolve_ref_unsafe() won't work (it uses
325 - * git_path). Parse the ref ourselves.
326 - */
327 - if (id)
328 - strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref);
329 - else
330 - strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref);
331 -
332 - if (!strbuf_readlink(&sb, path.buf, 0)) {
333 - if (!starts_with(sb.buf, "refs/") ||
334 - check_refname_format(sb.buf, 0))
335 - goto done;
336 - } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 &&
337 - starts_with(sb.buf, "ref:")) {
338 - strbuf_remove(&sb, 0, strlen("ref:"));
339 - strbuf_trim(&sb);
340 - } else
341 - goto done;
342 - if (strcmp(sb.buf, branch))
343 - goto done;
344 - if (id) {
345 - strbuf_reset(&path);
346 - strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
347 - if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
348 - goto done;
349 - strbuf_rtrim(&gitdir);
350 - } else
351 - strbuf_addstr(&gitdir, get_git_common_dir());
352 - strbuf_strip_suffix(&gitdir, ".git");
353 -
354 - existing = strbuf_detach(&gitdir, NULL);
355 -done:
356 - strbuf_release(&path);
357 - strbuf_release(&sb);
358 - strbuf_release(&gitdir);
359 -
360 - return existing;
361 -}
362 -
363 -char *find_shared_symref(const char *symref, const char *target)
364 -{
365 - struct strbuf path = STRBUF_INIT;
366 - DIR *dir;
367 - struct dirent *d;
368 - char *existing;
369 -
370 - if ((existing = find_linked_symref(symref, target, NULL)))
371 - return existing;
372 -
373 - strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
374 - dir = opendir(path.buf);
375 - strbuf_release(&path);
376 - if (!dir)
377 - return NULL;
378 -
379 - while ((d = readdir(dir)) != NULL) {
380 - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
381 - continue;
382 - existing = find_linked_symref(symref, target, d->d_name);
383 - if (existing)
384 - goto done;
385 - }
386 -done:
387 - closedir(dir);
388 -
389 - return existing;
390 -}
391 -
315 void die_if_checked_out(const char *branch)
316 {
317 char *existing;
branch.h
-8
@@ -59,12 +59,4 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name);
59 */
60 extern void die_if_checked_out(const char *branch);
61
62 -/*
63 - * Check if a per-worktree symref points to a ref in the main worktree
64 - * or any linked worktree, and return the path to the exising worktree
65 - * if it is. Returns NULL if there is no existing ref. The caller is
66 - * responsible for freeing the returned path.
67 - */
68 -extern char *find_shared_symref(const char *symref, const char *target);
69 -
62 #endif
builtin/notes.c
+1 -1
@@ -19,7 +19,7 @@
19 #include "string-list.h"
20 #include "notes-merge.h"
21 #include "notes-utils.h"
22 -#include "branch.h"
22 +#include "worktree.h"
23
24 static const char * const git_notes_usage[] = {
25 N_("git notes [--ref <notes-ref>] [list [<object>]]"),
worktree.c new
+82
@@ -0,0 +1,82 @@
1 +#include "cache.h"
2 +#include "refs.h"
3 +#include "strbuf.h"
4 +#include "worktree.h"
5 +
6 +static char *find_linked_symref(const char *symref, const char *branch,
7 + const char *id)
8 +{
9 + struct strbuf sb = STRBUF_INIT;
10 + struct strbuf path = STRBUF_INIT;
11 + struct strbuf gitdir = STRBUF_INIT;
12 + char *existing = NULL;
13 +
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);
23 +
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
33 + goto done;
34 + if (strcmp(sb.buf, branch))
35 + 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());
44 + strbuf_strip_suffix(&gitdir, ".git");
45 +
46 + existing = strbuf_detach(&gitdir, NULL);
47 +done:
48 + strbuf_release(&path);
49 + strbuf_release(&sb);
50 + strbuf_release(&gitdir);
51 +
52 + return existing;
53 +}
54 +
55 +char *find_shared_symref(const char *symref, const char *target)
56 +{
57 + struct strbuf path = STRBUF_INIT;
58 + DIR *dir;
59 + struct dirent *d;
60 + char *existing;
61 +
62 + if ((existing = find_linked_symref(symref, target, NULL)))
63 + return existing;
64 +
65 + strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
66 + dir = opendir(path.buf);
67 + strbuf_release(&path);
68 + if (!dir)
69 + return NULL;
70 +
71 + while ((d = readdir(dir)) != NULL) {
72 + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
73 + continue;
74 + existing = find_linked_symref(symref, target, d->d_name);
75 + if (existing)
76 + goto done;
77 + }
78 +done:
79 + closedir(dir);
80 +
81 + return existing;
82 +}
worktree.h new
+12
@@ -0,0 +1,12 @@
1 +#ifndef WORKTREE_H
2 +#define WORKTREE_H
3 +
4 +/*
5 + * Check if a per-worktree symref points to a ref in the main worktree
6 + * or any linked worktree, and return the path to the exising worktree
7 + * if it is. Returns NULL if there is no existing ref. The caller is
8 + * responsible for freeing the returned path.
9 + */
10 +extern char *find_shared_symref(const char *symref, const char *target);
11 +
12 +#endif