Skip to content

Commit 4ddddc1

Browse files
pcloudsgitster
authored andcommitted
worktree.c: add validate_worktree()
This function is later used by "worktree move" and "worktree remove" to ensure that we have a good connection between the repository and the worktree. For example, if a worktree is moved manually, the worktree location recorded in $GIT_DIR/worktrees/.../gitdir is incorrect and we should not move that one. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8279ed0 commit 4ddddc1

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

worktree.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,78 @@ const char *is_worktree_locked(struct worktree *wt)
254254
return wt->lock_reason;
255255
}
256256

257+
/* convenient wrapper to deal with NULL strbuf */
258+
static void strbuf_addf_gently(struct strbuf *buf, const char *fmt, ...)
259+
{
260+
va_list params;
261+
262+
if (!buf)
263+
return;
264+
265+
va_start(params, fmt);
266+
strbuf_vaddf(buf, fmt, params);
267+
va_end(params);
268+
}
269+
270+
int validate_worktree(const struct worktree *wt, struct strbuf *errmsg)
271+
{
272+
struct strbuf wt_path = STRBUF_INIT;
273+
char *path = NULL;
274+
int err, ret = -1;
275+
276+
strbuf_addf(&wt_path, "%s/.git", wt->path);
277+
278+
if (is_main_worktree(wt)) {
279+
if (is_directory(wt_path.buf)) {
280+
ret = 0;
281+
goto done;
282+
}
283+
/*
284+
* Main worktree using .git file to point to the
285+
* repository would make it impossible to know where
286+
* the actual worktree is if this function is executed
287+
* from another worktree. No .git file support for now.
288+
*/
289+
strbuf_addf_gently(errmsg,
290+
_("'%s' at main working tree is not the repository directory"),
291+
wt_path.buf);
292+
goto done;
293+
}
294+
295+
/*
296+
* Make sure "gitdir" file points to a real .git file and that
297+
* file points back here.
298+
*/
299+
if (!is_absolute_path(wt->path)) {
300+
strbuf_addf_gently(errmsg,
301+
_("'%s' file does not contain absolute path to the working tree location"),
302+
git_common_path("worktrees/%s/gitdir", wt->id));
303+
goto done;
304+
}
305+
306+
if (!file_exists(wt_path.buf)) {
307+
strbuf_addf_gently(errmsg, _("'%s' does not exist"), wt_path.buf);
308+
goto done;
309+
}
310+
311+
path = xstrdup_or_null(read_gitfile_gently(wt_path.buf, &err));
312+
if (!path) {
313+
strbuf_addf_gently(errmsg, _("'%s' is not a .git file, error code %d"),
314+
wt_path.buf, err);
315+
goto done;
316+
}
317+
318+
ret = fspathcmp(path, real_path(git_common_path("worktrees/%s", wt->id)));
319+
320+
if (ret)
321+
strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"),
322+
wt->path, git_common_path("worktrees/%s", wt->id));
323+
done:
324+
free(path);
325+
strbuf_release(&wt_path);
326+
return ret;
327+
}
328+
257329
int is_worktree_being_rebased(const struct worktree *wt,
258330
const char *target)
259331
{

worktree.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "refs.h"
55

6+
struct strbuf;
7+
68
struct worktree {
79
char *path;
810
char *id;
@@ -59,6 +61,13 @@ extern int is_main_worktree(const struct worktree *wt);
5961
*/
6062
extern const char *is_worktree_locked(struct worktree *wt);
6163

64+
/*
65+
* Return zero if the worktree is in good condition. Error message is
66+
* returned if "errmsg" is not NULL.
67+
*/
68+
extern int validate_worktree(const struct worktree *wt,
69+
struct strbuf *errmsg);
70+
6271
/*
6372
* Free up the memory for worktree(s)
6473
*/

0 commit comments

Comments
 (0)