Skip to content

Commit 7cc6c51

Browse files
committed
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: #15 #27 #33 msysgit#70 Signed-off-by: Ben Peart <[email protected]> Signed-off-by: Derrick Stolee <[email protected]>
2 parents a4ddadb + 949907d commit 7cc6c51

16 files changed

+871
-4
lines changed

Documentation/config/core.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ and MacOS.
107107
Note: if this config setting is set to `true`, the values of
108108
`core.fsmonitor` and `core.fsmonitorHookVersion` are ignored.
109109

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

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

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,7 @@ LIB_OBJS += utf8.o
10681068
LIB_OBJS += varint.o
10691069
LIB_OBJS += version.o
10701070
LIB_OBJS += versioncmp.o
1071+
LIB_OBJS += virtualfilesystem.o
10711072
LIB_OBJS += walker.o
10721073
LIB_OBJS += wildmatch.o
10731074
LIB_OBJS += worktree.o

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,7 @@ enum fsync_object_files_mode {
10041004
extern enum fsync_object_files_mode fsync_object_files;
10051005
extern int use_fsync;
10061006
extern int core_preload_index;
1007+
extern const char *core_virtualfilesystem;
10071008
extern int core_gvfs;
10081009
extern int precomposed_unicode;
10091010
extern int protect_hfs;

config.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,11 @@ int git_default_core_config(const char *var, const char *value, void *cb)
15221522
}
15231523

15241524
if (!strcmp(var, "core.sparsecheckout")) {
1525-
core_apply_sparse_checkout = git_config_bool(var, value);
1525+
/* virtual file system relies on the sparse checkout logic so force it on */
1526+
if (core_virtualfilesystem)
1527+
core_apply_sparse_checkout = 1;
1528+
else
1529+
core_apply_sparse_checkout = git_config_bool(var, value);
15261530
return 0;
15271531
}
15281532

@@ -2524,6 +2528,44 @@ int git_config_get_max_percent_split_change(void)
25242528
return -1; /* default value */
25252529
}
25262530

2531+
int git_config_get_virtualfilesystem(void)
2532+
{
2533+
/* Run only once. */
2534+
static int virtual_filesystem_result = -1;
2535+
if (virtual_filesystem_result >= 0)
2536+
return virtual_filesystem_result;
2537+
2538+
if (git_config_get_pathname("core.virtualfilesystem", &core_virtualfilesystem))
2539+
core_virtualfilesystem = getenv("GIT_VIRTUALFILESYSTEM_TEST");
2540+
2541+
if (core_virtualfilesystem && !*core_virtualfilesystem)
2542+
core_virtualfilesystem = NULL;
2543+
2544+
if (core_virtualfilesystem) {
2545+
/*
2546+
* Some git commands spawn helpers and redirect the index to a different
2547+
* location. These include "difftool -d" and the sequencer
2548+
* (i.e. `git rebase -i`, `git cherry-pick` and `git revert`) and others.
2549+
* In those instances we don't want to update their temporary index with
2550+
* our virtualization data.
2551+
*/
2552+
char *default_index_file = xstrfmt("%s/%s", the_repository->gitdir, "index");
2553+
int should_run_hook = !strcmp(default_index_file, the_repository->index_file);
2554+
2555+
free(default_index_file);
2556+
if (should_run_hook) {
2557+
/* virtual file system relies on the sparse checkout logic so force it on */
2558+
core_apply_sparse_checkout = 1;
2559+
virtual_filesystem_result = 1;
2560+
return 1;
2561+
}
2562+
core_virtualfilesystem = NULL;
2563+
}
2564+
2565+
virtual_filesystem_result = 0;
2566+
return 0;
2567+
}
2568+
25272569
int git_config_get_index_threads(int *dest)
25282570
{
25292571
int is_bool, val;

config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ int git_config_get_pathname(const char *key, const char **dest);
611611
int git_config_get_index_threads(int *dest);
612612
int git_config_get_split_index(void);
613613
int git_config_get_max_percent_split_change(void);
614+
int git_config_get_virtualfilesystem(void);
614615

615616
/* This dies if the configured or default date is in the future */
616617
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"
@@ -1416,6 +1417,17 @@ enum pattern_match_result path_matches_pattern_list(
14161417
int result = NOT_MATCHED;
14171418
size_t slash_pos;
14181419

1420+
/*
1421+
* The virtual file system data is used to prevent git from traversing
1422+
* any part of the tree that is not in the virtual file system. Return
1423+
* 1 to exclude the entry if it is not found in the virtual file system,
1424+
* else fall through to the regular excludes logic as it may further exclude.
1425+
*/
1426+
if (*dtype == DT_UNKNOWN)
1427+
*dtype = resolve_dtype(DT_UNKNOWN, istate, pathname, pathlen);
1428+
if (is_excluded_from_virtualfilesystem(pathname, pathlen, *dtype) > 0)
1429+
return 1;
1430+
14191431
if (!pl->use_cone_patterns) {
14201432
pattern = last_matching_pattern_from_list(pathname, pathlen, basename,
14211433
dtype, pl, istate);
@@ -1758,8 +1770,20 @@ struct path_pattern *last_matching_pattern(struct dir_struct *dir,
17581770
int is_excluded(struct dir_struct *dir, struct index_state *istate,
17591771
const char *pathname, int *dtype_p)
17601772
{
1761-
struct path_pattern *pattern =
1762-
last_matching_pattern(dir, istate, pathname, dtype_p);
1773+
struct path_pattern *pattern;
1774+
1775+
/*
1776+
* The virtual file system data is used to prevent git from traversing
1777+
* any part of the tree that is not in the virtual file system. Return
1778+
* 1 to exclude the entry if it is not found in the virtual file system,
1779+
* else fall through to the regular excludes logic as it may further exclude.
1780+
*/
1781+
if (*dtype_p == DT_UNKNOWN)
1782+
*dtype_p = resolve_dtype(DT_UNKNOWN, istate, pathname, strlen(pathname));
1783+
if (is_excluded_from_virtualfilesystem(pathname, strlen(pathname), *dtype_p) > 0)
1784+
return 1;
1785+
1786+
pattern = last_matching_pattern(dir, istate, pathname, dtype_p);
17631787
if (pattern)
17641788
return pattern->flags & PATTERN_FLAG_NEGATIVE ? 0 : 1;
17651789
return 0;
@@ -2324,6 +2348,8 @@ static enum path_treatment treat_path(struct dir_struct *dir,
23242348
ignore_case);
23252349
if (dtype != DT_DIR && has_path_in_index)
23262350
return path_none;
2351+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, dtype) > 0)
2352+
return path_excluded;
23272353

23282354
/*
23292355
* When we are looking at a directory P in the working tree,
@@ -2528,6 +2554,8 @@ static void add_path_to_appropriate_result_list(struct dir_struct *dir,
25282554
/* add the path to the appropriate result list */
25292555
switch (state) {
25302556
case path_excluded:
2557+
if (is_excluded_from_virtualfilesystem(path->buf, path->len, DT_DIR) > 0)
2558+
break;
25312559
if (dir->flags & DIR_SHOW_IGNORED)
25322560
dir_add_name(dir, istate, path->buf, path->len);
25332561
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 & 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"
@@ -2026,6 +2027,7 @@ static void post_read_index_from(struct index_state *istate)
20262027
tweak_untracked_cache(istate);
20272028
tweak_split_index(istate);
20282029
tweak_fsmonitor(istate);
2030+
apply_virtualfilesystem(istate);
20292031
}
20302032

20312033
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
@@ -1314,6 +1314,17 @@ int run_hook_strvec(const char *const *env, const char *name,
13141314
const char *p;
13151315

13161316
p = find_hook(name);
1317+
/*
1318+
* Backwards compatibility hack in VFS for Git: when originally
1319+
* introduced (and used!), it was called `post-indexchanged`, but this
1320+
* name was changed during the review on the Git mailing list.
1321+
*
1322+
* Therefore, when the `post-index-change` hook is not found, let's
1323+
* look for a hook with the old name (which would be found in case of
1324+
* already-existing checkouts).
1325+
*/
1326+
if (!p && !strcmp(name, "post-index-change"))
1327+
p = find_hook("post-indexchanged");
13171328
if (!p)
13181329
return 0;
13191330

0 commit comments

Comments
 (0)