From fc91983273b7d0cfd7230961cf53566968b8b818 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Wed, 1 May 2024 10:08:11 -0400 Subject: [PATCH] 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 --- Documentation/scalar.txt | 20 ++++++++++++++++++++ scalar.c | 19 ++++++++++++++++--- t/t9210-scalar.sh | 25 ++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/Documentation/scalar.txt b/Documentation/scalar.txt index 38612f4bcae6e2..dab62be71fe496 100644 --- a/Documentation/scalar.txt +++ b/Documentation/scalar.txt @@ -103,6 +103,26 @@ clone), and `~/.scalarCache` on macOS. Retrieve missing objects from the specified remote, which is expected to understand the GVFS protocol. +--[no-]gvfs-protocol:: + When cloning from a `` with either `dev.azure.com` or + `visualstudio.com` in the name, `scalar clone` will attempt to use the GVFS + Protocol to access Git objects, specifically from a cache server when + available, and will fail to clone if there is an error over that protocol. + + To enable the GVFS Protocol regardless of the origin ``, use + `--gvfs-protocol`. This will cause `scalar clone` to fail when the origin + server fails to provide a valid response to the `gvfs/config` endpoint. + + To disable the GVFS Protocol, use `--no-gvfs-protocol` and `scalar clone` + will only use the Git protocol, starting with a partial clone. This can be + helpful if your `` points to Azure Repos but the repository does not + have GVFS cache servers enabled. It is likely more efficient to use its + partial clone functionality through the Git protocol. + + Previous versions of `scalar clone` could fall back to a partial clone over + the Git protocol if there is any issue gathering GVFS configuration + information from the origin server. + List ~~~~ diff --git a/scalar.c b/scalar.c index 13cea9b9e525b6..e4a21b9b2caf73 100644 --- a/scalar.c +++ b/scalar.c @@ -686,6 +686,8 @@ static int cmd_clone(int argc, const char **argv) int src = 1; const char *cache_server_url = NULL, *local_cache_root = NULL; char *default_cache_server_url = NULL, *local_cache_root_abs = NULL; + int gvfs_protocol = -1; + struct option clone_options[] = { OPT_STRING('b', "branch", &branch, N_(""), N_("branch to checkout after clone")), @@ -696,6 +698,8 @@ static int cmd_clone(int argc, const char **argv) "be checked out")), OPT_BOOL(0, "src", &src, N_("create repository within 'src' directory")), + OPT_BOOL(0, "gvfs-protocol", &gvfs_protocol, + N_("force enable (or disable) the GVFS Protocol")), OPT_STRING(0, "cache-server-url", &cache_server_url, N_(""), N_("the url or friendly name of the cache server")), @@ -715,7 +719,6 @@ static int cmd_clone(int argc, const char **argv) char *enlistment = NULL, *dir = NULL; struct strbuf buf = STRBUF_INIT; int res; - int gvfs_protocol; argc = parse_options(argc, argv, NULL, clone_options, clone_usage, 0); @@ -823,8 +826,18 @@ static int cmd_clone(int argc, const char **argv) goto cleanup; } - gvfs_protocol = cache_server_url || - supports_gvfs_protocol(url, &default_cache_server_url); + /* Is --[no-]gvfs-protocol unspecified? Infer from url. */ + if (gvfs_protocol < 0) { + if (cache_server_url || + strstr(url, "dev.azure.com") || + strstr(url, "visualstudio.com")) + gvfs_protocol = 1; + else + gvfs_protocol = 0; + } + + if (gvfs_protocol && !supports_gvfs_protocol(url, &default_cache_server_url)) + die(_("failed to contact server via GVFS Protocol")); if (gvfs_protocol) { if ((res = init_shared_object_cache(url, local_cache_root))) diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index b14221a061dd26..43e20bbdbe8b87 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -349,7 +349,12 @@ test_expect_success '`scalar clone` with GVFS-enabled server' ' # We must set credential.interactive=true to bypass a setting # in "scalar clone" that disables interactive credentials during # an unattended command. - scalar -c credential.interactive=true clone --single-branch -- http://$HOST_PORT/ using-gvfs && + GIT_TRACE2_EVENT="$(pwd)/clone-trace-with-gvfs" scalar \ + -c credential.interactive=true \ + clone --gvfs-protocol \ + --single-branch -- http://$HOST_PORT/ using-gvfs && + + grep "GET/config(main)"