1 #include "cache.h"
2 #include "repository.h"
3 #include "refs.h"
4 #include "strbuf.h"
5 #include "worktree.h"
6 #include "dir.h"
7 #include "wt-status.h"
8 
free_worktrees(struct worktree ** worktrees)9 void free_worktrees(struct worktree **worktrees)
10 {
11 	int i = 0;
12 
13 	for (i = 0; worktrees[i]; i++) {
14 		free(worktrees[i]->path);
15 		free(worktrees[i]->id);
16 		free(worktrees[i]->head_ref);
17 		free(worktrees[i]->lock_reason);
18 		free(worktrees[i]);
19 	}
20 	free (worktrees);
21 }
22 
23 /**
24  * Update head_sha1, head_ref and is_detached of the given worktree
25  */
add_head_info(struct worktree * wt)26 static void add_head_info(struct worktree *wt)
27 {
28 	int flags;
29 	const char *target;
30 
31 	target = refs_resolve_ref_unsafe(get_worktree_ref_store(wt),
32 					 "HEAD",
33 					 0,
34 					 &wt->head_oid, &flags);
35 	if (!target)
36 		return;
37 
38 	if (flags & REF_ISSYMREF)
39 		wt->head_ref = xstrdup(target);
40 	else
41 		wt->is_detached = 1;
42 }
43 
44 /**
45  * get the main worktree
46  */
get_main_worktree(void)47 static struct worktree *get_main_worktree(void)
48 {
49 	struct worktree *worktree = NULL;
50 	struct strbuf path = STRBUF_INIT;
51 	struct strbuf worktree_path = STRBUF_INIT;
52 
53 	strbuf_add_absolute_path(&worktree_path, get_git_common_dir());
54 	if (!strbuf_strip_suffix(&worktree_path, "/.git"))
55 		strbuf_strip_suffix(&worktree_path, "/.");
56 
57 	strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
58 
59 	worktree = xcalloc(1, sizeof(*worktree));
60 	worktree->path = strbuf_detach(&worktree_path, NULL);
61 	/*
62 	 * NEEDSWORK: If this function is called from a secondary worktree and
63 	 * config.worktree is present, is_bare_repository_cfg will reflect the
64 	 * contents of config.worktree, not the contents of the main worktree.
65 	 * This means that worktree->is_bare may be set to 0 even if the main
66 	 * worktree is configured to be bare.
67 	 */
68 	worktree->is_bare = (is_bare_repository_cfg == 1) ||
69 		is_bare_repository();
70 	add_head_info(worktree);
71 
72 	strbuf_release(&path);
73 	strbuf_release(&worktree_path);
74 	return worktree;
75 }
76 
get_linked_worktree(const char * id)77 static struct worktree *get_linked_worktree(const char *id)
78 {
79 	struct worktree *worktree = NULL;
80 	struct strbuf path = STRBUF_INIT;
81 	struct strbuf worktree_path = STRBUF_INIT;
82 
83 	if (!id)
84 		die("Missing linked worktree name");
85 
86 	strbuf_git_common_path(&path, the_repository, "worktrees/%s/gitdir", id);
87 	if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0)
88 		/* invalid gitdir file */
89 		goto done;
90 
91 	strbuf_rtrim(&worktree_path);
92 	if (!strbuf_strip_suffix(&worktree_path, "/.git")) {
93 		strbuf_reset(&worktree_path);
94 		strbuf_add_absolute_path(&worktree_path, ".");
95 		strbuf_strip_suffix(&worktree_path, "/.");
96 	}
97 
98 	strbuf_reset(&path);
99 	strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
100 
101 	worktree = xcalloc(1, sizeof(*worktree));
102 	worktree->path = strbuf_detach(&worktree_path, NULL);
103 	worktree->id = xstrdup(id);
104 	add_head_info(worktree);
105 
106 done:
107 	strbuf_release(&path);
108 	strbuf_release(&worktree_path);
109 	return worktree;
110 }
111 
mark_current_worktree(struct worktree ** worktrees)112 static void mark_current_worktree(struct worktree **worktrees)
113 {
114 	char *git_dir = absolute_pathdup(get_git_dir());
115 	int i;
116 
117 	for (i = 0; worktrees[i]; i++) {
118 		struct worktree *wt = worktrees[i];
119 		const char *wt_git_dir = get_worktree_git_dir(wt);
120 
121 		if (!fspathcmp(git_dir, absolute_path(wt_git_dir))) {
122 			wt->is_current = 1;
123 			break;
124 		}
125 	}
126 	free(git_dir);
127 }
128 
compare_worktree(const void * a_,const void * b_)129 static int compare_worktree(const void *a_, const void *b_)
130 {
131 	const struct worktree *const *a = a_;
132 	const struct worktree *const *b = b_;
133 	return fspathcmp((*a)->path, (*b)->path);
134 }
135 
get_worktrees(unsigned flags)136 struct worktree **get_worktrees(unsigned flags)
137 {
138 	struct worktree **list = NULL;
139 	struct strbuf path = STRBUF_INIT;
140 	DIR *dir;
141 	struct dirent *d;
142 	int counter = 0, alloc = 2;
143 
144 	ALLOC_ARRAY(list, alloc);
145 
146 	list[counter++] = get_main_worktree();
147 
148 	strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
149 	dir = opendir(path.buf);
150 	strbuf_release(&path);
151 	if (dir) {
152 		while ((d = readdir(dir)) != NULL) {
153 			struct worktree *linked = NULL;
154 			if (is_dot_or_dotdot(d->d_name))
155 				continue;
156 
157 			if ((linked = get_linked_worktree(d->d_name))) {
158 				ALLOC_GROW(list, counter + 1, alloc);
159 				list[counter++] = linked;
160 			}
161 		}
162 		closedir(dir);
163 	}
164 	ALLOC_GROW(list, counter + 1, alloc);
165 	list[counter] = NULL;
166 
167 	if (flags & GWT_SORT_LINKED)
168 		/*
169 		 * don't sort the first item (main worktree), which will
170 		 * always be the first
171 		 */
172 		QSORT(list + 1, counter - 1, compare_worktree);
173 
174 	mark_current_worktree(list);
175 	return list;
176 }
177 
get_worktree_git_dir(const struct worktree * wt)178 const char *get_worktree_git_dir(const struct worktree *wt)
179 {
180 	if (!wt)
181 		return get_git_dir();
182 	else if (!wt->id)
183 		return get_git_common_dir();
184 	else
185 		return git_common_path("worktrees/%s", wt->id);
186 }
187 
find_worktree_by_suffix(struct worktree ** list,const char * suffix)188 static struct worktree *find_worktree_by_suffix(struct worktree **list,
189 						const char *suffix)
190 {
191 	struct worktree *found = NULL;
192 	int nr_found = 0, suffixlen;
193 
194 	suffixlen = strlen(suffix);
195 	if (!suffixlen)
196 		return NULL;
197 
198 	for (; *list && nr_found < 2; list++) {
199 		const char	*path	 = (*list)->path;
200 		int		 pathlen = strlen(path);
201 		int		 start	 = pathlen - suffixlen;
202 
203 		/* suffix must start at directory boundary */
204 		if ((!start || (start > 0 && is_dir_sep(path[start - 1]))) &&
205 		    !fspathcmp(suffix, path + start)) {
206 			found = *list;
207 			nr_found++;
208 		}
209 	}
210 	return nr_found == 1 ? found : NULL;
211 }
212 
find_worktree(struct worktree ** list,const char * prefix,const char * arg)213 struct worktree *find_worktree(struct worktree **list,
214 			       const char *prefix,
215 			       const char *arg)
216 {
217 	struct worktree *wt;
218 	char *path;
219 	char *to_free = NULL;
220 
221 	if ((wt = find_worktree_by_suffix(list, arg)))
222 		return wt;
223 
224 	if (prefix)
225 		arg = to_free = prefix_filename(prefix, arg);
226 	path = real_pathdup(arg, 0);
227 	if (!path) {
228 		free(to_free);
229 		return NULL;
230 	}
231 	for (; *list; list++) {
232 		const char *wt_path = real_path_if_valid((*list)->path);
233 
234 		if (wt_path && !fspathcmp(path, wt_path))
235 			break;
236 	}
237 	free(path);
238 	free(to_free);
239 	return *list;
240 }
241 
is_main_worktree(const struct worktree * wt)242 int is_main_worktree(const struct worktree *wt)
243 {
244 	return !wt->id;
245 }
246 
worktree_lock_reason(struct worktree * wt)247 const char *worktree_lock_reason(struct worktree *wt)
248 {
249 	assert(!is_main_worktree(wt));
250 
251 	if (!wt->lock_reason_valid) {
252 		struct strbuf path = STRBUF_INIT;
253 
254 		strbuf_addstr(&path, worktree_git_path(wt, "locked"));
255 		if (file_exists(path.buf)) {
256 			struct strbuf lock_reason = STRBUF_INIT;
257 			if (strbuf_read_file(&lock_reason, path.buf, 0) < 0)
258 				die_errno(_("failed to read '%s'"), path.buf);
259 			strbuf_trim(&lock_reason);
260 			wt->lock_reason = strbuf_detach(&lock_reason, NULL);
261 		} else
262 			wt->lock_reason = NULL;
263 		wt->lock_reason_valid = 1;
264 		strbuf_release(&path);
265 	}
266 
267 	return wt->lock_reason;
268 }
269 
270 /* convenient wrapper to deal with NULL strbuf */
strbuf_addf_gently(struct strbuf * buf,const char * fmt,...)271 static void strbuf_addf_gently(struct strbuf *buf, const char *fmt, ...)
272 {
273 	va_list params;
274 
275 	if (!buf)
276 		return;
277 
278 	va_start(params, fmt);
279 	strbuf_vaddf(buf, fmt, params);
280 	va_end(params);
281 }
282 
validate_worktree(const struct worktree * wt,struct strbuf * errmsg,unsigned flags)283 int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
284 		      unsigned flags)
285 {
286 	struct strbuf wt_path = STRBUF_INIT;
287 	char *path = NULL;
288 	int err, ret = -1;
289 
290 	strbuf_addf(&wt_path, "%s/.git", wt->path);
291 
292 	if (is_main_worktree(wt)) {
293 		if (is_directory(wt_path.buf)) {
294 			ret = 0;
295 			goto done;
296 		}
297 		/*
298 		 * Main worktree using .git file to point to the
299 		 * repository would make it impossible to know where
300 		 * the actual worktree is if this function is executed
301 		 * from another worktree. No .git file support for now.
302 		 */
303 		strbuf_addf_gently(errmsg,
304 				   _("'%s' at main working tree is not the repository directory"),
305 				   wt_path.buf);
306 		goto done;
307 	}
308 
309 	/*
310 	 * Make sure "gitdir" file points to a real .git file and that
311 	 * file points back here.
312 	 */
313 	if (!is_absolute_path(wt->path)) {
314 		strbuf_addf_gently(errmsg,
315 				   _("'%s' file does not contain absolute path to the working tree location"),
316 				   git_common_path("worktrees/%s/gitdir", wt->id));
317 		goto done;
318 	}
319 
320 	if (flags & WT_VALIDATE_WORKTREE_MISSING_OK &&
321 	    !file_exists(wt->path)) {
322 		ret = 0;
323 		goto done;
324 	}
325 
326 	if (!file_exists(wt_path.buf)) {
327 		strbuf_addf_gently(errmsg, _("'%s' does not exist"), wt_path.buf);
328 		goto done;
329 	}
330 
331 	path = xstrdup_or_null(read_gitfile_gently(wt_path.buf, &err));
332 	if (!path) {
333 		strbuf_addf_gently(errmsg, _("'%s' is not a .git file, error code %d"),
334 				   wt_path.buf, err);
335 		goto done;
336 	}
337 
338 	ret = fspathcmp(path, real_path(git_common_path("worktrees/%s", wt->id)));
339 
340 	if (ret)
341 		strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"),
342 				   wt->path, git_common_path("worktrees/%s", wt->id));
343 done:
344 	free(path);
345 	strbuf_release(&wt_path);
346 	return ret;
347 }
348 
update_worktree_location(struct worktree * wt,const char * path_)349 void update_worktree_location(struct worktree *wt, const char *path_)
350 {
351 	struct strbuf path = STRBUF_INIT;
352 
353 	if (is_main_worktree(wt))
354 		BUG("can't relocate main worktree");
355 
356 	strbuf_realpath(&path, path_, 1);
357 	if (fspathcmp(wt->path, path.buf)) {
358 		write_file(git_common_path("worktrees/%s/gitdir", wt->id),
359 			   "%s/.git", path.buf);
360 		free(wt->path);
361 		wt->path = strbuf_detach(&path, NULL);
362 	}
363 	strbuf_release(&path);
364 }
365 
is_worktree_being_rebased(const struct worktree * wt,const char * target)366 int is_worktree_being_rebased(const struct worktree *wt,
367 			      const char *target)
368 {
369 	struct wt_status_state state;
370 	int found_rebase;
371 
372 	memset(&state, 0, sizeof(state));
373 	found_rebase = wt_status_check_rebase(wt, &state) &&
374 		((state.rebase_in_progress ||
375 		  state.rebase_interactive_in_progress) &&
376 		 state.branch &&
377 		 starts_with(target, "refs/heads/") &&
378 		 !strcmp(state.branch, target + strlen("refs/heads/")));
379 	free(state.branch);
380 	free(state.onto);
381 	return found_rebase;
382 }
383 
is_worktree_being_bisected(const struct worktree * wt,const char * target)384 int is_worktree_being_bisected(const struct worktree *wt,
385 			       const char *target)
386 {
387 	struct wt_status_state state;
388 	int found_rebase;
389 
390 	memset(&state, 0, sizeof(state));
391 	found_rebase = wt_status_check_bisect(wt, &state) &&
392 		state.branch &&
393 		starts_with(target, "refs/heads/") &&
394 		!strcmp(state.branch, target + strlen("refs/heads/"));
395 	free(state.branch);
396 	return found_rebase;
397 }
398 
399 /*
400  * note: this function should be able to detect shared symref even if
401  * HEAD is temporarily detached (e.g. in the middle of rebase or
402  * bisect). New commands that do similar things should update this
403  * function as well.
404  */
find_shared_symref(const char * symref,const char * target)405 const struct worktree *find_shared_symref(const char *symref,
406 					  const char *target)
407 {
408 	const struct worktree *existing = NULL;
409 	static struct worktree **worktrees;
410 	int i = 0;
411 
412 	if (worktrees)
413 		free_worktrees(worktrees);
414 	worktrees = get_worktrees(0);
415 
416 	for (i = 0; worktrees[i]; i++) {
417 		struct worktree *wt = worktrees[i];
418 		const char *symref_target;
419 		struct ref_store *refs;
420 		int flags;
421 
422 		if (wt->is_bare)
423 			continue;
424 
425 		if (wt->is_detached && !strcmp(symref, "HEAD")) {
426 			if (is_worktree_being_rebased(wt, target)) {
427 				existing = wt;
428 				break;
429 			}
430 			if (is_worktree_being_bisected(wt, target)) {
431 				existing = wt;
432 				break;
433 			}
434 		}
435 
436 		refs = get_worktree_ref_store(wt);
437 		symref_target = refs_resolve_ref_unsafe(refs, symref, 0,
438 							NULL, &flags);
439 		if ((flags & REF_ISSYMREF) &&
440 		    symref_target && !strcmp(symref_target, target)) {
441 			existing = wt;
442 			break;
443 		}
444 	}
445 
446 	return existing;
447 }
448 
submodule_uses_worktrees(const char * path)449 int submodule_uses_worktrees(const char *path)
450 {
451 	char *submodule_gitdir;
452 	struct strbuf sb = STRBUF_INIT;
453 	DIR *dir;
454 	struct dirent *d;
455 	int ret = 0;
456 	struct repository_format format = REPOSITORY_FORMAT_INIT;
457 
458 	submodule_gitdir = git_pathdup_submodule(path, "%s", "");
459 	if (!submodule_gitdir)
460 		return 0;
461 
462 	/* The env would be set for the superproject. */
463 	get_common_dir_noenv(&sb, submodule_gitdir);
464 	free(submodule_gitdir);
465 
466 	/*
467 	 * The check below is only known to be good for repository format
468 	 * version 0 at the time of writing this code.
469 	 */
470 	strbuf_addstr(&sb, "/config");
471 	read_repository_format(&format, sb.buf);
472 	if (format.version != 0) {
473 		strbuf_release(&sb);
474 		clear_repository_format(&format);
475 		return 1;
476 	}
477 	clear_repository_format(&format);
478 
479 	/* Replace config by worktrees. */
480 	strbuf_setlen(&sb, sb.len - strlen("config"));
481 	strbuf_addstr(&sb, "worktrees");
482 
483 	/* See if there is any file inside the worktrees directory. */
484 	dir = opendir(sb.buf);
485 	strbuf_release(&sb);
486 
487 	if (!dir)
488 		return 0;
489 
490 	while ((d = readdir(dir)) != NULL) {
491 		if (is_dot_or_dotdot(d->d_name))
492 			continue;
493 
494 		ret = 1;
495 		break;
496 	}
497 	closedir(dir);
498 	return ret;
499 }
500 
parse_worktree_ref(const char * worktree_ref,const char ** name,int * name_length,const char ** ref)501 int parse_worktree_ref(const char *worktree_ref, const char **name,
502 		       int *name_length, const char **ref)
503 {
504 	if (skip_prefix(worktree_ref, "main-worktree/", &worktree_ref)) {
505 		if (!*worktree_ref)
506 			return -1;
507 		if (name)
508 			*name = NULL;
509 		if (name_length)
510 			*name_length = 0;
511 		if (ref)
512 			*ref = worktree_ref;
513 		return 0;
514 	}
515 	if (skip_prefix(worktree_ref, "worktrees/", &worktree_ref)) {
516 		const char *slash = strchr(worktree_ref, '/');
517 
518 		if (!slash || slash == worktree_ref || !slash[1])
519 			return -1;
520 		if (name)
521 			*name = worktree_ref;
522 		if (name_length)
523 			*name_length = slash - worktree_ref;
524 		if (ref)
525 			*ref = slash + 1;
526 		return 0;
527 	}
528 	return -1;
529 }
530 
strbuf_worktree_ref(const struct worktree * wt,struct strbuf * sb,const char * refname)531 void strbuf_worktree_ref(const struct worktree *wt,
532 			 struct strbuf *sb,
533 			 const char *refname)
534 {
535 	switch (ref_type(refname)) {
536 	case REF_TYPE_PSEUDOREF:
537 	case REF_TYPE_PER_WORKTREE:
538 		if (wt && !wt->is_current) {
539 			if (is_main_worktree(wt))
540 				strbuf_addstr(sb, "main-worktree/");
541 			else
542 				strbuf_addf(sb, "worktrees/%s/", wt->id);
543 		}
544 		break;
545 
546 	case REF_TYPE_MAIN_PSEUDOREF:
547 	case REF_TYPE_OTHER_PSEUDOREF:
548 		break;
549 
550 	case REF_TYPE_NORMAL:
551 		/*
552 		 * For shared refs, don't prefix worktrees/ or
553 		 * main-worktree/. It's not necessary and
554 		 * files-backend.c can't handle it anyway.
555 		 */
556 		break;
557 	}
558 	strbuf_addstr(sb, refname);
559 }
560 
worktree_ref(const struct worktree * wt,const char * refname)561 const char *worktree_ref(const struct worktree *wt, const char *refname)
562 {
563 	static struct strbuf sb = STRBUF_INIT;
564 
565 	strbuf_reset(&sb);
566 	strbuf_worktree_ref(wt, &sb, refname);
567 	return sb.buf;
568 }
569 
other_head_refs(each_ref_fn fn,void * cb_data)570 int other_head_refs(each_ref_fn fn, void *cb_data)
571 {
572 	struct worktree **worktrees, **p;
573 	int ret = 0;
574 
575 	worktrees = get_worktrees(0);
576 	for (p = worktrees; *p; p++) {
577 		struct worktree *wt = *p;
578 		struct object_id oid;
579 		int flag;
580 
581 		if (wt->is_current)
582 			continue;
583 
584 		if (!refs_read_ref_full(get_main_ref_store(the_repository),
585 					worktree_ref(wt, "HEAD"),
586 					RESOLVE_REF_READING,
587 					&oid, &flag))
588 			ret = fn(worktree_ref(wt, "HEAD"), &oid, flag, cb_data);
589 		if (ret)
590 			break;
591 	}
592 	free_worktrees(worktrees);
593 	return ret;
594 }
595