]>
Commit | Line | Data |
---|---|---|
18f7c51c | 1 | #include "builtin.h" |
18705953 | 2 | #include "cache.h" |
18f7c51c DB |
3 | #include "transport.h" |
4 | #include "remote.h" | |
18705953 | 5 | |
8951d7c1 DB |
6 | static const char ls_remote_usage[] = |
7 | "git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>"; | |
18705953 | 8 | |
2ea7fe0d JH |
9 | /* |
10 | * pattern is a list of tail-part of accepted refnames. Is there one | |
11 | * among them that is a suffix of the path? Directory boundary must | |
12 | * be honored when checking this match. IOW, patterns "master" and | |
13 | * "sa/master" both match path "refs/hold/sa/master". On the other | |
14 | * hand, path "refs/hold/foosa/master" is matched by "master" but not | |
15 | * by "sa/master". | |
16 | */ | |
17 | ||
18 | static int tail_match(const char **pattern, const char *path) | |
19 | { | |
20 | int pathlen; | |
21 | const char *p; | |
22 | ||
23 | if (!*pattern) | |
24 | return 1; /* no restriction */ | |
25 | ||
26 | for (pathlen = strlen(path); (p = *pattern); pattern++) { | |
27 | int pfxlen = pathlen - strlen(p); | |
28 | if (pfxlen < 0) | |
29 | continue; /* pattern is longer, will never match */ | |
30 | if (strcmp(path + pfxlen, p)) | |
31 | continue; /* no tail match */ | |
32 | if (!pfxlen || path[pfxlen - 1] == '/') | |
33 | return 1; /* fully match at directory boundary */ | |
34 | } | |
35 | return 0; | |
36 | } | |
37 | ||
8951d7c1 | 38 | int cmd_ls_remote(int argc, const char **argv, const char *prefix) |
18705953 | 39 | { |
18f7c51c DB |
40 | int i; |
41 | const char *dest = NULL; | |
e44eb3e4 | 42 | int nongit = 0; |
2718ff09 | 43 | unsigned flags = 0; |
18f7c51c | 44 | const char *uploadpack = NULL; |
2ea7fe0d | 45 | const char **pattern = NULL; |
18f7c51c | 46 | |
7c2c6ee7 | 47 | struct remote *remote; |
18f7c51c DB |
48 | struct transport *transport; |
49 | const struct ref *ref; | |
e44eb3e4 JH |
50 | |
51 | setup_git_directory_gently(&nongit); | |
18705953 JH |
52 | |
53 | for (i = 1; i < argc; i++) { | |
18f7c51c | 54 | const char *arg = argv[i]; |
18705953 JH |
55 | |
56 | if (*arg == '-') { | |
599065a3 | 57 | if (!prefixcmp(arg, "--upload-pack=")) { |
27dca07f UKK |
58 | uploadpack = arg + 14; |
59 | continue; | |
60 | } | |
599065a3 | 61 | if (!prefixcmp(arg, "--exec=")) { |
27dca07f | 62 | uploadpack = arg + 7; |
2718ff09 LT |
63 | continue; |
64 | } | |
65 | if (!strcmp("--tags", arg)) { | |
66 | flags |= REF_TAGS; | |
67 | continue; | |
68 | } | |
69 | if (!strcmp("--heads", arg)) { | |
70 | flags |= REF_HEADS; | |
71 | continue; | |
72 | } | |
73 | if (!strcmp("--refs", arg)) { | |
74 | flags |= REF_NORMAL; | |
75 | continue; | |
76 | } | |
8951d7c1 | 77 | usage(ls_remote_usage); |
18705953 JH |
78 | } |
79 | dest = arg; | |
80 | break; | |
81 | } | |
2718ff09 | 82 | |
2ea7fe0d | 83 | if (!dest) |
8951d7c1 | 84 | usage(ls_remote_usage); |
2ea7fe0d | 85 | pattern = argv + i + 1; |
7c2c6ee7 SP |
86 | remote = nongit ? NULL : remote_get(dest); |
87 | if (remote && !remote->url_nr) | |
88 | die("remote %s has no configured URL", dest); | |
89 | transport = transport_get(remote, remote ? remote->url[0] : dest); | |
18f7c51c DB |
90 | if (uploadpack != NULL) |
91 | transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack); | |
92 | ||
93 | ref = transport_get_remote_refs(transport); | |
94 | ||
95 | if (!ref) | |
96 | return 1; | |
97 | ||
2ea7fe0d JH |
98 | for ( ; ref; ref = ref->next) { |
99 | if (!check_ref_type(ref, flags)) | |
100 | continue; | |
101 | if (!tail_match(pattern, ref->name)) | |
102 | continue; | |
103 | printf("%s %s\n", sha1_to_hex(ref->old_sha1), ref->name); | |
18f7c51c DB |
104 | } |
105 | return 0; | |
18705953 | 106 | } |