@@ -14,110 +14,123 @@ static struct refspec_item s_tag_refspec = {
14
14
/* See TAG_REFSPEC for the string version */
15
15
const struct refspec_item * tag_refspec = & s_tag_refspec ;
16
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 )
18
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 ;
21
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 ;
27
29
28
- is_glob = 0 ;
30
+ lhs = refspec ;
31
+ if (* lhs == '+' ) {
32
+ item -> force = 1 ;
33
+ lhs ++ ;
34
+ }
29
35
30
- lhs = refspec [i ];
31
- if (* lhs == '+' ) {
32
- rs [i ].force = 1 ;
33
- lhs ++ ;
34
- }
36
+ rhs = strrchr (lhs , ':' );
35
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
+ }
37
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 {
38
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.
41
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 ;
45
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 ;
51
118
}
119
+ }
52
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
+ }
61
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 ;
120
132
}
133
+
121
134
return rs ;
122
135
123
136
invalid :
0 commit comments