Skip to content

Commit 0f2d4f6

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 <[email protected]>
1 parent d80ee09 commit 0f2d4f6

18 files changed

+826
-8
lines changed

Documentation/config/core.adoc

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.adoc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,26 @@ and "0" meaning they were not.
758758
Only one parameter should be set to "1" when the hook runs. The hook
759759
running passing "1", "1" should not be possible.
760760
761+
virtualFilesystem
762+
~~~~~~~~~~~~~~~~~~
763+
764+
"Virtual File System" allows populating the working directory sparsely.
765+
The projection data is typically automatically generated by an external
766+
process. Git will limit what files it checks for changes as well as which
767+
directories are checked for untracked files based on the path names given.
768+
Git will also only update those files listed in the projection.
769+
770+
The hook is invoked when the configuration option core.virtualFilesystem
771+
is set. It takes one argument, a version (currently 1).
772+
773+
The hook should output to stdout the list of all files in the working
774+
directory that git should track. The paths are relative to the root
775+
of the working directory and are separated by a single NUL. Full paths
776+
('dir1/a.txt') as well as directories are supported (ie 'dir1/').
777+
778+
The exit status determines whether git will use the data from the
779+
hook. On error, git will abort the command with an error message.
780+
761781
SEE ALSO
762782
--------
763783
linkgit:git-hook[1]

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,7 @@ LIB_OBJS += utf8.o
12081208
LIB_OBJS += varint.o
12091209
LIB_OBJS += version.o
12101210
LIB_OBJS += versioncmp.o
1211+
LIB_OBJS += virtualfilesystem.o
12111212
LIB_OBJS += walker.o
12121213
LIB_OBJS += wildmatch.o
12131214
LIB_OBJS += worktree.o

config.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,11 @@ int git_default_core_config(const char *var, const char *value,
16191619
}
16201620

16211621
if (!strcmp(var, "core.sparsecheckout")) {
1622-
core_apply_sparse_checkout = git_config_bool(var, value);
1622+
/* virtual file system relies on the sparse checkout logic so force it on */
1623+
if (core_virtualfilesystem)
1624+
core_apply_sparse_checkout = 1;
1625+
else
1626+
core_apply_sparse_checkout = git_config_bool(var, value);
16231627
return 0;
16241628
}
16251629

@@ -2714,6 +2718,30 @@ int repo_config_get_max_percent_split_change(struct repository *r)
27142718
return -1; /* default value */
27152719
}
27162720

2721+
int repo_config_get_virtualfilesystem(struct repository *r)
2722+
{
2723+
/* Run only once. */
2724+
static int virtual_filesystem_result = -1;
2725+
if (virtual_filesystem_result >= 0)
2726+
return virtual_filesystem_result;
2727+
2728+
if (repo_config_get_pathname(r, "core.virtualfilesystem", &core_virtualfilesystem))
2729+
core_virtualfilesystem = xstrdup_or_null(getenv("GIT_VIRTUALFILESYSTEM_TEST"));
2730+
2731+
if (core_virtualfilesystem && !*core_virtualfilesystem)
2732+
FREE_AND_NULL(core_virtualfilesystem);
2733+
2734+
/* virtual file system relies on the sparse checkout logic so force it on */
2735+
if (core_virtualfilesystem) {
2736+
core_apply_sparse_checkout = 1;
2737+
virtual_filesystem_result = 1;
2738+
return 1;
2739+
}
2740+
2741+
virtual_filesystem_result = 0;
2742+
return 0;
2743+
}
2744+
27172745
int repo_config_get_index_threads(struct repository *r, int *dest)
27182746
{
27192747
int is_bool, val;

config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,8 @@ int repo_config_get_index_threads(struct repository *r, int *dest);
693693
int repo_config_get_split_index(struct repository *r);
694694
int repo_config_get_max_percent_split_change(struct repository *r);
695695

696+
int repo_config_get_virtualfilesystem(struct repository *r);
697+
696698
/* This dies if the configured or default date is in the future */
697699
int repo_config_get_expiry(struct repository *r, const char *key, char **output);
698700

dir.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "git-compat-util.h"
1313
#include "abspath.h"
14+
#include "virtualfilesystem.h"
1415
#include "config.h"
1516
#include "convert.h"
1617
#include "dir.h"
@@ -1485,6 +1486,19 @@ enum pattern_match_result path_matches_pattern_list(
14851486
int result = NOT_MATCHED;
14861487
size_t slash_pos;
14871488

1489+
if (core_virtualfilesystem) {
1490+
/*
1491+
* The virtual file system data is used to prevent git from traversing
1492+
* any part of the tree that is not in the virtual file system. Return
1493+
* 1 to exclude the entry if it is not found in the virtual file system,
1494+
* else fall through to the regular excludes logic as it may further exclude.
1495+
*/
1496+
if (*dtype == DT_UNKNOWN)
1497+
*dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen);
1498+
if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0)
1499+
return 1;
1500+
}
1501+
14881502
if (!pl->use_cone_patterns) {
14891503
pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
14901504
dtype, pl, istate);
@@ -1829,8 +1843,22 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir,
18291843
int is_excluded(struct dir_struct *dir, struct index_state *istate,
18301844
const char *pathname, int *dtype_p)
18311845
{
1832-
struct path_pattern *pattern =
1833-
last_matching_pattern(dir, istate, pathname, dtype_p);
1846+
struct path_pattern *pattern;
1847+
1848+
if (core_virtualfilesystem) {
1849+
/*
1850+
* The virtual file system data is used to prevent git from traversing
1851+
* any part of the tree that is not in the virtual file system. Return
1852+
* 1 to exclude the entry if it is not found in the virtual file system,
1853+
* else fall through to the regular excludes logic as it may further exclude.
1854+
*/
1855+
if (*dtype_p == DT_UNKNOWN)
1856+
*dtype_p = resolve_dtype(DT_UNKNOWN, istate, pathname, strlen(pathname));
1857+
if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0)
1858+
return 1;
1859+
}
1860+
1861+
pattern = last_matching_pattern(dir, istate, pathname, dtype_p);
18341862
if (pattern)
18351863
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;
18361864
return 0;
@@ -2448,6 +2476,8 @@ static enum path_treatment treat_path(struct dir_struct *dir,
24482476
ignore_case);
24492477
if (dtype != DT_DIR && has_path_in_index)
24502478
return path_none;
2479+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0)
2480+
return path_excluded;
24512481

24522482
/*
24532483
* When we are looking at a directory P in the working tree,
@@ -2652,6 +2682,8 @@ static void add_path_to_appropriate_result_list(struct dir_struct *dir,
26522682
/* add the path to the appropriate result list */
26532683
switch (state) {
26542684
case path_excluded:
2685+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, DT_DIR) > 0)
2686+
break;
26552687
if (dir->flags & DIR_SHOW_IGNORED)
26562688
dir_add_name(dir, istate, path->buf, path->len);
26572689
else if ((dir->flags & DIR_SHOW_IGNORED_TOO) ||

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ int core_apply_sparse_checkout;
6868
int core_sparse_checkout_cone;
6969
int sparse_expect_files_outside_of_patterns;
7070
int core_gvfs;
71+
char *core_virtualfilesystem;
7172
int merge_log_config = -1;
7273
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
7374
unsigned long pack_size_limit_cfg;

environment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ extern unsigned long pack_size_limit_cfg;
156156
extern int max_allowed_tree_depth;
157157

158158
extern int core_preload_index;
159+
extern char *core_virtualfilesystem;
159160
extern int core_gvfs;
160161
extern int precomposed_unicode;
161162
extern int protect_hfs;

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ libgit_sources = [
526526
'varint.c',
527527
'version.c',
528528
'versioncmp.c',
529+
'virtualfilesystem.c',
529530
'walker.c',
530531
'wildmatch.c',
531532
'worktree.c',

read-cache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "git-compat-util.h"
1111
#include "bulk-checkin.h"
12+
#include "virtualfilesystem.h"
1213
#include "config.h"
1314
#include "date.h"
1415
#include "diff.h"
@@ -1952,6 +1953,7 @@ static void post_read_index_from(struct index_state *istate)
19521953
tweak_untracked_cache(istate);
19531954
tweak_split_index(istate);
19541955
tweak_fsmonitor(istate);
1956+
apply_virtualfilesystem(istate);
19551957
}
19561958

19571959
static size_t estimate_cache_size_from_compressed(unsigned int entries)

0 commit comments

Comments
 (0)