@@ -1310,65 +1310,68 @@ int update_ref(const char *msg, const char *refname,
1310
1310
old_oid , flags , onerr );
1311
1311
}
1312
1312
1313
+ /*
1314
+ * Check that the string refname matches a rule of the form
1315
+ * "{prefix}%.*s{suffix}". So "foo/bar/baz" would match the rule
1316
+ * "foo/%.*s/baz", and return the string "bar".
1317
+ */
1318
+ static const char * match_parse_rule (const char * refname , const char * rule ,
1319
+ size_t * len )
1320
+ {
1321
+ /*
1322
+ * Check that rule matches refname up to the first percent in the rule.
1323
+ * We can bail immediately if not, but otherwise we leave "rule" at the
1324
+ * %-placeholder, and "refname" at the start of the potential matched
1325
+ * name.
1326
+ */
1327
+ while (* rule != '%' ) {
1328
+ if (!* rule )
1329
+ BUG ("rev-parse rule did not have percent" );
1330
+ if (* refname ++ != * rule ++ )
1331
+ return NULL ;
1332
+ }
1333
+
1334
+ /*
1335
+ * Check that our "%" is the expected placeholder. This assumes there
1336
+ * are no other percents (placeholder or quoted) in the string, but
1337
+ * that is sufficient for our rev-parse rules.
1338
+ */
1339
+ if (!skip_prefix (rule , "%.*s" , & rule ))
1340
+ return NULL ;
1341
+
1342
+ /*
1343
+ * And now check that our suffix (if any) matches.
1344
+ */
1345
+ if (!strip_suffix (refname , rule , len ))
1346
+ return NULL ;
1347
+
1348
+ return refname ; /* len set by strip_suffix() */
1349
+ }
1350
+
1313
1351
char * refs_shorten_unambiguous_ref (struct ref_store * refs ,
1314
1352
const char * refname , int strict )
1315
1353
{
1316
1354
int i ;
1317
- static char * * scanf_fmts ;
1318
- static int nr_rules ;
1319
- char * short_name ;
1320
1355
struct strbuf resolved_buf = STRBUF_INIT ;
1321
1356
1322
- if (!nr_rules ) {
1323
- /*
1324
- * Pre-generate scanf formats from ref_rev_parse_rules[].
1325
- * Generate a format suitable for scanf from a
1326
- * ref_rev_parse_rules rule by interpolating "%s" at the
1327
- * location of the "%.*s".
1328
- */
1329
- size_t total_len = 0 ;
1330
- size_t offset = 0 ;
1331
-
1332
- /* the rule list is NULL terminated, count them first */
1333
- for (nr_rules = 0 ; ref_rev_parse_rules [nr_rules ]; nr_rules ++ )
1334
- /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */
1335
- total_len += strlen (ref_rev_parse_rules [nr_rules ]) - 2 + 1 ;
1336
-
1337
- scanf_fmts = xmalloc (st_add (st_mult (sizeof (char * ), nr_rules ), total_len ));
1338
-
1339
- offset = 0 ;
1340
- for (i = 0 ; i < nr_rules ; i ++ ) {
1341
- assert (offset < total_len );
1342
- scanf_fmts [i ] = (char * )& scanf_fmts [nr_rules ] + offset ;
1343
- offset += xsnprintf (scanf_fmts [i ], total_len - offset ,
1344
- ref_rev_parse_rules [i ], 2 , "%s" ) + 1 ;
1345
- }
1346
- }
1347
-
1348
- /* bail out if there are no rules */
1349
- if (!nr_rules )
1350
- return xstrdup (refname );
1351
-
1352
- /* buffer for scanf result, at most refname must fit */
1353
- short_name = xstrdup (refname );
1354
-
1355
1357
/* skip first rule, it will always match */
1356
- for (i = nr_rules - 1 ; i > 0 ; -- i ) {
1358
+ for (i = NUM_REV_PARSE_RULES - 1 ; i > 0 ; -- i ) {
1357
1359
int j ;
1358
1360
int rules_to_fail = i ;
1359
- int short_name_len ;
1361
+ const char * short_name ;
1362
+ size_t short_name_len ;
1360
1363
1361
- if (1 != sscanf (refname , scanf_fmts [i ], short_name ))
1364
+ short_name = match_parse_rule (refname , ref_rev_parse_rules [i ],
1365
+ & short_name_len );
1366
+ if (!short_name )
1362
1367
continue ;
1363
1368
1364
- short_name_len = strlen (short_name );
1365
-
1366
1369
/*
1367
1370
* in strict mode, all (except the matched one) rules
1368
1371
* must fail to resolve to a valid non-ambiguous ref
1369
1372
*/
1370
1373
if (strict )
1371
- rules_to_fail = nr_rules ;
1374
+ rules_to_fail = NUM_REV_PARSE_RULES ;
1372
1375
1373
1376
/*
1374
1377
* check if the short name resolves to a valid ref,
@@ -1388,7 +1391,8 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
1388
1391
*/
1389
1392
strbuf_reset (& resolved_buf );
1390
1393
strbuf_addf (& resolved_buf , rule ,
1391
- short_name_len , short_name );
1394
+ cast_size_t_to_int (short_name_len ),
1395
+ short_name );
1392
1396
if (refs_ref_exists (refs , resolved_buf .buf ))
1393
1397
break ;
1394
1398
}
@@ -1399,12 +1403,11 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
1399
1403
*/
1400
1404
if (j == rules_to_fail ) {
1401
1405
strbuf_release (& resolved_buf );
1402
- return short_name ;
1406
+ return xmemdupz ( short_name , short_name_len ) ;
1403
1407
}
1404
1408
}
1405
1409
1406
1410
strbuf_release (& resolved_buf );
1407
- free (short_name );
1408
1411
return xstrdup (refname );
1409
1412
}
1410
1413
0 commit comments