Skip to content

Commit 26a1353

Browse files
derrickstoleedscho
authored andcommitted
scalar: make GVFS Protocol a forced choice
In the Office monorepo, we've recently had an uptick in issues with `scalar clone`. These issues didn't make sense at first and seemed like the users weren't using `microsoft/git` but instead the upstream version's `scalar clone`. Instead of using GVFS cache servers, they were attempting to use the Git protocol's partial clone (which times out). It turns out that what's actually happening is that some network issue is causing the connection with Azure DevOps to error out during the `/gvfs/config` request. In the Git traces, we see the following error during this request: (curl:56) Failure when receiving data from the peer [transient] This isn't 100% of the time, but has increased enough to cause problems for a variety of users. The solution being proposed in this pull request is to remove the fall-back mechanism and instead have an explicit choice to use the GVFS protocol. To avoid significant disruption to Azure DevOps customers (the vast majority of `microsoft/git` users who use `scalar clone` based on my understanding), I added some inferring of a default value from the clone URL. This fallback mechanism was first implemented in the C# version of Scalar in microsoft/scalar#339. This was an attempt to make the Scalar client interesting to non-Azure DevOps customers, especially as GitHub was about to launch the availability of partial clones. Now that the `scalar` client is available upstream, users don't need the GVFS-enabled version to get these benefits. In addition, this will resolve #384 since those requests won't happen against non-ADO URLs unless requested. Signed-off-by: Derrick Stolee <stolee@gmail.com>
1 parent a077b6f commit 26a1353

3 files changed

Lines changed: 61 additions & 4 deletions

File tree

‎Documentation/scalar.adoc‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,27 @@ clone), and `~/.scalarCache` on macOS.
121121
Retrieve missing objects from the specified remote, which is expected to
122122
understand the GVFS protocol.
123123

124+
--gvfs-protocol::
125+
--no-gvfs-protocol::
126+
When cloning from a `<url>` with either `dev.azure.com` or
127+
`visualstudio.com` in the name, `scalar clone` will attempt to use the GVFS
128+
Protocol to access Git objects, specifically from a cache server when
129+
available, and will fail to clone if there is an error over that protocol.
130+
131+
To enable the GVFS Protocol regardless of the origin `<url>`, use
132+
`--gvfs-protocol`. This will cause `scalar clone` to fail when the origin
133+
server fails to provide a valid response to the `gvfs/config` endpoint.
134+
135+
To disable the GVFS Protocol, use `--no-gvfs-protocol` and `scalar clone`
136+
will only use the Git protocol, starting with a partial clone. This can be
137+
helpful if your `<url>` points to Azure Repos but the repository does not
138+
have GVFS cache servers enabled. It is likely more efficient to use its
139+
partial clone functionality through the Git protocol.
140+
141+
Previous versions of `scalar clone` could fall back to a partial clone over
142+
the Git protocol if there is any issue gathering GVFS configuration
143+
information from the origin server.
144+
124145
List
125146
~~~~
126147

‎scalar.c‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,8 @@ static int cmd_clone(int argc, const char **argv)
730730
int src = 1, tags = 1, maintenance = 1;
731731
const char *cache_server_url = NULL, *local_cache_root = NULL;
732732
char *default_cache_server_url = NULL, *local_cache_root_abs = NULL;
733+
int gvfs_protocol = -1;
734+
733735
struct option clone_options[] = {
734736
OPT_STRING('b', "branch", &branch, N_("<branch>"),
735737
N_("branch to checkout after clone")),
@@ -744,6 +746,8 @@ static int cmd_clone(int argc, const char **argv)
744746
N_("specify if tags should be fetched during clone")),
745747
OPT_BOOL(0, "maintenance", &maintenance,
746748
N_("specify if background maintenance should be enabled")),
749+
OPT_BOOL(0, "gvfs-protocol", &gvfs_protocol,
750+
N_("force enable (or disable) the GVFS Protocol")),
747751
OPT_STRING(0, "cache-server-url", &cache_server_url,
748752
N_("<url>"),
749753
N_("the url or friendly name of the cache server")),
@@ -763,7 +767,6 @@ static int cmd_clone(int argc, const char **argv)
763767
char *enlistment = NULL, *dir = NULL;
764768
struct strbuf buf = STRBUF_INIT;
765769
int res;
766-
int gvfs_protocol;
767770

768771
argc = parse_options(argc, argv, NULL, clone_options, clone_usage, 0);
769772

@@ -876,8 +879,18 @@ static int cmd_clone(int argc, const char **argv)
876879
goto cleanup;
877880
}
878881

879-
gvfs_protocol = cache_server_url ||
880-
supports_gvfs_protocol(url, &default_cache_server_url);
882+
/* Is --[no-]gvfs-protocol unspecified? Infer from url. */
883+
if (gvfs_protocol < 0) {
884+
if (cache_server_url ||
885+
strstr(url, "dev.azure.com") ||
886+
strstr(url, "visualstudio.com"))
887+
gvfs_protocol = 1;
888+
else
889+
gvfs_protocol = 0;
890+
}
891+
892+
if (gvfs_protocol && !supports_gvfs_protocol(url, &default_cache_server_url))
893+
die(_("failed to contact server via GVFS Protocol"));
881894

882895
if (gvfs_protocol) {
883896
if ((res = init_shared_object_cache(url, local_cache_root)))

‎t/t9210-scalar.sh‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,12 @@ test_expect_success '`scalar clone` with GVFS-enabled server' '
400400
# We must set credential.interactive=true to bypass a setting
401401
# in "scalar clone" that disables interactive credentials during
402402
# an unattended command.
403-
scalar -c credential.interactive=true clone --single-branch -- http://$HOST_PORT/ using-gvfs &&
403+
GIT_TRACE2_EVENT="$(pwd)/clone-trace-with-gvfs" scalar \
404+
-c credential.interactive=true \
405+
clone --gvfs-protocol \
406+
--single-branch -- http://$HOST_PORT/ using-gvfs &&
407+
408+
grep "GET/config(main)" <clone-trace-with-gvfs &&
404409
405410
: verify that the shared cache has been configured &&
406411
cache_key="url_$(printf "%s" http://$HOST_PORT/ |
@@ -422,6 +427,24 @@ test_expect_success '`scalar clone` with GVFS-enabled server' '
422427
)
423428
'
424429

430+
test_expect_success '`scalar clone --no-gvfs-protocol` skips gvfs/config' '
431+
# the fake cache server requires fake authentication &&
432+
git config --global core.askPass true &&
433+
434+
# We must set credential.interactive=true to bypass a setting
435+
# in "scalar clone" that disables interactive credentials during
436+
# an unattended command.
437+
GIT_TRACE2_EVENT="$(pwd)/clone-trace-no-gvfs" scalar \
438+
-c credential.interactive=true \
439+
clone --no-gvfs-protocol \
440+
--single-branch -- http://$HOST_PORT/ skipping-gvfs &&
441+
442+
! grep "GET/config(main)" <clone-trace-no-gvfs &&
443+
! git -C skipping-gvfs/src config core.gvfs &&
444+
445+
test_config -C skipping-gvfs/src remote.origin.partialclonefilter blob:none
446+
'
447+
425448
test_expect_success '`scalar register` parallel to worktree is unsupported' '
426449
git init test-repo/src &&
427450
mkdir -p test-repo/out &&

0 commit comments

Comments
 (0)