Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion builtin/worktree.c
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,14 @@ static int add(int ac, const char **av, const char *prefix,
if (ac < 1 || ac > 2)
usage_with_options(git_worktree_add_usage, options);

/*
* When the virtual file system is active, skip checkout during
* worktree creation. The VFS layer will handle the checkout
* after the worktree structure is set up.
*/
if (gvfs_config_is_set(the_repository, GVFS_USE_VIRTUAL_FILESYSTEM))
opts.checkout = 0;

path = prefix_filename(prefix, av[0]);
branch = ac < 2 ? "HEAD" : av[1];
used_new_branch_options = new_branch || new_branch_force;
Expand Down Expand Up @@ -1358,6 +1366,21 @@ static int delete_git_work_tree(struct worktree *wt)
return ret;
}

/*
* Check if a pre-command hook has already verified worktree cleanliness
* and written a marker file to skip git's own check. VFSForGit uses this
* to unmount ProjFS after its own status check; without it, git's status
* call would fail because the virtual filesystem is no longer available.
*/
static int should_skip_clean_check(struct worktree *wt)
{
char *path = repo_common_path(the_repository,
"worktrees/%s/skip-clean-check", wt->id);
int skip = file_exists(path);
free(path);
return skip;
}

static int remove_worktree(int ac, const char **av, const char *prefix,
struct repository *repo UNUSED)
{
Expand Down Expand Up @@ -1397,7 +1420,7 @@ static int remove_worktree(int ac, const char **av, const char *prefix,
strbuf_release(&errmsg);

if (file_exists(wt->path)) {
if (!force)
if (!force && !(core_virtualfilesystem && should_skip_clean_check(wt)))
check_clean_worktree(wt, av[0]);

ret |= delete_git_work_tree(wt);
Expand Down Expand Up @@ -1469,6 +1492,14 @@ int cmd_worktree(int ac,

ac = parse_options(ac, av, prefix, options, git_worktree_usage, 0);

/*
* Block worktree commands when VFS is active unless the VFS layer
* has signaled worktree support via GVFS_SUPPORTS_WORKTREES.
*/
if (gvfs_config_is_set(the_repository, GVFS_USE_VIRTUAL_FILESYSTEM) &&
!gvfs_config_is_set(the_repository, GVFS_SUPPORTS_WORKTREES))
die("'git worktree' is not supported when using the virtual file system");

prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;

Expand Down
2 changes: 1 addition & 1 deletion git.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ static struct cmd_struct commands[] = {
#ifndef WITH_BREAKING_CHANGES
{ "whatchanged", cmd_whatchanged, RUN_SETUP | DEPRECATED },
#endif
{ "worktree", cmd_worktree, RUN_SETUP | BLOCK_ON_VFS_ENABLED },
{ "worktree", cmd_worktree, RUN_SETUP },
{ "write-tree", cmd_write_tree, RUN_SETUP },
};

Expand Down
7 changes: 7 additions & 0 deletions gvfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ struct repository;
#define GVFS_BLOCK_FILTERS_AND_EOL_CONVERSIONS (1 << 6)
#define GVFS_PREFETCH_DURING_FETCH (1 << 7)

/*
* When set, this flag indicates that the VFS layer supports
* git worktrees. This allows `git worktree add/remove` to
* operate on VFS-enabled repositories.
*/
#define GVFS_SUPPORTS_WORKTREES (1 << 8)

#define GVFS_ANY_MASK 0xFFFFFFFF

int gvfs_config_is_set(struct repository *r, int mask);
Expand Down
29 changes: 28 additions & 1 deletion t/t0402-block-command-on-gvfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,34 @@ not_with_gvfs update-index --index-version 2
not_with_gvfs update-index --skip-worktree
not_with_gvfs update-index --no-skip-worktree
not_with_gvfs update-index --split-index
not_with_gvfs worktree list

# worktree is conditionally allowed: blocked when VFS enabled without
# GVFS_SUPPORTS_WORKTREES.
test_expect_success 'worktree blocked with VFS but without SUPPORTS_WORKTREES' '
test_config core.gvfs 95 &&
test_must_fail git worktree list 2>err &&
test_grep "not supported when using the virtual file system" err
'

test_expect_success 'worktree operations work when SUPPORTS_WORKTREES is set' '
test_commit initial &&

# Use core.gvfs=true which sets all bits including SUPPORTS_WORKTREES.
test_config core.gvfs true &&

# add: succeeds, forces --no-checkout (no initial.t on disk)
git worktree add ../vfs-wt &&
test_path_exists ../vfs-wt/.git &&
! test_path_exists ../vfs-wt/initial.t &&

# list: shows the worktree
git worktree list >out &&
grep "vfs-wt" out &&

# remove: cleans up
git worktree remove --force ../vfs-wt &&
! test_path_exists ../vfs-wt
'

test_expect_success 'test gc --auto succeeds when disabled via config' '
test_config core.gvfs true &&
Expand Down
Loading