The code formerly in branch.c was largely the basis of the get_worktree_list implementation is now moved to worktree.c, and the find_shared_symref implementation has been refactored to use get_worktree_list Signed-off-by: Michael Rappazzo <rappazzo@xxxxxxxxx> --- branch.c | 79 +-------------------------------------------------------- branch.h | 8 ------ builtin/notes.c | 1 + worktree.c | 40 +++++++++++++++++++++++++++++ worktree.h | 7 +++++ 5 files changed, 49 insertions(+), 86 deletions(-) diff --git a/branch.c b/branch.c index d013374..77d7f2a 100644 --- a/branch.c +++ b/branch.c @@ -4,6 +4,7 @@ #include "refs.h" #include "remote.h" #include "commit.h" +#include "worktree.h" struct tracking { struct refspec spec; @@ -311,84 +312,6 @@ void remove_branch_state(void) unlink(git_path_squash_msg()); } -static char *find_linked_symref(const char *symref, const char *branch, - const char *id) -{ - struct strbuf sb = STRBUF_INIT; - struct strbuf path = STRBUF_INIT; - struct strbuf gitdir = STRBUF_INIT; - char *existing = NULL; - - /* - * $GIT_COMMON_DIR/$symref (e.g. HEAD) is practically outside - * $GIT_DIR so resolve_ref_unsafe() won't work (it uses - * git_path). Parse the ref ourselves. - */ - if (id) - strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref); - else - strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref); - - if (!strbuf_readlink(&sb, path.buf, 0)) { - if (!starts_with(sb.buf, "refs/") || - check_refname_format(sb.buf, 0)) - goto done; - } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 && - starts_with(sb.buf, "ref:")) { - strbuf_remove(&sb, 0, strlen("ref:")); - strbuf_trim(&sb); - } else - goto done; - if (strcmp(sb.buf, branch)) - goto done; - if (id) { - strbuf_reset(&path); - strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id); - if (strbuf_read_file(&gitdir, path.buf, 0) <= 0) - goto done; - strbuf_rtrim(&gitdir); - } else - strbuf_addstr(&gitdir, get_git_common_dir()); - strbuf_strip_suffix(&gitdir, ".git"); - - existing = strbuf_detach(&gitdir, NULL); -done: - strbuf_release(&path); - strbuf_release(&sb); - strbuf_release(&gitdir); - - return existing; -} - -char *find_shared_symref(const char *symref, const char *target) -{ - struct strbuf path = STRBUF_INIT; - DIR *dir; - struct dirent *d; - char *existing; - - if ((existing = find_linked_symref(symref, target, NULL))) - return existing; - - strbuf_addf(&path, "%s/worktrees", get_git_common_dir()); - dir = opendir(path.buf); - strbuf_release(&path); - if (!dir) - return NULL; - - while ((d = readdir(dir)) != NULL) { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) - continue; - existing = find_linked_symref(symref, target, d->d_name); - if (existing) - goto done; - } -done: - closedir(dir); - - return existing; -} - void die_if_checked_out(const char *branch) { char *existing; diff --git a/branch.h b/branch.h index d3446ed..58aa45f 100644 --- a/branch.h +++ b/branch.h @@ -59,12 +59,4 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name); */ extern void die_if_checked_out(const char *branch); -/* - * Check if a per-worktree symref points to a ref in the main worktree - * or any linked worktree, and return the path to the exising worktree - * if it is. Returns NULL if there is no existing ref. The caller is - * responsible for freeing the returned path. - */ -extern char *find_shared_symref(const char *symref, const char *target); - #endif diff --git a/builtin/notes.c b/builtin/notes.c index 3608c64..8b30334 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -20,6 +20,7 @@ #include "notes-merge.h" #include "notes-utils.h" #include "branch.h" +#include "worktree.h" static const char * const git_notes_usage[] = { N_("git notes [--ref <notes-ref>] [list [<object>]]"), diff --git a/worktree.c b/worktree.c index 33d2e57..e45b651 100644 --- a/worktree.c +++ b/worktree.c @@ -155,3 +155,43 @@ done: return list; } +char *find_shared_symref(const char *symref, const char *target) +{ + char *existing = NULL; + struct strbuf path = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT; + struct worktree_list *worktree_list = get_worktree_list(); + struct worktree_list *orig_list = worktree_list; + struct worktree *matched = NULL; + + while (!matched && worktree_list) { + if (strcmp("HEAD", symref)) { + strbuf_reset(&path); + strbuf_reset(&sb); + strbuf_addf(&path, "%s/%s", worktree_list->worktree->git_dir, symref); + + if (_parse_ref(path.buf, &sb, NULL)) { + continue; + } + + if (!strcmp(sb.buf, target)) + matched = worktree_list->worktree; + } else { + if (worktree_list->worktree->head_ref && !strcmp(worktree_list->worktree->head_ref, target)) + matched = worktree_list->worktree; + } + worktree_list = worktree_list->next ? worktree_list->next : NULL; + } + + if (matched) { + existing = malloc(strlen(matched->path) + 1); + strcpy(existing, matched->path); + } + +done: + strbuf_release(&path); + strbuf_release(&sb); + worktree_list_release(orig_list); + + return existing; +} diff --git a/worktree.h b/worktree.h index 2bc0ab8..320f17e 100644 --- a/worktree.h +++ b/worktree.h @@ -45,4 +45,11 @@ struct worktree *get_worktree(const char *id); extern void worktree_list_release(struct worktree_list *); extern void worktree_release(struct worktree *); +/* + * Look for a symref in any worktree, and return the path to the first + * worktree found or NULL if not found. The caller is responsible for + * freeing the returned path. + */ +extern char *find_shared_symref(const char *symref, const char *target); + #endif -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html