@@ -305,42 +305,127 @@ static void read_config(void)
305
305
git_config (handle_config );
306
306
}
307
307
308
- struct refspec * parse_ref_spec (int nr_refspec , const char * * refspec )
308
+ static struct refspec * parse_refspec_internal (int nr_refspec , const char * * refspec , int fetch )
309
309
{
310
310
int i ;
311
+ int st ;
311
312
struct refspec * rs = xcalloc (sizeof (* rs ), nr_refspec );
313
+
312
314
for (i = 0 ; i < nr_refspec ; i ++ ) {
313
- const char * sp , * ep , * gp ;
314
- sp = refspec [i ];
315
- if (* sp == '+' ) {
315
+ size_t llen , rlen ;
316
+ int is_glob ;
317
+ const char * lhs , * rhs ;
318
+
319
+ llen = rlen = is_glob = 0 ;
320
+
321
+ lhs = refspec [i ];
322
+ if (* lhs == '+' ) {
316
323
rs [i ].force = 1 ;
317
- sp ++ ;
324
+ lhs ++ ;
325
+ }
326
+
327
+ rhs = strrchr (lhs , ':' );
328
+ if (rhs ) {
329
+ rhs ++ ;
330
+ rlen = strlen (rhs );
331
+ is_glob = (2 <= rlen && !strcmp (rhs + rlen - 2 , "/*" ));
332
+ if (is_glob )
333
+ rlen -= 2 ;
334
+ rs [i ].dst = xstrndup (rhs , rlen );
318
335
}
319
- gp = strchr (sp , '*' );
320
- ep = strchr (sp , ':' );
321
- if (gp && ep && gp > ep )
322
- gp = NULL ;
323
- if (ep ) {
324
- if (ep [1 ]) {
325
- const char * glob = strchr (ep + 1 , '*' );
326
- if (!glob )
327
- gp = NULL ;
328
- if (gp )
329
- rs [i ].dst = xstrndup (ep + 1 ,
330
- glob - ep - 1 );
331
- else
332
- rs [i ].dst = xstrdup (ep + 1 );
336
+
337
+ llen = (rhs ? (rhs - lhs - 1 ) : strlen (lhs ));
338
+ if (2 <= llen && !memcmp (lhs + llen - 2 , "/*" , 2 )) {
339
+ if ((rhs && !is_glob ) || (!rhs && fetch ))
340
+ goto invalid ;
341
+ is_glob = 1 ;
342
+ llen -= 2 ;
343
+ } else if (rhs && is_glob ) {
344
+ goto invalid ;
345
+ }
346
+
347
+ rs [i ].pattern = is_glob ;
348
+ rs [i ].src = xstrndup (lhs , llen );
349
+
350
+ if (fetch ) {
351
+ /*
352
+ * LHS
353
+ * - empty is allowed; it means HEAD.
354
+ * - otherwise it must be a valid looking ref.
355
+ */
356
+ if (!* rs [i ].src )
357
+ ; /* empty is ok */
358
+ else {
359
+ st = check_ref_format (rs [i ].src );
360
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
361
+ goto invalid ;
362
+ }
363
+ /*
364
+ * RHS
365
+ * - missing is ok, and is same as empty.
366
+ * - empty is ok; it means not to store.
367
+ * - otherwise it must be a valid looking ref.
368
+ */
369
+ if (!rs [i ].dst ) {
370
+ ; /* ok */
371
+ } else if (!* rs [i ].dst ) {
372
+ ; /* ok */
373
+ } else {
374
+ st = check_ref_format (rs [i ].dst );
375
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
376
+ goto invalid ;
333
377
}
334
378
} else {
335
- ep = sp + strlen (sp );
336
- }
337
- if (gp ) {
338
- rs [i ].pattern = 1 ;
339
- ep = gp ;
379
+ /*
380
+ * LHS
381
+ * - empty is allowed; it means delete.
382
+ * - when wildcarded, it must be a valid looking ref.
383
+ * - otherwise, it must be an extended SHA-1, but
384
+ * there is no existing way to validate this.
385
+ */
386
+ if (!* rs [i ].src )
387
+ ; /* empty is ok */
388
+ else if (is_glob ) {
389
+ st = check_ref_format (rs [i ].src );
390
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
391
+ goto invalid ;
392
+ }
393
+ else
394
+ ; /* anything goes, for now */
395
+ /*
396
+ * RHS
397
+ * - missing is allowed, but LHS then must be a
398
+ * valid looking ref.
399
+ * - empty is not allowed.
400
+ * - otherwise it must be a valid looking ref.
401
+ */
402
+ if (!rs [i ].dst ) {
403
+ st = check_ref_format (rs [i ].src );
404
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
405
+ goto invalid ;
406
+ } else if (!* rs [i ].dst ) {
407
+ goto invalid ;
408
+ } else {
409
+ st = check_ref_format (rs [i ].dst );
410
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
411
+ goto invalid ;
412
+ }
340
413
}
341
- rs [i ].src = xstrndup (sp , ep - sp );
342
414
}
343
415
return rs ;
416
+
417
+ invalid :
418
+ die ("Invalid refspec '%s'" , refspec [i ]);
419
+ }
420
+
421
+ struct refspec * parse_fetch_refspec (int nr_refspec , const char * * refspec )
422
+ {
423
+ return parse_refspec_internal (nr_refspec , refspec , 1 );
424
+ }
425
+
426
+ struct refspec * parse_push_refspec (int nr_refspec , const char * * refspec )
427
+ {
428
+ return parse_refspec_internal (nr_refspec , refspec , 0 );
344
429
}
345
430
346
431
static int valid_remote_nick (const char * name )
@@ -371,8 +456,8 @@ struct remote *remote_get(const char *name)
371
456
add_url (ret , name );
372
457
if (!ret -> url )
373
458
return NULL ;
374
- ret -> fetch = parse_ref_spec (ret -> fetch_refspec_nr , ret -> fetch_refspec );
375
- ret -> push = parse_ref_spec (ret -> push_refspec_nr , ret -> push_refspec );
459
+ ret -> fetch = parse_fetch_refspec (ret -> fetch_refspec_nr , ret -> fetch_refspec );
460
+ ret -> push = parse_push_refspec (ret -> push_refspec_nr , ret -> push_refspec );
376
461
return ret ;
377
462
}
378
463
@@ -385,11 +470,11 @@ int for_each_remote(each_remote_fn fn, void *priv)
385
470
if (!r )
386
471
continue ;
387
472
if (!r -> fetch )
388
- r -> fetch = parse_ref_spec (r -> fetch_refspec_nr ,
389
- r -> fetch_refspec );
473
+ r -> fetch = parse_fetch_refspec (r -> fetch_refspec_nr ,
474
+ r -> fetch_refspec );
390
475
if (!r -> push )
391
- r -> push = parse_ref_spec (r -> push_refspec_nr ,
392
- r -> push_refspec );
476
+ r -> push = parse_push_refspec (r -> push_refspec_nr ,
477
+ r -> push_refspec );
393
478
result = fn (r , priv );
394
479
}
395
480
return result ;
@@ -455,7 +540,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)
455
540
if (!fetch -> dst )
456
541
continue ;
457
542
if (fetch -> pattern ) {
458
- if (!prefixcmp (needle , key )) {
543
+ if (!prefixcmp (needle , key ) &&
544
+ needle [strlen (key )] == '/' ) {
459
545
* result = xmalloc (strlen (value ) +
460
546
strlen (needle ) -
461
547
strlen (key ) + 1 );
@@ -695,7 +781,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
695
781
{
696
782
int i ;
697
783
for (i = 0 ; i < rs_nr ; i ++ ) {
698
- if (rs [i ].pattern && !prefixcmp (src -> name , rs [i ].src ))
784
+ if (rs [i ].pattern &&
785
+ !prefixcmp (src -> name , rs [i ].src ) &&
786
+ src -> name [strlen (rs [i ].src )] == '/' )
699
787
return rs + i ;
700
788
}
701
789
return NULL ;
@@ -710,7 +798,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
710
798
int nr_refspec , const char * * refspec , int flags )
711
799
{
712
800
struct refspec * rs =
713
- parse_ref_spec (nr_refspec , (const char * * ) refspec );
801
+ parse_push_refspec (nr_refspec , (const char * * ) refspec );
714
802
int send_all = flags & MATCH_REFS_ALL ;
715
803
int send_mirror = flags & MATCH_REFS_MIRROR ;
716
804
@@ -894,7 +982,7 @@ int get_fetch_map(const struct ref *remote_refs,
894
982
struct ref * * * tail ,
895
983
int missing_ok )
896
984
{
897
- struct ref * ref_map , * rm ;
985
+ struct ref * ref_map , * * rmp ;
898
986
899
987
if (refspec -> pattern ) {
900
988
ref_map = get_expanded_map (remote_refs , refspec );
@@ -911,10 +999,20 @@ int get_fetch_map(const struct ref *remote_refs,
911
999
}
912
1000
}
913
1001
914
- for (rm = ref_map ; rm ; rm = rm -> next ) {
915
- if (rm -> peer_ref && check_ref_format (rm -> peer_ref -> name + 5 ))
916
- die ("* refusing to create funny ref '%s' locally" ,
917
- rm -> peer_ref -> name );
1002
+ for (rmp = & ref_map ; * rmp ; ) {
1003
+ if ((* rmp )-> peer_ref ) {
1004
+ int st = check_ref_format ((* rmp )-> peer_ref -> name + 5 );
1005
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL ) {
1006
+ struct ref * ignore = * rmp ;
1007
+ error ("* Ignoring funny ref '%s' locally" ,
1008
+ (* rmp )-> peer_ref -> name );
1009
+ * rmp = (* rmp )-> next ;
1010
+ free (ignore -> peer_ref );
1011
+ free (ignore );
1012
+ continue ;
1013
+ }
1014
+ }
1015
+ rmp = & ((* rmp )-> next );
918
1016
}
919
1017
920
1018
if (ref_map )
0 commit comments