Skip to content

Commit 78e46b2

Browse files
dschojeffhostetler
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 025dfe9 + 2332bf3 commit 78e46b2

16 files changed

+864
-6
lines changed

Documentation/config/core.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ Note: if this config setting is set to `true`, any FSMonitor hook
106106
configured via `core.fsmonitor` (and possibly `core.fsmonitorHookVersion`)
107107
is ignored.
108108

109+
core.virtualFilesystem::
110+
If set, the value of this variable is used as a command which
111+
will identify all files and directories that are present in
112+
the working directory. Git will only track and update files
113+
listed in the virtual file system. Using the virtual file system
114+
will supersede the sparse-checkout settings which will be ignored.
115+
See the "virtual file system" section of linkgit:githooks[5].
116+
109117
core.trustctime::
110118
If false, the ctime differences between the index and the
111119
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
@@ -690,6 +690,26 @@ and "0" meaning they were not.
690690
Only one parameter should be set to "1" when the hook runs. The hook
691691
running passing "1", "1" should not be possible.
692692

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

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,7 @@ LIB_OBJS += utf8.o
10381038
LIB_OBJS += varint.o
10391039
LIB_OBJS += version.o
10401040
LIB_OBJS += versioncmp.o
1041+
LIB_OBJS += virtualfilesystem.o
10411042
LIB_OBJS += walker.o
10421043
LIB_OBJS += wildmatch.o
10431044
LIB_OBJS += worktree.o

cache.h

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

958958
extern int fsync_object_files;
959959
extern int core_preload_index;
960+
extern const char *core_virtualfilesystem;
960961
extern int core_gvfs;
961962
extern int precomposed_unicode;
962963
extern int protect_hfs;

config.c

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

15511551
if (!strcmp(var, "core.sparsecheckout")) {
1552-
core_apply_sparse_checkout = git_config_bool(var, value);
1552+
/* virtual file system relies on the sparse checkout logic so force it on */
1553+
if (core_virtualfilesystem)
1554+
core_apply_sparse_checkout = 1;
1555+
else
1556+
core_apply_sparse_checkout = git_config_bool(var, value);
15531557
return 0;
15541558
}
15551559

@@ -2545,6 +2549,37 @@ int repo_config_get_fsmonitor(struct repository *r)
25452549
return 0;
25462550
}
25472551

2552+
int git_config_get_virtualfilesystem(void)
2553+
{
2554+
if (git_config_get_pathname("core.virtualfilesystem", &core_virtualfilesystem))
2555+
core_virtualfilesystem = getenv("GIT_VIRTUALFILESYSTEM_TEST");
2556+
2557+
if (core_virtualfilesystem && !*core_virtualfilesystem)
2558+
core_virtualfilesystem = NULL;
2559+
2560+
if (core_virtualfilesystem) {
2561+
/*
2562+
* Some git commands spawn helpers and redirect the index to a different
2563+
* location. These include "difftool -d" and the sequencer
2564+
* (i.e. `git rebase -i`, `git cherry-pick` and `git revert`) and others.
2565+
* In those instances we don't want to update their temporary index with
2566+
* our virtualization data.
2567+
*/
2568+
char *default_index_file = xstrfmt("%s/%s", the_repository->gitdir, "index");
2569+
int should_run_hook = !strcmp(default_index_file, the_repository->index_file);
2570+
2571+
free(default_index_file);
2572+
if (should_run_hook) {
2573+
/* virtual file system relies on the sparse checkout logic so force it on */
2574+
core_apply_sparse_checkout = 1;
2575+
return 1;
2576+
}
2577+
core_virtualfilesystem = NULL;
2578+
}
2579+
2580+
return 0;
2581+
}
2582+
25482583
int git_config_get_index_threads(int *dest)
25492584
{
25502585
int is_bool, val;

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ int git_config_get_untracked_cache(void);
608608
int git_config_get_split_index(void);
609609
int git_config_get_max_percent_split_change(void);
610610
int repo_config_get_fsmonitor(struct repository *r);
611+
int git_config_get_virtualfilesystem(void);
611612

612613
/* This dies if the configured or default date is in the future */
613614
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"
@@ -1402,6 +1403,17 @@ enum pattern_match_result path_matches_pattern_list(
14021403
int result = NOT_MATCHED;
14031404
const char *slash_pos;
14041405

1406+
/*
1407+
* The virtual file system data is used to prevent git from traversing
1408+
* any part of the tree that is not in the virtual file system. Return
1409+
* 1 to exclude the entry if it is not found in the virtual file system,
1410+
* else fall through to the regular excludes logic as it may further exclude.
1411+
*/
1412+
if (*dtype == DT_UNKNOWN)
1413+
*dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen);
1414+
if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0)
1415+
return 1;
1416+
14051417
if (!pl->use_cone_patterns) {
14061418
pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
14071419
dtype, pl, istate);
@@ -1660,8 +1672,20 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir,
16601672
int is_excluded(struct dir_struct *dir, struct index_state *istate,
16611673
const char *pathname, int *dtype_p)
16621674
{
1663-
struct path_pattern *pattern =
1664-
last_matching_pattern(dir, istate, pathname, dtype_p);
1675+
struct path_pattern *pattern;
1676+
1677+
/*
1678+
* The virtual file system data is used to prevent git from traversing
1679+
* any part of the tree that is not in the virtual file system. Return
1680+
* 1 to exclude the entry if it is not found in the virtual file system,
1681+
* else fall through to the regular excludes logic as it may further exclude.
1682+
*/
1683+
if (*dtype_p == DT_UNKNOWN)
1684+
*dtype_p = resolve_dtype(DT_UNKNOWN, istate, pathname, strlen(pathname));
1685+
if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0)
1686+
return 1;
1687+
1688+
pattern = last_matching_pattern(dir, istate, pathname, dtype_p);
16651689
if (pattern)
16661690
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;
16671691
return 0;
@@ -2211,6 +2235,8 @@ static enum path_treatment treat_path(struct dir_struct *dir,
22112235
ignore_case);
22122236
if (dtype != DT_DIR && has_path_in_index)
22132237
return path_none;
2238+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0)
2239+
return path_excluded;
22142240

22152241
/*
22162242
* When we are looking at a directory P in the working tree,
@@ -2415,6 +2441,8 @@ static void add_path_to_appropriate_result_list(struct dir_struct *dir,
24152441
/* add the path to the appropriate result list */
24162442
switch (state) {
24172443
case path_excluded:
2444+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, DT_DIR) > 0)
2445+
break;
24182446
if (dir->flags & DIR_SHOW_IGNORED)
24192447
dir_add_name(dir, istate, path->buf, path->len);
24202448
else if ((dir->flags & DIR_SHOW_IGNORED_TOO) ||

environment.c

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

read-cache.c

Lines changed: 2 additions & 1 deletion
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"
@@ -26,7 +27,6 @@
2627
#include "fsmonitor.h"
2728
#include "thread-utils.h"
2829
#include "progress.h"
29-
#include "gvfs.h"
3030

3131
/* Mask for the name length in ce_flags in the on-disk index */
3232

@@ -1938,6 +1938,7 @@ static void post_read_index_from(struct index_state *istate)
19381938
tweak_untracked_cache(istate);
19391939
tweak_split_index(istate);
19401940
tweak_fsmonitor(istate);
1941+
apply_virtualfilesystem(istate);
19411942
}
19421943

19431944
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
@@ -1418,6 +1418,17 @@ int run_hook_strvec(const char *const *env, const char *name,
14181418
const char *p;
14191419

14201420
p = find_hook(name);
1421+
/*
1422+
* Backwards compatibility hack in VFS for Git: when originally
1423+
* introduced (and used!), it was called `post-indexchanged`, but this
1424+
* name was changed during the review on the Git mailing list.
1425+
*
1426+
* Therefore, when the `post-index-change` hook is not found, let's
1427+
* look for a hook with the old name (which would be found in case of
1428+
* already-existing checkouts).
1429+
*/
1430+
if (!p && !strcmp(name, "post-index-change"))
1431+
p = find_hook("post-indexchanged");
14211432
if (!p)
14221433
return 0;
14231434

0 commit comments

Comments
 (0)