Skip to content

Commit 1a248cf

Browse files
stefanbellergitster
authored andcommitted
worktree: check if a submodule uses worktrees
In a later patch we want to move around the the git directory of a submodule. Both submodules as well as worktrees are involved in placing git directories at unusual places, so their functionality may collide. To react appropriately to situations where worktrees in submodules are in use, offer a new function to query the a submodule if it uses the worktree feature. An earlier approach: "Implement submodule_get_worktrees and just count them", however: This can be done cheaply (both in new code to write as well as run time) by obtaining the list of worktrees based off that submodules git directory. However as we have loaded the variables for the current repository, the values in the submodule worktree can be wrong, e.g. * core.ignorecase may differ between these two repositories * the ref resolution is broken (refs/heads/branch in the submodule resolves to the sha1 value of the `branch` in the current repository that may not exist or have another sha1) The implementation here is just checking for any files in $GIT_COMMON_DIR/worktrees for the submodule, which ought to be sufficient if the submodule is using the current repository format, which we also check. Signed-off-by: Stefan Beller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6f94351 commit 1a248cf

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

worktree.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,53 @@ const struct worktree *find_shared_symref(const char *symref,
380380

381381
return existing;
382382
}
383+
384+
int submodule_uses_worktrees(const char *path)
385+
{
386+
char *submodule_gitdir;
387+
struct strbuf sb = STRBUF_INIT;
388+
DIR *dir;
389+
struct dirent *d;
390+
int ret;
391+
struct repository_format format;
392+
393+
submodule_gitdir = git_pathdup_submodule(path, "%s", "");
394+
if (!submodule_gitdir)
395+
return 0;
396+
397+
/* The env would be set for the superproject. */
398+
get_common_dir_noenv(&sb, submodule_gitdir);
399+
400+
/*
401+
* The check below is only known to be good for repository format
402+
* version 0 at the time of writing this code.
403+
*/
404+
strbuf_addstr(&sb, "/config");
405+
read_repository_format(&format, sb.buf);
406+
if (format.version != 0) {
407+
strbuf_release(&sb);
408+
return 1;
409+
}
410+
411+
/* Replace config by worktrees. */
412+
strbuf_setlen(&sb, sb.len - strlen("config"));
413+
strbuf_addstr(&sb, "worktrees");
414+
415+
/* See if there is any file inside the worktrees directory. */
416+
dir = opendir(sb.buf);
417+
strbuf_release(&sb);
418+
free(submodule_gitdir);
419+
420+
if (!dir)
421+
return 0;
422+
423+
while ((d = readdir(dir)) != NULL) {
424+
if (is_dot_or_dotdot(d->d_name))
425+
continue;
426+
427+
ret = 1;
428+
break;
429+
}
430+
closedir(dir);
431+
return ret;
432+
}

worktree.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ struct worktree {
2727
*/
2828
extern struct worktree **get_worktrees(unsigned flags);
2929

30+
/*
31+
* Returns 1 if linked worktrees exist, 0 otherwise.
32+
*/
33+
extern int submodule_uses_worktrees(const char *path);
34+
3035
/*
3136
* Return git dir of the worktree. Note that the path may be relative.
3237
* If wt is NULL, git dir of current worktree is returned.

0 commit comments

Comments
 (0)