From 5ab2cbf04e61aef4d5e62ab5d4b233912c0ad525 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 23 Apr 2021 16:12:33 +0200 Subject: [PATCH] scalar: add the `cache-server` command This allows setting the GVFS-enabled cache server, or listing the one(s) associated with the remote repository. Signed-off-by: Johannes Schindelin --- Documentation/scalar.txt | 22 ++++++++++ scalar.c | 95 +++++++++++++++++++++++++++++++++++++++- t/t9210-scalar.sh | 34 ++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) diff --git a/Documentation/scalar.txt b/Documentation/scalar.txt index 155df8a5c7f437..cea68a23d5ee6d 100644 --- a/Documentation/scalar.txt +++ b/Documentation/scalar.txt @@ -18,6 +18,7 @@ scalar run ( all | config | commit-graph | fetch | loose-objects | pack-files ) scalar reconfigure [ --all | ] scalar diagnose [] scalar delete +scalar cache-server ( --get | --set | --list [] ) [] DESCRIPTION ----------- @@ -182,6 +183,27 @@ delete :: This subcommand lets you delete an existing Scalar enlistment from your local file system, unregistering the repository. +Cache-server +~~~~~~~~~~~~ + +cache-server ( --get | --set | --list [] ) []:: + This command lets you query or set the GVFS-enabled cache server used + to fetch missing objects. + +--get:: + This is the default command mode: query the currently-configured cache + server URL, if any. + +--list:: + Access the `gvfs/info` endpoint of the specified remote (default: + `origin`) to figure out which cache servers are available, if any. ++ +In contrast to the `--get` command mode (which only accesses the local +repository), this command mode triggers a request via the network that +potentially requires authentication. If authentication is required, the +configured credential helper is employed (see linkgit:git-credential[1] +for details). + SEE ALSO -------- linkgit:git-clone[1], linkgit:git-maintenance[1]. diff --git a/scalar.c b/scalar.c index 928c08e6dbe0bc..8e62bc3d5a889c 100644 --- a/scalar.c +++ b/scalar.c @@ -23,6 +23,7 @@ #include "wrapper.h" #include "trace2.h" #include "json-parser.h" +#include "remote.h" #include "path.h" static int is_unattended(void) { @@ -361,6 +362,21 @@ static int set_config(const char *fmt, ...) return res; } +static int list_cache_server_urls(struct json_iterator *it) +{ + const char *p; + char *q; + long l; + + if (it->type == JSON_STRING && + skip_iprefix(it->key.buf, ".CacheServers[", &p) && + (l = strtol(p, &q, 10)) >= 0 && p != q && + !strcasecmp(q, "].Url")) + printf("#%ld: %s\n", l, it->string_value.buf); + + return 0; +} + /* Find N for which .CacheServers[N].GlobalDefault == true */ static int get_cache_server_index(struct json_iterator *it) { @@ -430,6 +446,18 @@ static int supports_gvfs_protocol(const char *url, char **cache_server_url) JSON_ITERATOR_INIT(out.buf, get_cache_server_index, &l); struct cache_server_url_data data = { .url = NULL }; + if (!cache_server_url) { + it.fn = list_cache_server_urls; + if (iterate_json(&it) < 0) { + reset_iterator(&it); + strbuf_release(&out); + return error("JSON parse error"); + } + reset_iterator(&it); + strbuf_release(&out); + return 0; + } + if (iterate_json(&it) < 0) { reset_iterator(&it); strbuf_release(&out); @@ -450,7 +478,9 @@ static int supports_gvfs_protocol(const char *url, char **cache_server_url) return 1; } strbuf_release(&out); - return 0; /* error out quietly */ + /* error out quietly, unless we wanted to list URLs */ + return cache_server_url ? + 0 : error(_("Could not access gvfs/config endpoint")); } static char *default_cache_root(const char *root) @@ -1292,6 +1322,68 @@ static int cmd_version(int argc, const char **argv) return 0; } +static int cmd_cache_server(int argc, const char **argv) +{ + int get = 0; + const char *set = NULL, *list = NULL; + struct option options[] = { + OPT_CMDMODE(0, "get", &get, + N_("get the configured cache-server URL"), 1), + OPT_STRING(0, "set", &set, N_("URL"), + N_("configure the cache-server to use")), + OPT_STRING(0, "list", &list, N_("remote"), + N_("list the possible cache-server URLs")), + OPT_END(), + }; + const char * const usage[] = { + N_("scalar cache-server " + "[--get | --set | --list ] []"), + NULL + }; + int res = 0; + + argc = parse_options(argc, argv, NULL, options, + usage, 0); + + if (get + !!set + !!list > 1) + usage_msg_opt(_("--get/--set/--list are mutually exclusive"), + usage, options); + + setup_enlistment_directory(argc, argv, usage, options, NULL); + + if (list) { + const char *name = list, *url = list; + + if (!strchr(list, '/')) { + struct remote *remote; + + /* Look up remote */ + remote = remote_get(list); + if (!remote) { + error("no such remote: '%s'", name); + return 1; + } + if (!remote->url.nr) { + return error(_("remote '%s' has no URLs"), + name); + } + url = remote->url.v[0]; + } + res = supports_gvfs_protocol(url, NULL); + } else if (set) { + res = set_config("gvfs.cache-server=%s", set); + } else { + char *url = NULL; + + printf("Using cache server: %s\n", + git_config_get_string("gvfs.cache-server", &url) ? + "(undefined)" : url); + free(url); + } + + return !!res; +} + static struct { const char *name; int (*fn)(int, const char **); @@ -1306,6 +1398,7 @@ static struct { { "help", cmd_help }, { "version", cmd_version }, { "diagnose", cmd_diagnose }, + { "cache-server", cmd_cache_server }, { NULL, NULL}, }; diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index ca61027035bfd8..fc03773cdfcd39 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -462,4 +462,38 @@ test_expect_success '`scalar delete` with existing repo' ' test_path_is_missing existing ' +test_expect_success 'scalar cache-server basics' ' + repo=with-cache-server && + git init $repo && + scalar cache-server --get $repo >out && + cat >expect <<-EOF && + Using cache server: (undefined) + EOF + test_cmp expect out && + + scalar cache-server --set http://fake-server/url $repo && + test_cmp_config -C $repo http://fake-server/url gvfs.cache-server && + scalar delete $repo && + test_path_is_missing $repo +' + +test_expect_success 'scalar cache-server list URL' ' + repo=with-real-gvfs && + git init $repo && + git -C $repo remote add origin http://$HOST_PORT/ && + scalar cache-server --list origin $repo >out && + + cat >expect <<-EOF && + #0: http://$HOST_PORT/servertype/cache + EOF + + test_cmp expect out && + + test_must_fail scalar -C $repo cache-server --list 2>err && + grep "requires a value" err && + + scalar delete $repo && + test_path_is_missing $repo +' + test_done