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 <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Brandon Williams committed
May 16, 2018 at 15:57 UTC
3eec3700fdc4d5b0a33729d45e7fb9735ed7e0f5
1 file changed
+104
-91
refspec.c
+104
-91
@@ -14,110 +14,123 @@ static struct refspec_item s_tag_refspec = {
14
/* See TAG_REFSPEC for the string version */
15
const struct refspec_item *tag_refspec = &s_tag_refspec;
16
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)
22
{
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;
27
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;
29
28
- is_glob = 0;
30
+ lhs = refspec;
31
+ if (*lhs == '+') {
32
+ item->force = 1;
33
+ lhs++;
34
+ }
35
30
- lhs = refspec[i];
31
- if (*lhs == '+') {
32
- rs[i].force = 1;
33
- lhs++;
34
- }
36
+ rhs = strrchr(lhs, ':');
37
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
+ }
46
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 {
88
/*
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.
94
*/
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;
100
}
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;
118
}
119
+ }
120
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
+}
123
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;
132
}
133
+
134
return rs;
135
136
invalid: