worktree.c: find_worktree() search by path suffix

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 <sunshine@sunshineco.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jun 13, 2016 at 19:18 UTC 080739ba1db7897dde53427937acc011ea98a006
2 files changed +34
Documentation/git-worktree.txt
+5
@@ -129,6 +129,11 @@ OPTIONS
129 <worktree>::
130 Working trees can be identified by path, either relative or
131 absolute.
132 ++
133 +If the last path components in the working tree's path is unique among
134 +working trees, it can be used to identify worktrees. For example if
135 +you only have to working trees at "/abc/def/ghi" and "/abc/def/ggg",
136 +then "ghi" or "def/ghi" is enough to point to the former working tree.
137
138 DETAILS
139 -------
worktree.c
+29
@@ -219,12 +219,41 @@ const char *get_worktree_git_dir(const struct worktree *wt)
219 return git_common_path("worktrees/%s", wt->id);
220 }
221
222 +static struct worktree *find_worktree_by_suffix(struct worktree **list,
223 + const char *suffix)
224 +{
225 + struct worktree *found = NULL;
226 + int nr_found = 0, suffixlen;
227 +
228 + suffixlen = strlen(suffix);
229 + if (!suffixlen)
230 + return NULL;
231 +
232 + for (; *list && nr_found < 2; list++) {
233 + const char *path = (*list)->path;
234 + int pathlen = strlen(path);
235 + int start = pathlen - suffixlen;
236 +
237 + /* suffix must start at directory boundary */
238 + if ((!start || (start > 0 && is_dir_sep(path[start - 1]))) &&
239 + !fspathcmp(suffix, path + start)) {
240 + found = *list;
241 + nr_found++;
242 + }
243 + }
244 + return nr_found == 1 ? found : NULL;
245 +}
246 +
247 struct worktree *find_worktree(struct worktree **list,
248 const char *prefix,
249 const char *arg)
250 {
251 + struct worktree *wt;
252 char *path;
253
254 + if ((wt = find_worktree_by_suffix(list, arg)))
255 + return wt;
256 +
257 arg = prefix_filename(prefix, strlen(prefix), arg);
258 path = xstrdup(real_path(arg));
259 for (; *list; list++)