pathspec: create parse_long_magic function

Factor out the logic responsible for parsing long magic into its own function. As well as hoist the prefix check logic outside of the inner loop as there isn't anything that needs to be done after matching "prefix:". Signed-off-by: Brandon Williams <bmwill@google.com> Reviewed-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Jan 4, 2017 at 10:04 UTC 8881fde01340e1fff4a3acc17805886b644d18d8
1 file changed +57 -35
pathspec.c
+57 -35
@@ -156,6 +156,60 @@ static int get_global_magic(int element_magic)
156 return global_magic;
157 }
158
159 +/*
160 + * Parse the pathspec element looking for long magic
161 + *
162 + * saves all magic in 'magic'
163 + * if prefix magic is used, save the prefix length in 'prefix_len'
164 + * returns the position in 'elem' after all magic has been parsed
165 + */
166 +static const char *parse_long_magic(unsigned *magic, int *prefix_len,
167 + const char *elem)
168 +{
169 + const char *pos;
170 + const char *nextat;
171 +
172 + for (pos = elem + 2; *pos && *pos != ')'; pos = nextat) {
173 + size_t len = strcspn(pos, ",)");
174 + int i;
175 +
176 + if (pos[len] == ',')
177 + nextat = pos + len + 1; /* handle ',' */
178 + else
179 + nextat = pos + len; /* handle ')' and '\0' */
180 +
181 + if (!len)
182 + continue;
183 +
184 + if (starts_with(pos, "prefix:")) {
185 + char *endptr;
186 + *prefix_len = strtol(pos + 7, &endptr, 10);
187 + if (endptr - pos != len)
188 + die(_("invalid parameter for pathspec magic 'prefix'"));
189 + continue;
190 + }
191 +
192 + for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
193 + if (strlen(pathspec_magic[i].name) == len &&
194 + !strncmp(pathspec_magic[i].name, pos, len)) {
195 + *magic |= pathspec_magic[i].bit;
196 + break;
197 + }
198 + }
199 +
200 + if (ARRAY_SIZE(pathspec_magic) <= i)
201 + die(_("Invalid pathspec magic '%.*s' in '%s'"),
202 + (int) len, pos, elem);
203 + }
204 +
205 + if (*pos != ')')
206 + die(_("Missing ')' at the end of pathspec magic in '%s'"),
207 + elem);
208 + pos++;
209 +
210 + return pos;
211 +}
212 +
213 /*
214 * Parse the pathspec element looking for short magic
215 *
@@ -218,41 +272,9 @@ static unsigned prefix_pathspec(struct pathspec_item *item, unsigned flags,
272 ; /* nothing to do */
273 } else if (elt[1] == '(') {
274 /* longhand */
221 - const char *nextat;
222 - for (copyfrom = elt + 2;
223 - *copyfrom && *copyfrom != ')';
224 - copyfrom = nextat) {
225 - size_t len = strcspn(copyfrom, ",)");
226 - if (copyfrom[len] == ',')
227 - nextat = copyfrom + len + 1;
228 - else
229 - /* handle ')' and '\0' */
230 - nextat = copyfrom + len;
231 - if (!len)
232 - continue;
233 - for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++) {
234 - if (strlen(pathspec_magic[i].name) == len &&
235 - !strncmp(pathspec_magic[i].name, copyfrom, len)) {
236 - element_magic |= pathspec_magic[i].bit;
237 - break;
238 - }
239 - if (starts_with(copyfrom, "prefix:")) {
240 - char *endptr;
241 - pathspec_prefix = strtol(copyfrom + 7,
242 - &endptr, 10);
243 - if (endptr - copyfrom != len)
244 - die(_("invalid parameter for pathspec magic 'prefix'"));
245 - /* "i" would be wrong, but it does not matter */
246 - break;
247 - }
248 - }
249 - if (ARRAY_SIZE(pathspec_magic) <= i)
250 - die(_("Invalid pathspec magic '%.*s' in '%s'"),
251 - (int) len, copyfrom, elt);
252 - }
253 - if (*copyfrom != ')')
254 - die(_("Missing ')' at the end of pathspec magic in '%s'"), elt);
255 - copyfrom++;
275 + copyfrom = parse_long_magic(&element_magic,
276 + &pathspec_prefix,
277 + elt);
278 } else {
279 /* shorthand */
280 copyfrom = parse_short_magic(&element_magic, elt);