Skip to content

Commit e53ecaf

Browse files
benpeartdscho
authored andcommitted
Add virtual file system settings and hook proc
On index load, clear/set the skip worktree bits based on the virtual file system data. Use virtual file system data to update skip-worktree bit in unpack-trees. Use virtual file system data to exclude files and folders not explicitly requested. Update 2022-04-05: disable the "present-despite-SKIP_WORKTREE" file removal behavior when 'core.virtualfilesystem' is enabled. Signed-off-by: Ben Peart <benpeart@microsoft.com>
1 parent 93a2c24 commit e53ecaf

16 files changed

+794
-6
lines changed

Documentation/config/core.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ Version 2 uses an opaque string so that the monitor can return
111111
something that can be used to determine what files have changed
112112
without race conditions.
113113

114+
core.virtualFilesystem::
115+
If set, the value of this variable is used as a command which
116+
will identify all files and directories that are present in
117+
the working directory. Git will only track and update files
118+
listed in the virtual file system. Using the virtual file system
119+
will supersede the sparse-checkout settings which will be ignored.
120+
See the "virtual file system" section of linkgit:githooks[5].
121+
114122
core.trustctime::
115123
If false, the ctime differences between the index and the
116124
working tree are ignored; useful when the inode change time

Documentation/githooks.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,26 @@ and "0" meaning they were not.
698698
Only one parameter should be set to "1" when the hook runs. The hook
699699
running passing "1", "1" should not be possible.
700700

701+
virtualFilesystem
702+
~~~~~~~~~~~~~~~~~~
703+
704+
"Virtual File System" allows populating the working directory sparsely.
705+
The projection data is typically automatically generated by an external
706+
process. Git will limit what files it checks for changes as well as which
707+
directories are checked for untracked files based on the path names given.
708+
Git will also only update those files listed in the projection.
709+
710+
The hook is invoked when the configuration option core.virtualFilesystem
711+
is set. It takes one argument, a version (currently 1).
712+
713+
The hook should output to stdout the list of all files in the working
714+
directory that git should track. The paths are relative to the root
715+
of the working directory and are separated by a single NUL. Full paths
716+
('dir1/a.txt') as well as directories are supported (ie 'dir1/').
717+
718+
The exit status determines whether git will use the data from the
719+
hook. On error, git will abort the command with an error message.
720+
701721
SEE ALSO
702722
--------
703723
linkgit:git-hook[1]

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ LIB_OBJS += utf8.o
11211121
LIB_OBJS += varint.o
11221122
LIB_OBJS += version.o
11231123
LIB_OBJS += versioncmp.o
1124+
LIB_OBJS += virtualfilesystem.o
11241125
LIB_OBJS += walker.o
11251126
LIB_OBJS += wildmatch.o
11261127
LIB_OBJS += worktree.o

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,7 @@ enum fsync_method {
10741074

10751075
extern enum fsync_method fsync_method;
10761076
extern int core_preload_index;
1077+
extern const char *core_virtualfilesystem;
10771078
extern int core_gvfs;
10781079
extern int precomposed_unicode;
10791080
extern int protect_hfs;

config.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,11 @@ int git_default_core_config(const char *var, const char *value, void *cb)
17361736
}
17371737

17381738
if (!strcmp(var, "core.sparsecheckout")) {
1739-
core_apply_sparse_checkout = git_config_bool(var, value);
1739+
/* virtual file system relies on the sparse checkout logic so force it on */
1740+
if (core_virtualfilesystem)
1741+
core_apply_sparse_checkout = 1;
1742+
else
1743+
core_apply_sparse_checkout = git_config_bool(var, value);
17401744
return 0;
17411745
}
17421746

@@ -2800,6 +2804,30 @@ int git_config_get_max_percent_split_change(void)
28002804
return -1; /* default value */
28012805
}
28022806

2807+
int git_config_get_virtualfilesystem(void)
2808+
{
2809+
/* Run only once. */
2810+
static int virtual_filesystem_result = -1;
2811+
if (virtual_filesystem_result >= 0)
2812+
return virtual_filesystem_result;
2813+
2814+
if (git_config_get_pathname("core.virtualfilesystem", &core_virtualfilesystem))
2815+
core_virtualfilesystem = getenv("GIT_VIRTUALFILESYSTEM_TEST");
2816+
2817+
if (core_virtualfilesystem && !*core_virtualfilesystem)
2818+
core_virtualfilesystem = NULL;
2819+
2820+
/* virtual file system relies on the sparse checkout logic so force it on */
2821+
if (core_virtualfilesystem) {
2822+
core_apply_sparse_checkout = 1;
2823+
virtual_filesystem_result = 1;
2824+
return 1;
2825+
}
2826+
2827+
virtual_filesystem_result = 0;
2828+
return 0;
2829+
}
2830+
28032831
int git_config_get_index_threads(int *dest)
28042832
{
28052833
int is_bool, val;

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,7 @@ int git_config_get_pathname(const char *key, const char **dest);
614614
int git_config_get_index_threads(int *dest);
615615
int git_config_get_split_index(void);
616616
int git_config_get_max_percent_split_change(void);
617+
int git_config_get_virtualfilesystem(void);
617618

618619
/* This dies if the configured or default date is in the future */
619620
int git_config_get_expiry(const char *key, const char **output);

dir.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Junio Hamano, 2005-2006
77
*/
88
#include "cache.h"
9+
#include "virtualfilesystem.h"
910
#include "config.h"
1011
#include "dir.h"
1112
#include "object-store.h"
@@ -1414,6 +1415,17 @@ enum pattern_match_result path_matches_pattern_list(
14141415
int result = NOT_MATCHED;
14151416
size_t slash_pos;
14161417

1418+
/*
1419+
* The virtual file system data is used to prevent git from traversing
1420+
* any part of the tree that is not in the virtual file system. Return
1421+
* 1 to exclude the entry if it is not found in the virtual file system,
1422+
* else fall through to the regular excludes logic as it may further exclude.
1423+
*/
1424+
if (*dtype == DT_UNKNOWN)
1425+
*dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen);
1426+
if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0)
1427+
return 1;
1428+
14171429
if (!pl->use_cone_patterns) {
14181430
pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
14191431
dtype, pl, istate);
@@ -1757,8 +1769,20 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir,
17571769
int is_excluded(struct dir_struct *dir, struct index_state *istate,
17581770
const char *pathname, int *dtype_p)
17591771
{
1760-
struct path_pattern *pattern =
1761-
last_matching_pattern(dir, istate, pathname, dtype_p);
1772+
struct path_pattern *pattern;
1773+
1774+
/*
1775+
* The virtual file system data is used to prevent git from traversing
1776+
* any part of the tree that is not in the virtual file system. Return
1777+
* 1 to exclude the entry if it is not found in the virtual file system,
1778+
* else fall through to the regular excludes logic as it may further exclude.
1779+
*/
1780+
if (*dtype_p == DT_UNKNOWN)
1781+
*dtype_p = resolve_dtype(DT_UNKNOWN, istate, pathname, strlen(pathname));
1782+
if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0)
1783+
return 1;
1784+
1785+
pattern = last_matching_pattern(dir, istate, pathname, dtype_p);
17621786
if (pattern)
17631787
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;
17641788
return 0;
@@ -2344,6 +2368,8 @@ static enum path_treatment treat_path(struct dir_struct *dir,
23442368
ignore_case);
23452369
if (dtype != DT_DIR && has_path_in_index)
23462370
return path_none;
2371+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0)
2372+
return path_excluded;
23472373

23482374
/*
23492375
* When we are looking at a directory P in the working tree,
@@ -2548,6 +2574,8 @@ static void add_path_to_appropriate_result_list(struct dir_struct *dir,
25482574
/* add the path to the appropriate result list */
25492575
switch (state) {
25502576
case path_excluded:
2577+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, DT_DIR) > 0)
2578+
break;
25512579
if (dir->flags & DIR_SHOW_IGNORED)
25522580
dir_add_name(dir, istate, path->buf, path->len);
25532581
else if ((dir->flags & DIR_SHOW_IGNORED_TOO) ||

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ int core_apply_sparse_checkout;
7373
int core_sparse_checkout_cone;
7474
int sparse_expect_files_outside_of_patterns;
7575
int core_gvfs;
76+
const char *core_virtualfilesystem;
7677
int merge_log_config = -1;
7778
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
7879
unsigned long pack_size_limit_cfg;

read-cache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
#include "cache.h"
77
#include "gvfs.h"
8+
#include "virtualfilesystem.h"
89
#include "config.h"
910
#include "diff.h"
1011
#include "diffcore.h"
@@ -2047,6 +2048,7 @@ static void post_read_index_from(struct index_state *istate)
20472048
tweak_untracked_cache(istate);
20482049
tweak_split_index(istate);
20492050
tweak_fsmonitor(istate);
2051+
apply_virtualfilesystem(istate);
20502052
}
20512053

20522054
static size_t estimate_cache_size_from_compressed(unsigned int entries)

sparse-index.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ void clear_skip_worktree_from_present_files(struct index_state *istate)
495495
int i;
496496

497497
if (!core_apply_sparse_checkout ||
498+
core_virtualfilesystem ||
498499
sparse_expect_files_outside_of_patterns)
499500
return;
500501

0 commit comments

Comments
 (0)