From 6835314459794831a1b88bed56549653710e910c Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Fri, 3 Jun 2016 19:19:39 +0700 Subject: worktree.c: add find_worktree() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far we haven't needed to identify an existing worktree from command line. Future commands such as lock or move will need it. The current implementation identifies worktrees by path (*). In future, the function could learn to identify by $(basename $path) or tags... (*) We could probably go cheaper with comparing inode number (and probably more reliable than paths when unicode enters the game). But not all systems have good inode that so let's stick to something simple for now. Helped-by: Eric Sunshine Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- worktree.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'worktree.c') diff --git a/worktree.c b/worktree.c index f4a4f38092..0782e00983 100644 --- a/worktree.c +++ b/worktree.c @@ -214,6 +214,21 @@ const char *get_worktree_git_dir(const struct worktree *wt) return git_common_path("worktrees/%s", wt->id); } +struct worktree *find_worktree(struct worktree **list, + const char *prefix, + const char *arg) +{ + char *path; + + arg = prefix_filename(prefix, strlen(prefix), arg); + path = xstrdup(real_path(arg)); + for (; *list; list++) + if (!fspathcmp(path, real_path((*list)->path))) + break; + free(path); + return *list; +} + int is_worktree_being_rebased(const struct worktree *wt, const char *target) { -- cgit v1.3-5-g9baa From 984ad9e56c9d884f7f1aa7d6b2052f3fb082ee5d Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Fri, 3 Jun 2016 19:19:40 +0700 Subject: worktree.c: add is_main_worktree() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Main worktree _is_ different. You can lock (*) a linked worktree but not the main one, for example. Provide an API for checking that. (*) Add the file $GIT_DIR/worktrees/xxx/locked to avoid worktree xxx from being removed or moved. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- worktree.c | 5 +++++ worktree.h | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'worktree.c') diff --git a/worktree.c b/worktree.c index 0782e00983..12a766a38d 100644 --- a/worktree.c +++ b/worktree.c @@ -229,6 +229,11 @@ struct worktree *find_worktree(struct worktree **list, return *list; } +int is_main_worktree(const struct worktree *wt) +{ + return !wt->id; +} + int is_worktree_being_rebased(const struct worktree *wt, const char *target) { diff --git a/worktree.h b/worktree.h index 7ad15da0dc..e1c4715238 100644 --- a/worktree.h +++ b/worktree.h @@ -37,6 +37,11 @@ extern struct worktree *find_worktree(struct worktree **list, const char *prefix, const char *arg); +/* + * Return true if the given worktree is the main one. + */ +extern int is_main_worktree(const struct worktree *wt); + /* * Free up the memory for worktree(s) */ -- cgit v1.3-5-g9baa From 346ef53058ef25f5a7273ee77c03ebc5f732ad77 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Mon, 13 Jun 2016 19:18:23 +0700 Subject: worktree.c: add is_worktree_locked() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need this later to avoid double locking a worktree, or unlocking one when it's not even locked. Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- worktree.c | 28 ++++++++++++++++++++++++++++ worktree.h | 8 ++++++++ 2 files changed, 36 insertions(+) (limited to 'worktree.c') diff --git a/worktree.c b/worktree.c index 12a766a38d..2bcfff3850 100644 --- a/worktree.c +++ b/worktree.c @@ -13,6 +13,7 @@ void free_worktrees(struct worktree **worktrees) free(worktrees[i]->path); free(worktrees[i]->id); free(worktrees[i]->head_ref); + free(worktrees[i]->lock_reason); free(worktrees[i]); } free (worktrees); @@ -98,6 +99,8 @@ static struct worktree *get_main_worktree(void) worktree->is_detached = is_detached; worktree->is_current = 0; add_head_info(&head_ref, worktree); + worktree->lock_reason = NULL; + worktree->lock_reason_valid = 0; done: strbuf_release(&path); @@ -143,6 +146,8 @@ static struct worktree *get_linked_worktree(const char *id) worktree->is_detached = is_detached; worktree->is_current = 0; add_head_info(&head_ref, worktree); + worktree->lock_reason = NULL; + worktree->lock_reason_valid = 0; done: strbuf_release(&path); @@ -234,6 +239,29 @@ int is_main_worktree(const struct worktree *wt) return !wt->id; } +const char *is_worktree_locked(struct worktree *wt) +{ + assert(!is_main_worktree(wt)); + + if (!wt->lock_reason_valid) { + struct strbuf path = STRBUF_INIT; + + strbuf_addstr(&path, worktree_git_path(wt, "locked")); + if (file_exists(path.buf)) { + struct strbuf lock_reason = STRBUF_INIT; + if (strbuf_read_file(&lock_reason, path.buf, 0) < 0) + die_errno(_("failed to read '%s'"), path.buf); + strbuf_trim(&lock_reason); + wt->lock_reason = strbuf_detach(&lock_reason, NULL); + } else + wt->lock_reason = NULL; + wt->lock_reason_valid = 1; + strbuf_release(&path); + } + + return wt->lock_reason; +} + int is_worktree_being_rebased(const struct worktree *wt, const char *target) { diff --git a/worktree.h b/worktree.h index e1c4715238..90e1311fa7 100644 --- a/worktree.h +++ b/worktree.h @@ -5,10 +5,12 @@ struct worktree { char *path; char *id; char *head_ref; + char *lock_reason; /* internal use */ unsigned char head_sha1[20]; int is_detached; int is_bare; int is_current; + int lock_reason_valid; }; /* Functions for acting on the information about worktrees. */ @@ -42,6 +44,12 @@ extern struct worktree *find_worktree(struct worktree **list, */ extern int is_main_worktree(const struct worktree *wt); +/* + * Return the reason string if the given worktree is locked or NULL + * otherwise. + */ +extern const char *is_worktree_locked(struct worktree *wt); + /* * Free up the memory for worktree(s) */ -- cgit v1.3-5-g9baa From 080739ba1db7897dde53427937acc011ea98a006 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Mon, 13 Jun 2016 19:18:26 +0700 Subject: worktree.c: find_worktree() search by path suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the user to do something like "worktree lock foo" or "worktree lock to/foo" instead of "worktree lock /long/path/to/foo" if it's unambiguous. With completion support it could be quite convenient. While this base name search can be done in the same worktree iteration loop, the code is split into a separate function for clarity. Suggested-by: Eric Sunshine Signed-off-by: Nguyễn Thái Ngọc Duy Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 5 +++++ worktree.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'worktree.c') diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 27330c5a39..7850deedf7 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -129,6 +129,11 @@ OPTIONS :: Working trees can be identified by path, either relative or absolute. ++ +If the last path components in the working tree's path is unique among +working trees, it can be used to identify worktrees. For example if +you only have to working trees at "/abc/def/ghi" and "/abc/def/ggg", +then "ghi" or "def/ghi" is enough to point to the former working tree. DETAILS ------- diff --git a/worktree.c b/worktree.c index 2bcfff3850..2107c0625d 100644 --- a/worktree.c +++ b/worktree.c @@ -219,12 +219,41 @@ const char *get_worktree_git_dir(const struct worktree *wt) return git_common_path("worktrees/%s", wt->id); } +static struct worktree *find_worktree_by_suffix(struct worktree **list, + const char *suffix) +{ + struct worktree *found = NULL; + int nr_found = 0, suffixlen; + + suffixlen = strlen(suffix); + if (!suffixlen) + return NULL; + + for (; *list && nr_found < 2; list++) { + const char *path = (*list)->path; + int pathlen = strlen(path); + int start = pathlen - suffixlen; + + /* suffix must start at directory boundary */ + if ((!start || (start > 0 && is_dir_sep(path[start - 1]))) && + !fspathcmp(suffix, path + start)) { + found = *list; + nr_found++; + } + } + return nr_found == 1 ? found : NULL; +} + struct worktree *find_worktree(struct worktree **list, const char *prefix, const char *arg) { + struct worktree *wt; char *path; + if ((wt = find_worktree_by_suffix(list, arg))) + return wt; + arg = prefix_filename(prefix, strlen(prefix), arg); path = xstrdup(real_path(arg)); for (; *list; list++) -- cgit v1.3-5-g9baa