]> git.ipfire.org Git - thirdparty/git.git/blame - refspec.c
Documentation/RelNotes/2.45.0.txt: fix typo
[thirdparty/git.git] / refspec.c
CommitLineData
36bf1958 1#include "git-compat-util.h"
a6dc3d36 2#include "gettext.h"
d1cbe1e6 3#include "hash.h"
41771fa4 4#include "hex.h"
dbbcd44f 5#include "strvec.h"
ec0cb496
BW
6#include "refs.h"
7#include "refspec.h"
d4a4f929 8#include "strbuf.h"
ec0cb496 9
0ad4a5ff 10static struct refspec_item s_tag_refspec = {
b3454e2d
ÆAB
11 .force = 0,
12 .pattern = 1,
13 .matching = 0,
14 .exact_sha1 = 0,
15 .negative = 0,
16 .src = "refs/tags/*",
17 .dst = "refs/tags/*",
ec0cb496
BW
18};
19
20/* See TAG_REFSPEC for the string version */
0ad4a5ff 21const struct refspec_item *tag_refspec = &s_tag_refspec;
ec0cb496 22
3eec3700
BW
23/*
24 * Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
25 * Returns 1 if successful and 0 if the refspec is invalid.
26 */
27static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch)
ec0cb496 28{
3eec3700
BW
29 size_t llen;
30 int is_glob;
31 const char *lhs, *rhs;
32 int flags;
ec0cb496 33
3eec3700 34 is_glob = 0;
ec0cb496 35
3eec3700
BW
36 lhs = refspec;
37 if (*lhs == '+') {
38 item->force = 1;
39 lhs++;
c0192df6
JK
40 } else if (*lhs == '^') {
41 item->negative = 1;
42 lhs++;
3eec3700 43 }
ec0cb496 44
3eec3700 45 rhs = strrchr(lhs, ':');
ec0cb496 46
c0192df6
JK
47 /* negative refspecs only have one side */
48 if (item->negative && rhs)
49 return 0;
50
3eec3700
BW
51 /*
52 * Before going on, special case ":" (or "+:") as a refspec
53 * for pushing matching refs.
54 */
55 if (!fetch && rhs == lhs && rhs[1] == '\0') {
56 item->matching = 1;
57 return 1;
58 }
ec0cb496 59
3eec3700
BW
60 if (rhs) {
61 size_t rlen = strlen(++rhs);
62 is_glob = (1 <= rlen && strchr(rhs, '*'));
63 item->dst = xstrndup(rhs, rlen);
c3072c6e
JH
64 } else {
65 item->dst = NULL;
3eec3700
BW
66 }
67
68 llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
69 if (1 <= llen && memchr(lhs, '*', llen)) {
c0192df6 70 if ((rhs && !is_glob) || (!rhs && !item->negative && fetch))
3eec3700
BW
71 return 0;
72 is_glob = 1;
73 } else if (rhs && is_glob) {
74 return 0;
75 }
76
77 item->pattern = is_glob;
374fbaef
FC
78 if (llen == 1 && *lhs == '@')
79 item->src = xstrdup("HEAD");
80 else
81 item->src = xstrndup(lhs, llen);
3eec3700
BW
82 flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
83
c0192df6
JK
84 if (item->negative) {
85 struct object_id unused;
86
87 /*
88 * Negative refspecs only have a LHS, which indicates a ref
89 * (or pattern of refs) to exclude from other matches. This
90 * can either be a simple ref, or a glob pattern. Exact sha1
91 * match is not currently supported.
92 */
93 if (!*item->src)
94 return 0; /* negative refspecs must not be empty */
95 else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
96 return 0; /* negative refpsecs cannot be exact sha1 */
97 else if (!check_refname_format(item->src, flags))
98 ; /* valid looking ref is ok */
99 else
100 return 0;
101
102 /* the other rules below do not apply to negative refspecs */
103 return 1;
104 }
105
3eec3700
BW
106 if (fetch) {
107 struct object_id unused;
108
109 /* LHS */
110 if (!*item->src)
111 ; /* empty is ok; it means "HEAD" */
b8d45d03 112 else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
3eec3700
BW
113 item->exact_sha1 = 1; /* ok */
114 else if (!check_refname_format(item->src, flags))
115 ; /* valid looking ref is ok */
116 else
117 return 0;
118 /* RHS */
119 if (!item->dst)
120 ; /* missing is ok; it is the same as empty */
121 else if (!*item->dst)
122 ; /* empty is ok; it means "do not store" */
123 else if (!check_refname_format(item->dst, flags))
124 ; /* valid looking ref is ok */
125 else
126 return 0;
127 } else {
ec0cb496 128 /*
3eec3700
BW
129 * LHS
130 * - empty is allowed; it means delete.
131 * - when wildcarded, it must be a valid looking ref.
132 * - otherwise, it must be an extended SHA-1, but
133 * there is no existing way to validate this.
ec0cb496 134 */
3eec3700
BW
135 if (!*item->src)
136 ; /* empty is ok */
137 else if (is_glob) {
138 if (check_refname_format(item->src, flags))
139 return 0;
ec0cb496 140 }
3eec3700
BW
141 else
142 ; /* anything goes, for now */
143 /*
144 * RHS
145 * - missing is allowed, but LHS then must be a
146 * valid looking ref.
147 * - empty is not allowed.
148 * - otherwise it must be a valid looking ref.
149 */
150 if (!item->dst) {
151 if (check_refname_format(item->src, flags))
152 return 0;
153 } else if (!*item->dst) {
154 return 0;
155 } else {
156 if (check_refname_format(item->dst, flags))
157 return 0;
ec0cb496 158 }
3eec3700 159 }
ec0cb496 160
3eec3700
BW
161 return 1;
162}
ec0cb496 163
c495fd3d 164int refspec_item_init(struct refspec_item *item, const char *refspec, int fetch)
6d4c0578
BW
165{
166 memset(item, 0, sizeof(*item));
c495fd3d
ÆAB
167 return parse_refspec(item, refspec, fetch);
168}
6d4c0578 169
c495fd3d
ÆAB
170void refspec_item_init_or_die(struct refspec_item *item, const char *refspec,
171 int fetch)
172{
173 if (!refspec_item_init(item, refspec, fetch))
1b5e07bb 174 die(_("invalid refspec '%s'"), refspec);
6d4c0578
BW
175}
176
177void refspec_item_clear(struct refspec_item *item)
178{
179 FREE_AND_NULL(item->src);
180 FREE_AND_NULL(item->dst);
181 item->force = 0;
182 item->pattern = 0;
183 item->matching = 0;
184 item->exact_sha1 = 0;
185}
186
187void refspec_init(struct refspec *rs, int fetch)
188{
189 memset(rs, 0, sizeof(*rs));
190 rs->fetch = fetch;
191}
192
1af8b8c0 193static void refspec_append_nodup(struct refspec *rs, char *refspec)
6d4c0578
BW
194{
195 struct refspec_item item;
196
dc064221 197 refspec_item_init_or_die(&item, refspec, rs->fetch);
6d4c0578
BW
198
199 ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc);
200 rs->items[rs->nr++] = item;
201
202 ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc);
1af8b8c0
RS
203 rs->raw[rs->raw_nr++] = refspec;
204}
205
206void refspec_append(struct refspec *rs, const char *refspec)
207{
208 refspec_append_nodup(rs, xstrdup(refspec));
209}
210
211void refspec_appendf(struct refspec *rs, const char *fmt, ...)
212{
213 va_list ap;
214
215 va_start(ap, fmt);
216 refspec_append_nodup(rs, xstrvfmt(fmt, ap));
217 va_end(ap);
6d4c0578
BW
218}
219
220void refspec_appendn(struct refspec *rs, const char **refspecs, int nr)
221{
222 int i;
223 for (i = 0; i < nr; i++)
224 refspec_append(rs, refspecs[i]);
225}
226
227void refspec_clear(struct refspec *rs)
228{
229 int i;
230
231 for (i = 0; i < rs->nr; i++)
232 refspec_item_clear(&rs->items[i]);
233
234 FREE_AND_NULL(rs->items);
235 rs->alloc = 0;
236 rs->nr = 0;
237
238 for (i = 0; i < rs->raw_nr; i++)
239 free((char *)rs->raw[i]);
240 FREE_AND_NULL(rs->raw);
241 rs->raw_alloc = 0;
242 rs->raw_nr = 0;
243
244 rs->fetch = 0;
245}
c8fa9efe
BW
246
247int valid_fetch_refspec(const char *fetch_refspec_str)
248{
249 struct refspec_item refspec;
7865d157 250 int ret = refspec_item_init(&refspec, fetch_refspec_str, REFSPEC_FETCH);
c8fa9efe
BW
251 refspec_item_clear(&refspec);
252 return ret;
253}
6373cb59 254
f2c6fda8
SB
255int valid_remote_name(const char *name)
256{
257 int result;
258 struct strbuf refspec = STRBUF_INIT;
259 strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name);
260 result = valid_fetch_refspec(refspec.buf);
261 strbuf_release(&refspec);
262 return result;
263}
264
6373cb59 265void refspec_ref_prefixes(const struct refspec *rs,
c972bf4c 266 struct strvec *ref_prefixes)
6373cb59
BW
267{
268 int i;
269 for (i = 0; i < rs->nr; i++) {
270 const struct refspec_item *item = &rs->items[i];
271 const char *prefix = NULL;
272
c0192df6 273 if (item->exact_sha1 || item->negative)
6c301adb 274 continue;
6373cb59
BW
275 if (rs->fetch == REFSPEC_FETCH)
276 prefix = item->src;
277 else if (item->dst)
278 prefix = item->dst;
279 else if (item->src && !item->exact_sha1)
280 prefix = item->src;
281
bfded875
FC
282 if (!prefix)
283 continue;
284
285 if (item->pattern) {
286 const char *glob = strchr(prefix, '*');
287 strvec_pushf(ref_prefixes, "%.*s",
288 (int)(glob - prefix),
289 prefix);
290 } else {
291 expand_ref_prefix(ref_prefixes, prefix);
6373cb59
BW
292 }
293 }
294}