Skip to content

Commit 3eec370

Browse files
bmwillgitster
authored andcommitted
refspec: factor out parsing a single refspec
Factor out the logic which parses a single refspec into its own function. This makes it easier to reuse this logic in a future patch. Signed-off-by: Brandon Williams <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0ad4a5f commit 3eec370

File tree

1 file changed

+104
-91
lines changed

1 file changed

+104
-91
lines changed

refspec.c

Lines changed: 104 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -14,110 +14,123 @@ static struct refspec_item s_tag_refspec = {
1414
/* See TAG_REFSPEC for the string version */
1515
const struct refspec_item *tag_refspec = &s_tag_refspec;
1616

17-
static struct refspec_item *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
17+
/*
18+
* Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
19+
* Returns 1 if successful and 0 if the refspec is invalid.
20+
*/
21+
static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch)
1822
{
19-
int i;
20-
struct refspec_item *rs = xcalloc(nr_refspec, sizeof(*rs));
23+
size_t llen;
24+
int is_glob;
25+
const char *lhs, *rhs;
26+
int flags;
2127

22-
for (i = 0; i < nr_refspec; i++) {
23-
size_t llen;
24-
int is_glob;
25-
const char *lhs, *rhs;
26-
int flags;
28+
is_glob = 0;
2729

28-
is_glob = 0;
30+
lhs = refspec;
31+
if (*lhs == '+') {
32+
item->force = 1;
33+
lhs++;
34+
}
2935

30-
lhs = refspec[i];
31-
if (*lhs == '+') {
32-
rs[i].force = 1;
33-
lhs++;
34-
}
36+
rhs = strrchr(lhs, ':');
3537

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

47+
if (rhs) {
48+
size_t rlen = strlen(++rhs);
49+
is_glob = (1 <= rlen && strchr(rhs, '*'));
50+
item->dst = xstrndup(rhs, rlen);
51+
}
52+
53+
llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
54+
if (1 <= llen && memchr(lhs, '*', llen)) {
55+
if ((rhs && !is_glob) || (!rhs && fetch))
56+
return 0;
57+
is_glob = 1;
58+
} else if (rhs && is_glob) {
59+
return 0;
60+
}
61+
62+
item->pattern = is_glob;
63+
item->src = xstrndup(lhs, llen);
64+
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
65+
66+
if (fetch) {
67+
struct object_id unused;
68+
69+
/* LHS */
70+
if (!*item->src)
71+
; /* empty is ok; it means "HEAD" */
72+
else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(item->src, &unused))
73+
item->exact_sha1 = 1; /* ok */
74+
else if (!check_refname_format(item->src, flags))
75+
; /* valid looking ref is ok */
76+
else
77+
return 0;
78+
/* RHS */
79+
if (!item->dst)
80+
; /* missing is ok; it is the same as empty */
81+
else if (!*item->dst)
82+
; /* empty is ok; it means "do not store" */
83+
else if (!check_refname_format(item->dst, flags))
84+
; /* valid looking ref is ok */
85+
else
86+
return 0;
87+
} else {
3888
/*
39-
* Before going on, special case ":" (or "+:") as a refspec
40-
* for pushing matching refs.
89+
* LHS
90+
* - empty is allowed; it means delete.
91+
* - when wildcarded, it must be a valid looking ref.
92+
* - otherwise, it must be an extended SHA-1, but
93+
* there is no existing way to validate this.
4194
*/
42-
if (!fetch && rhs == lhs && rhs[1] == '\0') {
43-
rs[i].matching = 1;
44-
continue;
95+
if (!*item->src)
96+
; /* empty is ok */
97+
else if (is_glob) {
98+
if (check_refname_format(item->src, flags))
99+
return 0;
45100
}
46-
47-
if (rhs) {
48-
size_t rlen = strlen(++rhs);
49-
is_glob = (1 <= rlen && strchr(rhs, '*'));
50-
rs[i].dst = xstrndup(rhs, rlen);
101+
else
102+
; /* anything goes, for now */
103+
/*
104+
* RHS
105+
* - missing is allowed, but LHS then must be a
106+
* valid looking ref.
107+
* - empty is not allowed.
108+
* - otherwise it must be a valid looking ref.
109+
*/
110+
if (!item->dst) {
111+
if (check_refname_format(item->src, flags))
112+
return 0;
113+
} else if (!*item->dst) {
114+
return 0;
115+
} else {
116+
if (check_refname_format(item->dst, flags))
117+
return 0;
51118
}
119+
}
52120

53-
llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
54-
if (1 <= llen && memchr(lhs, '*', llen)) {
55-
if ((rhs && !is_glob) || (!rhs && fetch))
56-
goto invalid;
57-
is_glob = 1;
58-
} else if (rhs && is_glob) {
59-
goto invalid;
60-
}
121+
return 1;
122+
}
61123

62-
rs[i].pattern = is_glob;
63-
rs[i].src = xstrndup(lhs, llen);
64-
flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
65-
66-
if (fetch) {
67-
struct object_id unused;
68-
69-
/* LHS */
70-
if (!*rs[i].src)
71-
; /* empty is ok; it means "HEAD" */
72-
else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(rs[i].src, &unused))
73-
rs[i].exact_sha1 = 1; /* ok */
74-
else if (!check_refname_format(rs[i].src, flags))
75-
; /* valid looking ref is ok */
76-
else
77-
goto invalid;
78-
/* RHS */
79-
if (!rs[i].dst)
80-
; /* missing is ok; it is the same as empty */
81-
else if (!*rs[i].dst)
82-
; /* empty is ok; it means "do not store" */
83-
else if (!check_refname_format(rs[i].dst, flags))
84-
; /* valid looking ref is ok */
85-
else
86-
goto invalid;
87-
} else {
88-
/*
89-
* LHS
90-
* - empty is allowed; it means delete.
91-
* - when wildcarded, it must be a valid looking ref.
92-
* - otherwise, it must be an extended SHA-1, but
93-
* there is no existing way to validate this.
94-
*/
95-
if (!*rs[i].src)
96-
; /* empty is ok */
97-
else if (is_glob) {
98-
if (check_refname_format(rs[i].src, flags))
99-
goto invalid;
100-
}
101-
else
102-
; /* anything goes, for now */
103-
/*
104-
* RHS
105-
* - missing is allowed, but LHS then must be a
106-
* valid looking ref.
107-
* - empty is not allowed.
108-
* - otherwise it must be a valid looking ref.
109-
*/
110-
if (!rs[i].dst) {
111-
if (check_refname_format(rs[i].src, flags))
112-
goto invalid;
113-
} else if (!*rs[i].dst) {
114-
goto invalid;
115-
} else {
116-
if (check_refname_format(rs[i].dst, flags))
117-
goto invalid;
118-
}
119-
}
124+
static struct refspec_item *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
125+
{
126+
int i;
127+
struct refspec_item *rs = xcalloc(nr_refspec, sizeof(*rs));
128+
129+
for (i = 0; i < nr_refspec; i++) {
130+
if (!parse_refspec(&rs[i], refspec[i], fetch))
131+
goto invalid;
120132
}
133+
121134
return rs;
122135

123136
invalid:

0 commit comments

Comments
 (0)