diff options
author | Michael Rappazzo <rappazzo@gmail.com> | 2015-10-08 13:01:03 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-10-08 11:56:25 -0700 |
commit | 51934904425e55a190b05f0a7a3de40ea486f0e5 (patch) | |
tree | 10975d66c16dd044736cb6f71259fa149f39f038 /worktree.c | |
parent | 1ceb7f90674897a24a9f2a56abf7d26297761f18 (diff) | |
download | git-51934904425e55a190b05f0a7a3de40ea486f0e5.tar.gz |
worktree: add a function to get worktree details
The worktree structure provided for an individual worktree includes the
absolute path of the worktree. The fuction to get the worktree details
is a refactor of the find main/linked symref functions.
Signed-off-by: Michael Rappazzo <rappazzo@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'worktree.c')
-rw-r--r-- | worktree.c | 154 |
1 files changed, 108 insertions, 46 deletions
diff --git a/worktree.c b/worktree.c index 3c2498ae1c..c2e6db0a2c 100644 --- a/worktree.c +++ b/worktree.c @@ -3,6 +3,17 @@ #include "strbuf.h" #include "worktree.h" +void free_worktrees(struct worktree **worktrees) +{ + int i = 0; + + for (i = 0; worktrees[i]; i++) { + free(worktrees[i]->path); + free(worktrees[i]); + } + free (worktrees); +} + /* * read 'path_to_ref' into 'ref'. Also if is_detached is not NULL, * set is_detached to 1 (0) if the ref is detatched (is not detached). @@ -38,87 +49,138 @@ static int parse_ref(char *path_to_ref, struct strbuf *ref, int *is_detached) return 0; } -static char *find_main_symref(const char *symref, const char *branch) +/** + * get the main worktree + */ +static struct worktree *get_main_worktree(void) { - struct strbuf sb = STRBUF_INIT; + struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; + struct strbuf worktree_path = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; - char *existing = NULL; + struct strbuf head_ref = STRBUF_INIT; - strbuf_addf(&path, "%s/%s", get_git_common_dir(), symref); - if (parse_ref(path.buf, &sb, NULL) < 0) - goto done; - if (strcmp(sb.buf, branch)) - goto done; - strbuf_addstr(&gitdir, get_git_common_dir()); - strbuf_strip_suffix(&gitdir, ".git"); - existing = strbuf_detach(&gitdir, NULL); -done: + strbuf_addf(&gitdir, "%s", absolute_path(get_git_common_dir())); + strbuf_addbuf(&worktree_path, &gitdir); + if (!strbuf_strip_suffix(&worktree_path, "/.git")) + strbuf_strip_suffix(&worktree_path, "/."); + + strbuf_addf(&path, "%s/HEAD", get_git_common_dir()); + + if (parse_ref(path.buf, &head_ref, NULL) >= 0) { + worktree = xmalloc(sizeof(struct worktree)); + worktree->path = strbuf_detach(&worktree_path, NULL); + worktree->git_dir = strbuf_detach(&gitdir, NULL); + } strbuf_release(&path); - strbuf_release(&sb); strbuf_release(&gitdir); - - return existing; + strbuf_release(&worktree_path); + strbuf_release(&head_ref); + return worktree; } -static char *find_linked_symref(const char *symref, const char *branch, - const char *id) +static struct worktree *get_linked_worktree(const char *id) { - struct strbuf sb = STRBUF_INIT; + struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; + struct strbuf worktree_path = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; - char *existing = NULL; + struct strbuf head_ref = STRBUF_INIT; if (!id) die("Missing linked worktree name"); - strbuf_addf(&path, "%s/worktrees/%s/%s", get_git_common_dir(), id, symref); - - if (parse_ref(path.buf, &sb, NULL) < 0) - goto done; - if (strcmp(sb.buf, branch)) + strbuf_addf(&gitdir, "%s/worktrees/%s", + absolute_path(get_git_common_dir()), id); + strbuf_addf(&path, "%s/gitdir", gitdir.buf); + if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) + /* invalid gitdir file */ goto done; + + strbuf_rtrim(&worktree_path); + if (!strbuf_strip_suffix(&worktree_path, "/.git")) { + strbuf_reset(&worktree_path); + strbuf_addstr(&worktree_path, absolute_path(".")); + strbuf_strip_suffix(&worktree_path, "/."); + } + 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); - strbuf_strip_suffix(&gitdir, ".git"); + strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id); + + if (parse_ref(path.buf, &head_ref, NULL) >= 0) { + worktree = xmalloc(sizeof(struct worktree)); + worktree->path = strbuf_detach(&worktree_path, NULL); + worktree->git_dir = strbuf_detach(&gitdir, NULL); + } - existing = strbuf_detach(&gitdir, NULL); done: strbuf_release(&path); - strbuf_release(&sb); strbuf_release(&gitdir); - - return existing; + strbuf_release(&worktree_path); + strbuf_release(&head_ref); + return worktree; } -char *find_shared_symref(const char *symref, const char *target) +struct worktree **get_worktrees(void) { + struct worktree **list = NULL; struct strbuf path = STRBUF_INIT; DIR *dir; struct dirent *d; - char *existing; + int counter = 0, alloc = 2; + + list = xmalloc(alloc * sizeof(struct worktree *)); - if ((existing = find_main_symref(symref, target))) - return existing; + if ((list[counter] = get_main_worktree())) + counter++; strbuf_addf(&path, "%s/worktrees", get_git_common_dir()); dir = opendir(path.buf); strbuf_release(&path); - if (!dir) - return NULL; + if (dir) { + while ((d = readdir(dir)) != NULL) { + struct worktree *linked = NULL; + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + continue; - while ((d = readdir(dir)) != NULL) { - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) + if ((linked = get_linked_worktree(d->d_name))) { + ALLOC_GROW(list, counter + 1, alloc); + list[counter++] = linked; + } + } + closedir(dir); + } + ALLOC_GROW(list, counter + 1, alloc); + list[counter] = NULL; + 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 **worktrees = get_worktrees(); + int i = 0; + + for (i = 0; worktrees[i]; i++) { + strbuf_reset(&path); + strbuf_reset(&sb); + strbuf_addf(&path, "%s/%s", worktrees[i]->git_dir, symref); + + if (parse_ref(path.buf, &sb, NULL)) { continue; - existing = find_linked_symref(symref, target, d->d_name); - if (existing) - goto done; + } + + if (!strcmp(sb.buf, target)) { + existing = xstrdup(worktrees[i]->path); + break; + } } -done: - closedir(dir); + + strbuf_release(&path); + strbuf_release(&sb); + free_worktrees(worktrees); return existing; } |