git

Форк
0
/
refspec.c 
283 строки · 6.3 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "gettext.h"
5
#include "hash.h"
6
#include "hex.h"
7
#include "strvec.h"
8
#include "refs.h"
9
#include "refspec.h"
10
#include "strbuf.h"
11

12
/*
13
 * Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
14
 * Returns 1 if successful and 0 if the refspec is invalid.
15
 */
16
static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch)
17
{
18
	size_t llen;
19
	int is_glob;
20
	const char *lhs, *rhs;
21
	int flags;
22

23
	is_glob = 0;
24

25
	lhs = refspec;
26
	if (*lhs == '+') {
27
		item->force = 1;
28
		lhs++;
29
	} else if (*lhs == '^') {
30
		item->negative = 1;
31
		lhs++;
32
	}
33

34
	rhs = strrchr(lhs, ':');
35

36
	/* negative refspecs only have one side */
37
	if (item->negative && rhs)
38
		return 0;
39

40
	/*
41
	 * Before going on, special case ":" (or "+:") as a refspec
42
	 * for pushing matching refs.
43
	 */
44
	if (!fetch && rhs == lhs && rhs[1] == '\0') {
45
		item->matching = 1;
46
		return 1;
47
	}
48

49
	if (rhs) {
50
		size_t rlen = strlen(++rhs);
51
		is_glob = (1 <= rlen && strchr(rhs, '*'));
52
		item->dst = xstrndup(rhs, rlen);
53
	} else {
54
		item->dst = NULL;
55
	}
56

57
	llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
58
	if (1 <= llen && memchr(lhs, '*', llen)) {
59
		if ((rhs && !is_glob) || (!rhs && !item->negative && fetch))
60
			return 0;
61
		is_glob = 1;
62
	} else if (rhs && is_glob) {
63
		return 0;
64
	}
65

66
	item->pattern = is_glob;
67
	if (llen == 1 && *lhs == '@')
68
		item->src = xstrdup("HEAD");
69
	else
70
		item->src = xstrndup(lhs, llen);
71
	flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
72

73
	if (item->negative) {
74
		struct object_id unused;
75

76
		/*
77
		 * Negative refspecs only have a LHS, which indicates a ref
78
		 * (or pattern of refs) to exclude from other matches. This
79
		 * can either be a simple ref, or a glob pattern. Exact sha1
80
		 * match is not currently supported.
81
		 */
82
		if (!*item->src)
83
			return 0; /* negative refspecs must not be empty */
84
		else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
85
			return 0; /* negative refpsecs cannot be exact sha1 */
86
		else if (!check_refname_format(item->src, flags))
87
			; /* valid looking ref is ok */
88
		else
89
			return 0;
90

91
		/* the other rules below do not apply to negative refspecs */
92
		return 1;
93
	}
94

95
	if (fetch) {
96
		struct object_id unused;
97

98
		/* LHS */
99
		if (!*item->src)
100
			; /* empty is ok; it means "HEAD" */
101
		else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
102
			item->exact_sha1 = 1; /* ok */
103
		else if (!check_refname_format(item->src, flags))
104
			; /* valid looking ref is ok */
105
		else
106
			return 0;
107
		/* RHS */
108
		if (!item->dst)
109
			; /* missing is ok; it is the same as empty */
110
		else if (!*item->dst)
111
			; /* empty is ok; it means "do not store" */
112
		else if (!check_refname_format(item->dst, flags))
113
			; /* valid looking ref is ok */
114
		else
115
			return 0;
116
	} else {
117
		/*
118
		 * LHS
119
		 * - empty is allowed; it means delete.
120
		 * - when wildcarded, it must be a valid looking ref.
121
		 * - otherwise, it must be an extended SHA-1, but
122
		 *   there is no existing way to validate this.
123
		 */
124
		if (!*item->src)
125
			; /* empty is ok */
126
		else if (is_glob) {
127
			if (check_refname_format(item->src, flags))
128
				return 0;
129
		}
130
		else
131
			; /* anything goes, for now */
132
		/*
133
		 * RHS
134
		 * - missing is allowed, but LHS then must be a
135
		 *   valid looking ref.
136
		 * - empty is not allowed.
137
		 * - otherwise it must be a valid looking ref.
138
		 */
139
		if (!item->dst) {
140
			if (check_refname_format(item->src, flags))
141
				return 0;
142
		} else if (!*item->dst) {
143
			return 0;
144
		} else {
145
			if (check_refname_format(item->dst, flags))
146
				return 0;
147
		}
148
	}
149

150
	return 1;
151
}
152

153
int refspec_item_init(struct refspec_item *item, const char *refspec, int fetch)
154
{
155
	memset(item, 0, sizeof(*item));
156
	return parse_refspec(item, refspec, fetch);
157
}
158

159
void refspec_item_init_or_die(struct refspec_item *item, const char *refspec,
160
			      int fetch)
161
{
162
	if (!refspec_item_init(item, refspec, fetch))
163
		die(_("invalid refspec '%s'"), refspec);
164
}
165

166
void refspec_item_clear(struct refspec_item *item)
167
{
168
	FREE_AND_NULL(item->src);
169
	FREE_AND_NULL(item->dst);
170
	item->force = 0;
171
	item->pattern = 0;
172
	item->matching = 0;
173
	item->exact_sha1 = 0;
174
}
175

176
void refspec_init(struct refspec *rs, int fetch)
177
{
178
	memset(rs, 0, sizeof(*rs));
179
	rs->fetch = fetch;
180
}
181

182
static void refspec_append_nodup(struct refspec *rs, char *refspec)
183
{
184
	struct refspec_item item;
185

186
	refspec_item_init_or_die(&item, refspec, rs->fetch);
187

188
	ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc);
189
	rs->items[rs->nr++] = item;
190

191
	ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc);
192
	rs->raw[rs->raw_nr++] = refspec;
193
}
194

195
void refspec_append(struct refspec *rs, const char *refspec)
196
{
197
	refspec_append_nodup(rs, xstrdup(refspec));
198
}
199

200
void refspec_appendf(struct refspec *rs, const char *fmt, ...)
201
{
202
	va_list ap;
203

204
	va_start(ap, fmt);
205
	refspec_append_nodup(rs, xstrvfmt(fmt, ap));
206
	va_end(ap);
207
}
208

209
void refspec_appendn(struct refspec *rs, const char **refspecs, int nr)
210
{
211
	int i;
212
	for (i = 0; i < nr; i++)
213
		refspec_append(rs, refspecs[i]);
214
}
215

216
void refspec_clear(struct refspec *rs)
217
{
218
	int i;
219

220
	for (i = 0; i < rs->nr; i++)
221
		refspec_item_clear(&rs->items[i]);
222

223
	FREE_AND_NULL(rs->items);
224
	rs->alloc = 0;
225
	rs->nr = 0;
226

227
	for (i = 0; i < rs->raw_nr; i++)
228
		free((char *)rs->raw[i]);
229
	FREE_AND_NULL(rs->raw);
230
	rs->raw_alloc = 0;
231
	rs->raw_nr = 0;
232

233
	rs->fetch = 0;
234
}
235

236
int valid_fetch_refspec(const char *fetch_refspec_str)
237
{
238
	struct refspec_item refspec;
239
	int ret = refspec_item_init(&refspec, fetch_refspec_str, REFSPEC_FETCH);
240
	refspec_item_clear(&refspec);
241
	return ret;
242
}
243

244
int valid_remote_name(const char *name)
245
{
246
	int result;
247
	struct strbuf refspec = STRBUF_INIT;
248
	strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name);
249
	result = valid_fetch_refspec(refspec.buf);
250
	strbuf_release(&refspec);
251
	return result;
252
}
253

254
void refspec_ref_prefixes(const struct refspec *rs,
255
			  struct strvec *ref_prefixes)
256
{
257
	int i;
258
	for (i = 0; i < rs->nr; i++) {
259
		const struct refspec_item *item = &rs->items[i];
260
		const char *prefix = NULL;
261

262
		if (item->exact_sha1 || item->negative)
263
			continue;
264
		if (rs->fetch == REFSPEC_FETCH)
265
			prefix = item->src;
266
		else if (item->dst)
267
			prefix = item->dst;
268
		else if (item->src && !item->exact_sha1)
269
			prefix = item->src;
270

271
		if (!prefix)
272
			continue;
273

274
		if (item->pattern) {
275
			const char *glob = strchr(prefix, '*');
276
			strvec_pushf(ref_prefixes, "%.*s",
277
				     (int)(glob - prefix),
278
				     prefix);
279
		} else {
280
			expand_ref_prefix(ref_prefixes, prefix);
281
		}
282
	}
283
}
284

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.