Skip to content

Commit af27fd1

Browse files
dschoderrickstolee
authored andcommitted
Merge virtualfilesystem hook
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. The hook was first contributed in private, but was extended via the following pull requests: git-for-windows#15 git-for-windows#27 git-for-windows#33 git-for-windows#70 Signed-off-by: Ben Peart <[email protected]> Signed-off-by: Derrick Stolee <[email protected]>
2 parents 17a768d + 4451a05 commit af27fd1

15 files changed

+861
-4
lines changed

Documentation/config/core.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@ core.fsmonitorHookVersion::
7979
something that can be used to determine what files have changed
8080
without race conditions.
8181

82+
core.virtualFilesystem::
83+
If set, the value of this variable is used as a command which
84+
will identify all files and directories that are present in
85+
the working directory. Git will only track and update files
86+
listed in the virtual file system. Using the virtual file system
87+
will supersede the sparse-checkout settings which will be ignored.
88+
See the "virtual file system" section of linkgit:githooks[5].
89+
8290
core.trustctime::
8391
If false, the ctime differences between the index and the
8492
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
@@ -596,6 +596,26 @@ and "0" meaning they were not.
596596
Only one parameter should be set to "1" when the hook runs. The hook
597597
running passing "1", "1" should not be possible.
598598

599+
virtualFilesystem
600+
~~~~~~~~~~~~~~~~~~
601+
602+
"Virtual File System" allows populating the working directory sparsely.
603+
The projection data is typically automatically generated by an external
604+
process. Git will limit what files it checks for changes as well as which
605+
directories are checked for untracked files based on the path names given.
606+
Git will also only update those files listed in the projection.
607+
608+
The hook is invoked when the configuration option core.virtualFilesystem
609+
is set. It takes one argument, a version (currently 1).
610+
611+
The hook should output to stdout the list of all files in the working
612+
directory that git should track. The paths are relative to the root
613+
of the working directory and are separated by a single NUL. Full paths
614+
('dir1/a.txt') as well as directories are supported (ie 'dir1/').
615+
616+
The exit status determines whether git will use the data from the
617+
hook. On error, git will abort the command with an error message.
618+
599619
GIT
600620
---
601621
Part of the linkgit:git[1] suite

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,7 @@ LIB_OBJS += utf8.o
10271027
LIB_OBJS += varint.o
10281028
LIB_OBJS += version.o
10291029
LIB_OBJS += versioncmp.o
1030+
LIB_OBJS += virtualfilesystem.o
10301031
LIB_OBJS += walker.o
10311032
LIB_OBJS += wildmatch.o
10321033
LIB_OBJS += worktree.o

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,7 @@ extern char *git_replace_ref_base;
955955

956956
extern int fsync_object_files;
957957
extern int core_preload_index;
958+
extern const char *core_virtualfilesystem;
958959
extern int core_gvfs;
959960
extern int precomposed_unicode;
960961
extern int protect_hfs;

config.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,11 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
13811381
}
13821382

13831383
if (!strcmp(var, "core.sparsecheckout")) {
1384-
core_apply_sparse_checkout = git_config_bool(var, value);
1384+
/* virtual file system relies on the sparse checkout logic so force it on */
1385+
if (core_virtualfilesystem)
1386+
core_apply_sparse_checkout = 1;
1387+
else
1388+
core_apply_sparse_checkout = git_config_bool(var, value);
13851389
return 0;
13861390
}
13871391

@@ -2359,6 +2363,37 @@ int git_config_get_fsmonitor(void)
23592363
return 0;
23602364
}
23612365

2366+
int git_config_get_virtualfilesystem(void)
2367+
{
2368+
if (git_config_get_pathname("core.virtualfilesystem", &core_virtualfilesystem))
2369+
core_virtualfilesystem = getenv("GIT_VIRTUALFILESYSTEM_TEST");
2370+
2371+
if (core_virtualfilesystem && !*core_virtualfilesystem)
2372+
core_virtualfilesystem = NULL;
2373+
2374+
if (core_virtualfilesystem) {
2375+
/*
2376+
* Some git commands spawn helpers and redirect the index to a different
2377+
* location. These include "difftool -d" and the sequencer
2378+
* (i.e. `git rebase -i`, `git cherry-pick` and `git revert`) and others.
2379+
* In those instances we don't want to update their temporary index with
2380+
* our virtualization data.
2381+
*/
2382+
char *default_index_file = xstrfmt("%s/%s", the_repository->gitdir, "index");
2383+
int should_run_hook = !strcmp(default_index_file, the_repository->index_file);
2384+
2385+
free(default_index_file);
2386+
if (should_run_hook) {
2387+
/* virtual file system relies on the sparse checkout logic so force it on */
2388+
core_apply_sparse_checkout = 1;
2389+
return 1;
2390+
}
2391+
core_virtualfilesystem = NULL;
2392+
}
2393+
2394+
return 0;
2395+
}
2396+
23622397
int git_config_get_index_threads(int *dest)
23632398
{
23642399
int is_bool, val;

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ int git_config_get_untracked_cache(void);
584584
int git_config_get_split_index(void);
585585
int git_config_get_max_percent_split_change(void);
586586
int git_config_get_fsmonitor(void);
587+
int git_config_get_virtualfilesystem(void);
587588

588589
/* This dies if the configured or default date is in the future */
589590
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
@@ -18,6 +18,7 @@
1818
#include "ewah/ewok.h"
1919
#include "fsmonitor.h"
2020
#include "submodule-config.h"
21+
#include "virtualfilesystem.h"
2122

2223
/*
2324
* Tells read_directory_recursive how a file or directory should be treated.
@@ -1377,6 +1378,17 @@ enum pattern_match_result path_matches_pattern_list(
13771378
int result = NOT_MATCHED;
13781379
const char *slash_pos;
13791380

1381+
/*
1382+
* The virtual file system data is used to prevent git from traversing
1383+
* any part of the tree that is not in the virtual file system. Return
1384+
* 1 to exclude the entry if it is not found in the virtual file system,
1385+
* else fall through to the regular excludes logic as it may further exclude.
1386+
*/
1387+
if (*dtype == DT_UNKNOWN)
1388+
*dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen);
1389+
if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0)
1390+
return 1;
1391+
13801392
if (!pl->use_cone_patterns) {
13811393
pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
13821394
dtype, pl, istate);
@@ -1635,8 +1647,20 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir,
16351647
int is_excluded(struct dir_struct *dir, struct index_state *istate,
16361648
const char *pathname, int *dtype_p)
16371649
{
1638-
struct path_pattern *pattern =
1639-
last_matching_pattern(dir, istate, pathname, dtype_p);
1650+
struct path_pattern *pattern;
1651+
1652+
/*
1653+
* The virtual file system data is used to prevent git from traversing
1654+
* any part of the tree that is not in the virtual file system. Return
1655+
* 1 to exclude the entry if it is not found in the virtual file system,
1656+
* else fall through to the regular excludes logic as it may further exclude.
1657+
*/
1658+
if (*dtype_p == DT_UNKNOWN)
1659+
*dtype_p = resolve_dtype(DT_UNKNOWN, istate, pathname, strlen(pathname));
1660+
if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0)
1661+
return 1;
1662+
1663+
pattern = last_matching_pattern(dir, istate, pathname, dtype_p);
16401664
if (pattern)
16411665
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;
16421666
return 0;
@@ -2181,6 +2205,8 @@ static enum path_treatment treat_path(struct dir_struct *dir,
21812205
ignore_case);
21822206
if (dtype != DT_DIR && has_path_in_index)
21832207
return path_none;
2208+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0)
2209+
return path_excluded;
21842210

21852211
/*
21862212
* When we are looking at a directory P in the working tree,
@@ -2385,6 +2411,8 @@ static void add_path_to_appropriate_result_list(struct dir_struct *dir,
23852411
/* add the path to the appropriate result list */
23862412
switch (state) {
23872413
case path_excluded:
2414+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, DT_DIR) > 0)
2415+
break;
23882416
if (dir->flags & DIR_SHOW_IGNORED)
23892417
dir_add_name(dir, istate, path->buf, path->len);
23902418
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 @@ int grafts_replace_parents = 1;
7070
int core_apply_sparse_checkout;
7171
int core_sparse_checkout_cone;
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 */
@@ -1920,6 +1921,7 @@ static void post_read_index_from(struct index_state *istate)
19201921
tweak_untracked_cache(istate);
19211922
tweak_split_index(istate);
19221923
tweak_fsmonitor(istate);
1924+
apply_virtualfilesystem(istate);
19231925
}
19241926

19251927
static size_t estimate_cache_size_from_compressed(unsigned int entries)

run-command.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,17 @@ int run_hook_argv(const char *const *env, const char *name,
14071407
const char *p;
14081408

14091409
p = find_hook(name);
1410+
/*
1411+
* Backwards compatibility hack in VFS for Git: when originally
1412+
* introduced (and used!), it was called `post-indexchanged`, but this
1413+
* name was changed during the review on the Git mailing list.
1414+
*
1415+
* Therefore, when the `post-index-change` hook is not found, let's
1416+
* look for a hook with the old name (which would be found in case of
1417+
* already-existing checkouts).
1418+
*/
1419+
if (!p && !strcmp(name, "post-index-change"))
1420+
p = find_hook("post-indexchanged");
14101421
if (!p)
14111422
return 0;
14121423

0 commit comments

Comments
 (0)