Skip to content

Commit 322557a

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. Signed-off-by: Ben Peart <[email protected]>
1 parent 7d4dce9 commit 322557a

13 files changed

+789
-9
lines changed

Documentation/config/core.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ core.fsmonitor::
6868
avoiding unnecessary processing of files that have not changed.
6969
See the "fsmonitor-watchman" section of linkgit:githooks[5].
7070

71+
core.virtualFilesystem::
72+
If set, the value of this variable is used as a command which
73+
will identify all files and directories that are present in
74+
the working directory. Git will only track and update files
75+
listed in the virtual file system. Using the virtual file system
76+
will supersede the sparse-checkout settings which will be ignored.
77+
See the "virtual file system" section of linkgit:githooks[6].
78+
7179
core.trustctime::
7280
If false, the ctime differences between the index and the
7381
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
@@ -492,6 +492,26 @@ This hook is invoked by `git-p4 submit`. It takes no parameters and nothing
492492
from standard input. Exiting with non-zero status from this script prevent
493493
`git-p4 submit` from launching. Run `git-p4 submit --help` for details.
494494

495+
virtualFilesystem
496+
~~~~~~~~~~~~~~~~~~
497+
498+
"Virtual File System" allows populating the working directory sparsely.
499+
The projection data is typically automatically generated by an external
500+
process. Git will limit what files it checks for changes as well as which
501+
directories are checked for untracked files based on the path names given.
502+
Git will also only update those files listed in the projection.
503+
504+
The hook is invoked when the configuration option core.virtualFilesystem
505+
is set. It takes one argument, a version (currently 1).
506+
507+
The hook should output to stdout the list of all files in the working
508+
directory that git should track. The paths are relative to the root
509+
of the working directory and are separated by a single NUL. Full paths
510+
('dir1/a.txt') as well as directories are supported (ie 'dir1/').
511+
512+
The exit status determines whether git will use the data from the
513+
hook. On error, git will abort the command with an error message.
514+
495515
GIT
496516
---
497517
Part of the linkgit:git[1] suite

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ LIB_OBJS += utf8.o
10161016
LIB_OBJS += varint.o
10171017
LIB_OBJS += version.o
10181018
LIB_OBJS += versioncmp.o
1019+
LIB_OBJS += virtualfilesystem.o
10191020
LIB_OBJS += walker.o
10201021
LIB_OBJS += wildmatch.o
10211022
LIB_OBJS += worktree.o

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,7 @@ extern char *git_replace_ref_base;
886886
extern int fsync_object_files;
887887
extern int core_preload_index;
888888
extern int core_apply_sparse_checkout;
889+
extern const char *core_virtualfilesystem;
889890
extern int core_gvfs;
890891
extern int precomposed_unicode;
891892
extern int protect_hfs;

config.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1331,7 +1331,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
13311331
}
13321332

13331333
if (!strcmp(var, "core.sparsecheckout")) {
1334-
core_apply_sparse_checkout = git_config_bool(var, value);
1334+
/* virtual file system relies on the sparse checkout logic so force it on */
1335+
if (core_virtualfilesystem)
1336+
core_apply_sparse_checkout = 1;
1337+
else
1338+
core_apply_sparse_checkout = git_config_bool(var, value);
13351339
return 0;
13361340
}
13371341

@@ -2312,6 +2316,23 @@ int git_config_get_fsmonitor(void)
23122316
return 0;
23132317
}
23142318

2319+
int git_config_get_virtualfilesystem(void)
2320+
{
2321+
if (git_config_get_pathname("core.virtualfilesystem", &core_virtualfilesystem))
2322+
core_virtualfilesystem = getenv("GIT_VIRTUALFILESYSTEM_TEST");
2323+
2324+
if (core_virtualfilesystem && !*core_virtualfilesystem)
2325+
core_virtualfilesystem = NULL;
2326+
2327+
/* virtual file system relies on the sparse checkout logic so force it on */
2328+
if (core_virtualfilesystem) {
2329+
core_apply_sparse_checkout = 1;
2330+
return 1;
2331+
}
2332+
2333+
return 0;
2334+
}
2335+
23152336
int git_config_get_index_threads(int *dest)
23162337
{
23172338
int is_bool, val;

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ extern int git_config_get_untracked_cache(void);
251251
extern int git_config_get_split_index(void);
252252
extern int git_config_get_max_percent_split_change(void);
253253
extern int git_config_get_fsmonitor(void);
254+
extern int git_config_get_virtualfilesystem(void);
254255

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

dir.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "ewah/ewok.h"
2222
#include "fsmonitor.h"
2323
#include "submodule-config.h"
24+
#include "virtualfilesystem.h"
2425

2526
/*
2627
* Tells read_directory_recursive how a file or directory should be treated.
@@ -1159,6 +1160,18 @@ int is_excluded_from_list(const char *pathname,
11591160
struct exclude_list *el, struct index_state *istate)
11601161
{
11611162
struct exclude *exclude;
1163+
1164+
/*
1165+
* The virtual file system data is used to prevent git from traversing
1166+
* any part of the tree that is not in the virtual file system. Return
1167+
* 1 to exclude the entry if it is not found in the virtual file system,
1168+
* else fall through to the regular excludes logic as it may further exclude.
1169+
*/
1170+
if (*dtype == DT_UNKNOWN)
1171+
*dtype = get_dtype(NULL, istate, pathname, pathlen);
1172+
if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0)
1173+
return 1;
1174+
11621175
exclude = last_exclude_matching_from_list(pathname, pathlen, basename,
11631176
dtype, el, istate);
11641177
if (exclude)
@@ -1374,8 +1387,20 @@ struct exclude *last_exclude_matching(struct dir_struct *dir,
13741387
int is_excluded(struct dir_struct *dir, struct index_state *istate,
13751388
const char *pathname, int *dtype_p)
13761389
{
1377-
struct exclude *exclude =
1378-
last_exclude_matching(dir, istate, pathname, dtype_p);
1390+
struct exclude *exclude;
1391+
1392+
/*
1393+
* The virtual file system data is used to prevent git from traversing
1394+
* any part of the tree that is not in the virtual file system. Return
1395+
* 1 to exclude the entry if it is not found in the virtual file system,
1396+
* else fall through to the regular excludes logic as it may further exclude.
1397+
*/
1398+
if (*dtype_p == DT_UNKNOWN)
1399+
*dtype_p = get_dtype(NULL, istate, pathname, strlen(pathname));
1400+
if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0)
1401+
return 1;
1402+
1403+
exclude = last_exclude_matching(dir, istate, pathname, dtype_p);
13791404
if (exclude)
13801405
return exclude->flags & EXC_FLAG_NEGATIVE ? 0 : 1;
13811406
return 0;
@@ -1728,6 +1753,9 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
17281753
if (dtype != DT_DIR && has_path_in_index)
17291754
return path_none;
17301755

1756+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0)
1757+
return path_excluded;
1758+
17311759
/*
17321760
* When we are looking at a directory P in the working tree,
17331761
* there are three cases:
@@ -2068,6 +2096,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
20682096
/* add the path to the appropriate result list */
20692097
switch (state) {
20702098
case path_excluded:
2099+
if (is_excluded_from_virtualfilesystem(path.buf, path.len, DT_DIR) > 0)
2100+
break;
20712101
if (dir->flags & DIR_SHOW_IGNORED)
20722102
dir_add_name(dir, istate, path.buf, path.len);
20732103
else if ((dir->flags & DIR_SHOW_IGNORED_TOO) ||

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ char *notes_ref_name;
7070
int grafts_replace_parents = 1;
7171
int core_apply_sparse_checkout;
7272
int core_gvfs;
73+
const char *core_virtualfilesystem;
7374
int merge_log_config = -1;
7475
int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
7576
unsigned long pack_size_limit_cfg;

read-cache.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "fsmonitor.h"
2626
#include "thread-utils.h"
2727
#include "progress.h"
28+
#include "virtualfilesystem.h"
2829
#include "gvfs.h"
2930

3031
/* Mask for the name length in ce_flags in the on-disk index */
@@ -1897,6 +1898,7 @@ static void post_read_index_from(struct index_state *istate)
18971898
tweak_untracked_cache(istate);
18981899
tweak_split_index(istate);
18991900
tweak_fsmonitor(istate);
1901+
apply_virtualfilesystem(istate);
19001902
}
19011903

19021904
static size_t estimate_cache_size_from_compressed(unsigned int entries)

0 commit comments

Comments
 (0)