Skip to content

Commit

Permalink
scalar: make GVFS Protocol a forced choice
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
derrickstolee authored and dscho committed May 14, 2024
1 parent c784114 commit 6d67155
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
20 changes: 20 additions & 0 deletions Documentation/scalar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<url>` 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 `<url>`, 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 `<url>` 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
~~~~

Expand Down
19 changes: 16 additions & 3 deletions scalar.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,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_("<branch>"),
N_("branch to checkout after clone")),
Expand All @@ -718,6 +720,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_("<url>"),
N_("the url or friendly name of the cache server")),
Expand All @@ -737,7 +741,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);

Expand Down Expand Up @@ -845,8 +848,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)))
Expand Down
25 changes: 24 additions & 1 deletion t/t9210-scalar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,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)" <clone-trace-with-gvfs &&
: verify that the shared cache has been configured &&
cache_key="url_$(printf "%s" http://$HOST_PORT/ |
Expand All @@ -374,6 +379,24 @@ test_expect_success '`scalar clone` with GVFS-enabled server' '
)
'

test_expect_success '`scalar clone --no-gvfs-protocol` skips gvfs/config' '
# the fake cache server requires fake authentication &&
git config --global core.askPass true &&
# We must set credential.interactive=true to bypass a setting
# in "scalar clone" that disables interactive credentials during
# an unattended command.
GIT_TRACE2_EVENT="$(pwd)/clone-trace-no-gvfs" scalar \
-c credential.interactive=true \
clone --no-gvfs-protocol \
--single-branch -- http://$HOST_PORT/ skipping-gvfs &&
! grep "GET/config(main)" <clone-trace-no-gvfs &&
! git config -C skipping-gvfs/src core.gvfs &&
test_config -C skipping-gvfs/src remote.origin.partialclonefilter blob:none
'

test_expect_success '`scalar register` parallel to worktree is unsupported' '
git init test-repo/src &&
mkdir -p test-repo/out &&
Expand Down

0 comments on commit 6d67155

Please sign in to comment.