Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion Documentation/scalar.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]
[--[no-]src] [--[no-]tags] [--[no-]maintenance]
[--[no-]src] [--[no-]tags] [--[no-]maintenance] [--[no-]prefetch]
[--cache-server-url <url>] [--[verb]-cache-server-url <url>]
[--local-cache-path <path>] <url> [<enlistment>]
scalar list
Expand Down Expand Up @@ -110,6 +110,20 @@ cloning. If the HEAD at the remote did not point at any branch when
background maintenance feature. Use the `--no-maintenance` to skip
this configuration.

--prefetch::
--no-prefetch::
By default, when cloning with the GVFS Protocol, `scalar clone`
issues a `/gvfs/prefetch` request to hydrate the local object cache
with the commits and trees that back the checked-out branch. Use
`--no-prefetch` to skip that request during the clone so that the
initial worktree becomes ready as quickly as possible.
+
This only affects the initial fetch performed by `scalar clone`: the
prefetched data is still downloaded by the next `git fetch` (including the
background maintenance `prefetch` task), so the object cache is populated
shortly afterwards. This option has no effect when the GVFS Protocol is not
in use.

--local-cache-path <path>::
Override the path to the local cache root directory; Pre-fetched objects
are stored into a repository-dependent subdirectory of that path.
Expand Down
48 changes: 40 additions & 8 deletions scalar.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,19 @@
#include "trace2.h"
#include "path.h"
#include "json-parser.h"
#include "gvfs.h"
#include "remote.h"
#include "path.h"

/*
* The `core.gvfs` bitmask that `scalar clone` configures for enlistments
* that use the GVFS Protocol (historically the value `150`). See gvfs.h
* for the meaning of the individual bits.
*/
#define SCALAR_GVFS_MODE (GVFS_BLOCK_COMMANDS | GVFS_MISSING_OK | \
GVFS_FETCH_SKIP_REACHABILITY_AND_UPLOADPACK | \
GVFS_PREFETCH_DURING_FETCH)

static int is_unattended(void) {
return git_env_bool("Scalar_UNATTENDED", 0);
}
Expand Down Expand Up @@ -780,7 +790,7 @@ static int cmd_clone(int argc, const char **argv)
const char *branch = NULL;
char *branch_to_free = NULL;
int full_clone = 0, single_branch = 0, show_progress = isatty(2);
int src = 1, tags = 1, maintenance = 1;
int src = 1, tags = 1, maintenance = 1, prefetch = 1;
const char *cache_server_url = NULL, *local_cache_root = NULL;
char *default_cache_server_url = NULL, *local_cache_root_abs = NULL;
const char *prefetch_server = NULL, *get_server = NULL, *post_server = NULL;
Expand All @@ -801,6 +811,9 @@ static int cmd_clone(int argc, const char **argv)
N_("specify if tags should be fetched during clone")),
OPT_BOOL(0, "maintenance", &maintenance,
N_("specify if background maintenance should be enabled")),
OPT_BOOL(0, "prefetch", &prefetch,
N_("specify if commits and trees should be prefetched "
"during clone when using the GVFS Protocol")),
OPT_BOOL(0, "gvfs-protocol", &gvfs_protocol,
N_("force enable (or disable) the GVFS Protocol")),
OPT_STRING(0, "cache-server-url", &cache_server_url,
Expand All @@ -826,7 +839,8 @@ static int cmd_clone(int argc, const char **argv)
};
const char * const clone_usage[] = {
N_("scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n"
"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] [--ref-format <format>]\n"
"\t[--[no-]src] [--[no-]tags] [--[no-]maintenance] [--[no-]prefetch]\n"
"\t[--ref-format <format>]\n"
"\t[--cache-server-url <url>] [--[verb]-cache-server-url <url>]\n"
"\t[--local-cache-path <path>] <url> [<enlistment>]"),
NULL
Expand Down Expand Up @@ -977,7 +991,7 @@ static int cmd_clone(int argc, const char **argv)
if (!cache_server_url)
cache_server_url = default_cache_server_url;
if (set_config("core.useGVFSHelper=true") ||
set_config("core.gvfs=150") ||
set_config("core.gvfs=%d", SCALAR_GVFS_MODE) ||
set_config("http.%s.version=HTTP/1.1", url)) {
res = error(_("could not turn on GVFS helper"));
goto cleanup;
Expand Down Expand Up @@ -1034,11 +1048,29 @@ static int cmd_clone(int argc, const char **argv)
if (set_recommended_config(0))
return error(_("could not configure '%s'"), dir);

if ((res = run_git("fetch", "--quiet",
show_progress ? "--progress" : "--no-progress",
"origin",
(tags ? NULL : "--no-tags"),
NULL))) {
strvec_clear(&init_argv);
/*
* When cloning with the GVFS Protocol, the `core.gvfs` value set
* above enables the GVFS_PREFETCH_DURING_FETCH bit, so the `git fetch`
* below issues a `/gvfs/prefetch` request to hydrate the local object
* cache. With `--no-prefetch`, skip that request for this initial
* fetch only (by clearing that bit for this invocation) so the
* worktree becomes ready sooner. The persisted `core.gvfs` value is
* left untouched, so subsequent fetches -- including background
* maintenance -- still prefetch as usual.
*/
if (gvfs_protocol && !prefetch) {
strvec_push(&init_argv, "-c");
strvec_pushf(&init_argv, "core.gvfs=%d",
SCALAR_GVFS_MODE & ~GVFS_PREFETCH_DURING_FETCH);
}
strvec_pushl(&init_argv, "fetch", "--quiet",
show_progress ? "--progress" : "--no-progress",
"origin", NULL);
if (!tags)
strvec_push(&init_argv, "--no-tags");

if ((res = run_git_argv(&init_argv))) {
if (gvfs_protocol) {
res = error(_("failed to prefetch commits and trees"));
goto cleanup;
Expand Down
29 changes: 29 additions & 0 deletions t/t9210-scalar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,35 @@ test_expect_success '`scalar clone` with GVFS-enabled server' '
)
'

test_expect_success '`scalar clone --no-prefetch` skips the initial prefetch' '
git config --global core.askPass true &&

# A normal GVFS-enabled clone issues a "/gvfs/prefetch" request,
# which shows up in the trace as a "prefetch/since" data event.
GIT_TRACE2_EVENT="$(pwd)/with-prefetch-trace" scalar \
-c credential.interactive=true \
clone --gvfs-protocol --single-branch \
-- http://$ORIGIN_HOST_PORT/ with-prefetch &&
grep "prefetch/since" with-prefetch-trace &&

# ... but "--no-prefetch" skips that request during the clone.
GIT_TRACE2_EVENT="$(pwd)/no-prefetch-trace" scalar \
-c credential.interactive=true \
clone --no-prefetch --gvfs-protocol --single-branch \
-- http://$ORIGIN_HOST_PORT/ no-prefetch &&
! grep "prefetch/since" no-prefetch-trace &&

: the persisted core.gvfs still enables prefetch during fetch &&
echo 150 >expect &&
git -C no-prefetch/src config core.gvfs >actual &&
test_cmp expect actual &&

: and a subsequent git fetch performs the deferred prefetch &&
GIT_TRACE2_EVENT="$(pwd)/fetch-trace" \
git -C no-prefetch/src fetch origin &&
grep "prefetch/since" fetch-trace
'

test_expect_success '`scalar clone` with GVFS-enabled server; local cache path' '
: the fake cache server requires fake authentication &&
git config --global core.askPass true &&
Expand Down
Loading