Skip to content

Commit b4be741

Browse files
bmwillgitster
authored andcommitted
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>
1 parent 1af8ae1 commit b4be741

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

builtin/ls-remote.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "cache.h"
33
#include "transport.h"
44
#include "remote.h"
5+
#include "refs.h"
56

67
static const char * const ls_remote_usage[] = {
78
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)
4344
int show_symref_target = 0;
4445
const char *uploadpack = NULL;
4546
const char **pattern = NULL;
47+
struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
4648

4749
struct remote *remote;
4850
struct transport *transport;
@@ -74,8 +76,17 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
7476
if (argc > 1) {
7577
int i;
7678
pattern = xcalloc(argc, sizeof(const char *));
77-
for (i = 1; i < argc; i++)
79+
for (i = 1; i < argc; i++) {
80+
const char *glob;
7881
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+
}
7990
}
8091

8192
remote = remote_get(dest);
@@ -96,7 +107,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
96107
if (uploadpack != NULL)
97108
transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);
98109

99-
ref = transport_get_remote_refs(transport, NULL);
110+
ref = transport_get_remote_refs(transport, &ref_prefixes);
100111
if (transport_disconnect(transport))
101112
return 1;
102113

refs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "tag.h"
1414
#include "submodule.h"
1515
#include "worktree.h"
16+
#include "argv-array.h"
1617

1718
/*
1819
* List of all available backends
@@ -501,6 +502,19 @@ int refname_match(const char *abbrev_name, const char *full_name)
501502
return 0;
502503
}
503504

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+
504518
/*
505519
* *string and *len will only be substituted, and *string returned (for
506520
* later free()ing) if the string passed in is a magic short-hand form

refs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
139139
*/
140140
int refname_match(const char *abbrev_name, const char *full_name);
141141

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+
142149
int expand_ref(const char *str, int len, struct object_id *oid, char **ref);
143150
int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
144151
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);

t/t5702-protocol-v2.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ test_expect_success 'list refs with git:// using protocol v2' '
3232
test_cmp actual expect
3333
'
3434

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+
3548
stop_git_daemon
3649

3750
# Test protocol v2 with 'file://' transport
@@ -54,4 +67,17 @@ test_expect_success 'list refs with file:// using protocol v2' '
5467
test_cmp actual expect
5568
'
5669

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+
5783
test_done

0 commit comments

Comments
 (0)