ls-remote: pass ref prefixes when requesting a remote's refs
Construct an argv_array of ref prefixes based on the patterns supplied via the command line and pass them to 'transport_get_remote_refs()' to be used when communicating protocol v2 so that the server can limit the ref advertisement based on those prefixes. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Brandon Williams committed
Mar 15, 2018 at 10:31 UTC
b4be74105febef5c6235e1e2f1e468e76166cad8
4 files changed
+60
-2
builtin/ls-remote.c
+13
-2
@@ -2,6 +2,7 @@
2
#include "cache.h"
3
#include "transport.h"
4
#include "remote.h"
5
+#include "refs.h"
6
7
static const char * const ls_remote_usage[] = {
8
N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
@@ -43,6 +44,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
44
int show_symref_target = 0;
45
const char *uploadpack = NULL;
46
const char **pattern = NULL;
47
+ struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
48
49
struct remote *remote;
50
struct transport *transport;
@@ -74,8 +76,17 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
76
if (argc > 1) {
77
int i;
78
pattern = xcalloc(argc, sizeof(const char *));
77
- for (i = 1; i < argc; i++)
79
+ for (i = 1; i < argc; i++) {
80
+ const char *glob;
81
pattern[i - 1] = xstrfmt("*/%s", argv[i]);
82
+
83
+ glob = strchr(argv[i], '*');
84
+ if (glob)
85
+ argv_array_pushf(&ref_prefixes, "%.*s",
86
+ (int)(glob - argv[i]), argv[i]);
87
+ else
88
+ expand_ref_prefix(&ref_prefixes, argv[i]);
89
+ }
90
}
91
92
remote = remote_get(dest);
@@ -96,7 +107,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
107
if (uploadpack != NULL)
108
transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
109
99
- ref = transport_get_remote_refs(transport, NULL);
110
+ ref = transport_get_remote_refs(transport, &ref_prefixes);
111
if (transport_disconnect(transport))
112
return 1;
113
refs.c
+14
@@ -13,6 +13,7 @@
13
#include "tag.h"
14
#include "submodule.h"
15
#include "worktree.h"
16
+#include "argv-array.h"
17
18
/*
19
* List of all available backends
@@ -501,6 +502,19 @@ int refname_match(const char *abbrev_name, const char *full_name)
502
return 0;
503
}
504
505
+/*
506
+ * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
507
+ * the results to 'prefixes'
508
+ */
509
+void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
510
+{
511
+ const char **p;
512
+ int len = strlen(prefix);
513
+
514
+ for (p = ref_rev_parse_rules; *p; p++)
515
+ argv_array_pushf(prefixes, *p, len, prefix);
516
+}
517
+
518
/*
519
* *string and *len will only be substituted, and *string returned (for
520
* later free()ing) if the string passed in is a magic short-hand form
refs.h
+7
@@ -139,6 +139,13 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
139
*/
140
int refname_match(const char *abbrev_name, const char *full_name);
141
142
+/*
143
+ * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
144
+ * the results to 'prefixes'
145
+ */
146
+struct argv_array;
147
+void expand_ref_prefix(struct argv_array *prefixes, const char *prefix);
148
+
149
int expand_ref(const char *str, int len, struct object_id *oid, char **ref);
150
int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
151
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
t/t5702-protocol-v2.sh
+26
@@ -32,6 +32,19 @@ test_expect_success 'list refs with git:// using protocol v2' '
32
test_cmp actual expect
33
'
34
35
+test_expect_success 'ref advertisment is filtered with ls-remote using protocol v2' '
36
+ test_when_finished "rm -f log" &&
37
+
38
+ GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \
39
+ ls-remote "$GIT_DAEMON_URL/parent" master >actual &&
40
+
41
+ cat >expect <<-EOF &&
42
+ $(git -C "$daemon_parent" rev-parse refs/heads/master)$(printf "\t")refs/heads/master
43
+ EOF
44
+
45
+ test_cmp actual expect
46
+'
47
+
48
stop_git_daemon
49
50
# Test protocol v2 with 'file://' transport
@@ -54,4 +67,17 @@ test_expect_success 'list refs with file:// using protocol v2' '
67
test_cmp actual expect
68
'
69
70
+test_expect_success 'ref advertisment is filtered with ls-remote using protocol v2' '
71
+ test_when_finished "rm -f log" &&
72
+
73
+ GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \
74
+ ls-remote "file://$(pwd)/file_parent" master >actual &&
75
+
76
+ cat >expect <<-EOF &&
77
+ $(git -C file_parent rev-parse refs/heads/master)$(printf "\t")refs/heads/master
78
+ EOF
79
+
80
+ test_cmp actual expect
81
+'
82
+
83
test_done