Skip to content

Commit 92b7c0d

Browse files
committed
Merge advanced VFS-specific features
Most of these were done in private before microsoft/git. However, the following pull requests modified the core feature: msysgit#85 msysgit#89 msysgit#91 msysgit#98 msysgit#243 msysgit#263 Signed-off-by: Derrick Stolee <[email protected]>
2 parents 630ba67 + 58bc048 commit 92b7c0d

19 files changed

+507
-41
lines changed

BRANCHES.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
Branches used in this repo
2+
==========================
3+
4+
The document explains the branching structure that we are using in the VFSForGit repository as well as the forking strategy that we have adopted for contributing.
5+
6+
Repo Branches
7+
-------------
8+
9+
1. `vfs-#`
10+
11+
These branches are used to track the specific version that match Git for Windows with the VFSForGit specific patches on top. When a new version of Git for Windows is released, the VFSForGit patches will be rebased on that windows version and a new gvfs-# branch created to create pull requests against.
12+
13+
#### Examples
14+
15+
```
16+
vfs-2.27.0
17+
vfs-2.30.0
18+
```
19+
20+
The versions of git for VFSForGit are based on the Git for Windows versions. v2.20.0.vfs.1 will correspond with the v2.20.0.windows.1 with the VFSForGit specific patches applied to the windows version.
21+
22+
2. `vfs-#-exp`
23+
24+
These branches are for releasing experimental features to early adopters. They
25+
should contain everything within the corresponding `vfs-#` branch; if the base
26+
branch updates, then merge into the `vfs-#-exp` branch as well.
27+
28+
Tags
29+
----
30+
31+
We are using annotated tags to build the version number for git. The build will look back through the commit history to find the first tag matching `v[0-9]*vfs*` and build the git version number using that tag.
32+
33+
Full releases are of the form `v2.XX.Y.vfs.Z.W` where `v2.XX.Y` comes from the
34+
upstream version and `Z.W` are custom updates within our fork. Specifically,
35+
the `.Z` value represents the "compatibility level" with VFS for Git. Only
36+
increase this version when making a breaking change with a released version
37+
of VFS for Git. The `.W` version is used for minor updates between major
38+
versions.
39+
40+
Experimental releases are of the form `v2.XX.Y.vfs.Z.W.exp`. The `.exp`
41+
suffix indicates that experimental features are available. The rest of the
42+
version string comes from the full release tag. These versions will only
43+
be made available as pre-releases on the releases page, never a full release.
44+
45+
Forking
46+
-------
47+
48+
A personal fork of this repository and a branch in that repository should be used for development.
49+
50+
These branches should be based on the latest vfs-# branch. If there are work in progress pull requests that you have based on a previous version branch when a new version branch is created, you will need to move your patches to the new branch to get them in that latest version.
51+
52+
#### Example
53+
54+
```
55+
git clone <personal fork repo URL>
56+
git remote add ms https://github.com/Microsoft/git.git
57+
git checkout -b my-changes ms/vfs-2.20.0 --no-track
58+
git push -fu origin HEAD
59+
```

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,7 @@ LIB_OBJS += gettext.o
10401040
LIB_OBJS += gpg-interface.o
10411041
LIB_OBJS += graph.o
10421042
LIB_OBJS += grep.o
1043+
LIB_OBJS += gvfs.o
10431044
LIB_OBJS += hash-lookup.o
10441045
LIB_OBJS += hashmap.o
10451046
LIB_OBJS += help.o

apply.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3363,6 +3363,24 @@ static int checkout_target(struct index_state *istate,
33633363
{
33643364
struct checkout costate = CHECKOUT_INIT;
33653365

3366+
/*
3367+
* Do not checkout the entry if the skipworktree bit is set
3368+
*
3369+
* Both callers of this method (check_preimage and load_current)
3370+
* check for the existance of the file before calling this
3371+
* method so we know that the file doesn't exist at this point
3372+
* and we don't need to perform that check again here.
3373+
* We just need to check the skip-worktree and return.
3374+
*
3375+
* This is to prevent git from creating a file in the
3376+
* working directory that has the skip-worktree bit on,
3377+
* then updating the index from the patch and not keeping
3378+
* the working directory version up to date with what it
3379+
* changed the index version to be.
3380+
*/
3381+
if (ce_skip_worktree(ce))
3382+
return 0;
3383+
33663384
costate.refresh_cache = 1;
33673385
costate.istate = istate;
33683386
if (checkout_entry(ce, &costate, NULL, NULL) ||

builtin/gc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "builtin.h"
1414
#include "repository.h"
15+
#include "gvfs.h"
1516
#include "config.h"
1617
#include "tempfile.h"
1718
#include "lockfile.h"
@@ -616,6 +617,9 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
616617
if (quiet)
617618
strvec_push(&repack, "-q");
618619

620+
if ((!auto_gc || (auto_gc && gc_auto_threshold > 0)) && gvfs_config_is_set(GVFS_BLOCK_COMMANDS))
621+
die(_("'git gc' is not supported on a GVFS repo"));
622+
619623
if (auto_gc) {
620624
/*
621625
* Auto-gc should be least intrusive as possible.

builtin/update-index.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
#define USE_THE_INDEX_VARIABLE
77
#include "cache.h"
8+
#include "gvfs.h"
89
#include "bulk-checkin.h"
910
#include "config.h"
1011
#include "lockfile.h"
@@ -1171,7 +1172,13 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
11711172
argc = parse_options_end(&ctx);
11721173

11731174
getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
1175+
if (mark_skip_worktree_only && gvfs_config_is_set(GVFS_BLOCK_COMMANDS))
1176+
die(_("modifying the skip worktree bit is not supported on a GVFS repo"));
1177+
11741178
if (preferred_index_format) {
1179+
if (preferred_index_format != 4 && gvfs_config_is_set(GVFS_BLOCK_COMMANDS))
1180+
die(_("changing the index version is not supported on a GVFS repo"));
1181+
11751182
if (preferred_index_format < INDEX_FORMAT_LB ||
11761183
INDEX_FORMAT_UB < preferred_index_format)
11771184
die("index-version %d not in range: %d..%d",
@@ -1212,6 +1219,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
12121219
end_odb_transaction();
12131220

12141221
if (split_index > 0) {
1222+
if (gvfs_config_is_set(GVFS_BLOCK_COMMANDS))
1223+
die(_("split index is not supported on a GVFS repo"));
1224+
12151225
if (git_config_get_split_index() == 0)
12161226
warning(_("core.splitIndex is set to false; "
12171227
"remove or change it, if you really want to "

builtin/worktree.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "gvfs.h"
23
#include "checkout.h"
34
#include "config.h"
45
#include "builtin.h"
@@ -1188,6 +1189,13 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
11881189

11891190
git_config(git_worktree_config, NULL);
11901191

1192+
/*
1193+
* git-worktree is special-cased to work in Scalar repositories
1194+
* even when they use the GVFS Protocol.
1195+
*/
1196+
if (core_gvfs & GVFS_USE_VIRTUAL_FILESYSTEM)
1197+
die("'git %s' is not supported on a GVFS repo", "worktree");
1198+
11911199
if (!prefix)
11921200
prefix = "";
11931201

cache-tree.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,29 @@ static int update_one(struct cache_tree *it,
423423
continue;
424424

425425
strbuf_grow(&buffer, entlen + 100);
426-
strbuf_addf(&buffer, "%o %.*s%c", mode, entlen, path + baselen, '\0');
426+
427+
switch (mode) {
428+
case 0100644:
429+
strbuf_add(&buffer, "100644 ", 7);
430+
break;
431+
case 0100664:
432+
strbuf_add(&buffer, "100664 ", 7);
433+
break;
434+
case 0100755:
435+
strbuf_add(&buffer, "100755 ", 7);
436+
break;
437+
case 0120000:
438+
strbuf_add(&buffer, "120000 ", 7);
439+
break;
440+
case 0160000:
441+
strbuf_add(&buffer, "160000 ", 7);
442+
break;
443+
default:
444+
strbuf_addf(&buffer, "%o ", mode);
445+
break;
446+
}
447+
strbuf_add(&buffer, path + baselen, entlen);
448+
strbuf_addch(&buffer, '\0');
427449
strbuf_add(&buffer, oid->hash, the_hash_algo->rawsz);
428450

429451
#if DEBUG_CACHE_TREE

git.c

Lines changed: 91 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
#include "builtin.h"
2+
#include "gvfs.h"
23
#include "config.h"
34
#include "exec-cmd.h"
45
#include "help.h"
56
#include "run-command.h"
67
#include "alias.h"
78
#include "shallow.h"
9+
#include "dir.h"
10+
#include "hook.h"
811

912
#define RUN_SETUP (1<<0)
1013
#define RUN_SETUP_GENTLY (1<<1)
@@ -16,6 +19,7 @@
1619
#define NEED_WORK_TREE (1<<3)
1720
#define DELAY_PAGER_CONFIG (1<<4)
1821
#define NO_PARSEOPT (1<<5) /* parse-options is not used */
22+
#define BLOCK_ON_GVFS_REPO (1<<6) /* command not allowed in GVFS repos */
1923

2024
struct cmd_struct {
2125
const char *cmd;
@@ -401,6 +405,68 @@ static int handle_alias(int *argcp, const char ***argv)
401405
return ret;
402406
}
403407

408+
/* Runs pre/post-command hook */
409+
static struct strvec sargv = STRVEC_INIT;
410+
static int run_post_hook = 0;
411+
static int exit_code = -1;
412+
413+
static int run_pre_command_hook(const char **argv)
414+
{
415+
char *lock;
416+
int ret = 0;
417+
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
418+
419+
/*
420+
* Ensure the global pre/post command hook is only called for
421+
* the outer command and not when git is called recursively
422+
* or spawns multiple commands (like with the alias command)
423+
*/
424+
lock = getenv("COMMAND_HOOK_LOCK");
425+
if (lock && !strcmp(lock, "true"))
426+
return 0;
427+
setenv("COMMAND_HOOK_LOCK", "true", 1);
428+
429+
/* call the hook proc */
430+
strvec_pushv(&sargv, argv);
431+
strvec_pushf(&sargv, "--git-pid=%"PRIuMAX, (uintmax_t)getpid());
432+
strvec_pushv(&opt.args, sargv.v);
433+
ret = run_hooks_opt("pre-command", &opt);
434+
435+
if (!ret)
436+
run_post_hook = 1;
437+
return ret;
438+
}
439+
440+
static int run_post_command_hook(void)
441+
{
442+
char *lock;
443+
int ret = 0;
444+
struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
445+
446+
/*
447+
* Only run post_command if pre_command succeeded in this process
448+
*/
449+
if (!run_post_hook)
450+
return 0;
451+
lock = getenv("COMMAND_HOOK_LOCK");
452+
if (!lock || strcmp(lock, "true"))
453+
return 0;
454+
455+
strvec_pushv(&opt.args, sargv.v);
456+
strvec_pushf(&opt.args, "--exit_code=%u", exit_code);
457+
ret = run_hooks_opt("post-command", &opt);
458+
459+
run_post_hook = 0;
460+
strvec_clear(&sargv);
461+
setenv("COMMAND_HOOK_LOCK", "false", 1);
462+
return ret;
463+
}
464+
465+
static void post_command_hook_atexit(void)
466+
{
467+
run_post_command_hook();
468+
}
469+
404470
static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
405471
{
406472
int status, help;
@@ -436,18 +502,26 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
436502
if (!help && p->option & NEED_WORK_TREE)
437503
setup_work_tree();
438504

505+
if (!help && p->option & BLOCK_ON_GVFS_REPO && gvfs_config_is_set(GVFS_BLOCK_COMMANDS))
506+
die("'git %s' is not supported on a GVFS repo", p->cmd);
507+
508+
if (run_pre_command_hook(argv))
509+
die("pre-command hook aborted command");
510+
439511
trace_argv_printf(argv, "trace: built-in: git");
440512
trace2_cmd_name(p->cmd);
441513
trace2_cmd_list_config();
442514
trace2_cmd_list_env_vars();
443515

444516
validate_cache_entries(the_repository->index);
445-
status = p->fn(argc, argv, prefix);
517+
exit_code = status = p->fn(argc, argv, prefix);
446518
validate_cache_entries(the_repository->index);
447519

448520
if (status)
449521
return status;
450522

523+
run_post_command_hook();
524+
451525
/* Somebody closed stdout? */
452526
if (fstat(fileno(stdout), &st))
453527
return 0;
@@ -515,7 +589,7 @@ static struct cmd_struct commands[] = {
515589
{ "for-each-ref", cmd_for_each_ref, RUN_SETUP },
516590
{ "for-each-repo", cmd_for_each_repo, RUN_SETUP_GENTLY },
517591
{ "format-patch", cmd_format_patch, RUN_SETUP },
518-
{ "fsck", cmd_fsck, RUN_SETUP },
592+
{ "fsck", cmd_fsck, RUN_SETUP | BLOCK_ON_GVFS_REPO},
519593
{ "fsck-objects", cmd_fsck, RUN_SETUP },
520594
{ "fsmonitor--daemon", cmd_fsmonitor__daemon, RUN_SETUP },
521595
{ "gc", cmd_gc, RUN_SETUP },
@@ -556,7 +630,7 @@ static struct cmd_struct commands[] = {
556630
{ "pack-refs", cmd_pack_refs, RUN_SETUP },
557631
{ "patch-id", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT },
558632
{ "pickaxe", cmd_blame, RUN_SETUP },
559-
{ "prune", cmd_prune, RUN_SETUP },
633+
{ "prune", cmd_prune, RUN_SETUP | BLOCK_ON_GVFS_REPO},
560634
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
561635
{ "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
562636
{ "push", cmd_push, RUN_SETUP },
@@ -568,7 +642,7 @@ static struct cmd_struct commands[] = {
568642
{ "remote", cmd_remote, RUN_SETUP },
569643
{ "remote-ext", cmd_remote_ext, NO_PARSEOPT },
570644
{ "remote-fd", cmd_remote_fd, NO_PARSEOPT },
571-
{ "repack", cmd_repack, RUN_SETUP },
645+
{ "repack", cmd_repack, RUN_SETUP | BLOCK_ON_GVFS_REPO },
572646
{ "replace", cmd_replace, RUN_SETUP },
573647
{ "rerere", cmd_rerere, RUN_SETUP },
574648
{ "reset", cmd_reset, RUN_SETUP },
@@ -588,7 +662,7 @@ static struct cmd_struct commands[] = {
588662
{ "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE },
589663
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
590664
{ "stripspace", cmd_stripspace },
591-
{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
665+
{ "submodule--helper", cmd_submodule__helper, RUN_SETUP | BLOCK_ON_GVFS_REPO },
592666
{ "switch", cmd_switch, RUN_SETUP | NEED_WORK_TREE },
593667
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
594668
{ "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
@@ -724,13 +798,16 @@ static void execv_dashed_external(const char **argv)
724798
*/
725799
trace_argv_printf(cmd.args.v, "trace: exec:");
726800

801+
if (run_pre_command_hook(cmd.args.v))
802+
die("pre-command hook aborted command");
803+
727804
/*
728805
* If we fail because the command is not found, it is
729806
* OK to return. Otherwise, we just pass along the status code,
730807
* or our usual generic code if we were not even able to exec
731808
* the program.
732809
*/
733-
status = run_command(&cmd);
810+
exit_code = status = run_command(&cmd);
734811

735812
/*
736813
* If the child process ran and we are now going to exit, emit a
@@ -741,6 +818,8 @@ static void execv_dashed_external(const char **argv)
741818
exit(status);
742819
else if (errno != ENOENT)
743820
exit(128);
821+
822+
run_post_command_hook();
744823
}
745824

746825
static int run_argv(int *argcp, const char ***argv)
@@ -848,6 +927,7 @@ int cmd_main(int argc, const char **argv)
848927
}
849928

850929
trace_command_performance(argv);
930+
atexit(post_command_hook_atexit);
851931

852932
/*
853933
* "git-xxxx" is the same as "git xxxx", but we obviously:
@@ -873,10 +953,14 @@ int cmd_main(int argc, const char **argv)
873953
if (!argc) {
874954
/* The user didn't specify a command; give them help */
875955
commit_pager_choice();
956+
if (run_pre_command_hook(argv))
957+
die("pre-command hook aborted command");
876958
printf(_("usage: %s\n\n"), git_usage_string);
877959
list_common_cmds_help();
878960
printf("\n%s\n", _(git_more_info_string));
879-
exit(1);
961+
exit_code = 1;
962+
run_post_command_hook();
963+
exit(exit_code);
880964
}
881965

882966
if (!strcmp("--version", argv[0]) || !strcmp("-v", argv[0]))

0 commit comments

Comments
 (0)