@@ -171,7 +171,7 @@ static void read_branches_file(struct remote *remote)
171
171
{
172
172
const char * slash = strchr (remote -> name , '/' );
173
173
char * frag ;
174
- char * branch ;
174
+ struct strbuf branch ;
175
175
int n = slash ? slash - remote -> name : 1000 ;
176
176
FILE * f = fopen (git_path ("branches/%.*s" , n , remote -> name ), "r" );
177
177
char * s , * p ;
@@ -197,17 +197,33 @@ static void read_branches_file(struct remote *remote)
197
197
strcpy (p , s );
198
198
if (slash )
199
199
strcat (p , slash );
200
+
201
+ /*
202
+ * With "slash", e.g. "git fetch jgarzik/netdev-2.6" when
203
+ * reading from $GIT_DIR/branches/jgarzik fetches "HEAD" from
204
+ * the partial URL obtained from the branches file plus
205
+ * "/netdev-2.6" and does not store it in any tracking ref.
206
+ * #branch specifier in the file is ignored.
207
+ *
208
+ * Otherwise, the branches file would have URL and optionally
209
+ * #branch specified. The "master" (or specified) branch is
210
+ * fetched and stored in the local branch of the same name.
211
+ */
212
+ strbuf_init (& branch , 0 );
200
213
frag = strchr (p , '#' );
201
214
if (frag ) {
202
215
* (frag ++ ) = '\0' ;
203
- branch = xmalloc (strlen (frag ) + 12 );
204
- strcpy (branch , "refs/heads/" );
205
- strcat (branch , frag );
216
+ strbuf_addf (& branch , "refs/heads/%s" , frag );
217
+ } else
218
+ strbuf_addstr (& branch , "refs/heads/master" );
219
+ if (!slash ) {
220
+ strbuf_addf (& branch , ":refs/heads/%s" , remote -> name );
206
221
} else {
207
- branch = "refs/heads/master" ;
222
+ strbuf_reset (& branch );
223
+ strbuf_addstr (& branch , "HEAD:" );
208
224
}
209
225
add_url (remote , p );
210
- add_fetch_refspec (remote , branch );
226
+ add_fetch_refspec (remote , strbuf_detach ( & branch , 0 ) );
211
227
remote -> fetch_tags = 1 ; /* always auto-follow */
212
228
}
213
229
@@ -305,42 +321,127 @@ static void read_config(void)
305
321
git_config (handle_config );
306
322
}
307
323
308
- struct refspec * parse_ref_spec (int nr_refspec , const char * * refspec )
324
+ static struct refspec * parse_refspec_internal (int nr_refspec , const char * * refspec , int fetch )
309
325
{
310
326
int i ;
327
+ int st ;
311
328
struct refspec * rs = xcalloc (sizeof (* rs ), nr_refspec );
329
+
312
330
for (i = 0 ; i < nr_refspec ; i ++ ) {
313
- const char * sp , * ep , * gp ;
314
- sp = refspec [i ];
315
- if (* sp == '+' ) {
331
+ size_t llen , rlen ;
332
+ int is_glob ;
333
+ const char * lhs , * rhs ;
334
+
335
+ llen = rlen = is_glob = 0 ;
336
+
337
+ lhs = refspec [i ];
338
+ if (* lhs == '+' ) {
316
339
rs [i ].force = 1 ;
317
- sp ++ ;
340
+ lhs ++ ;
318
341
}
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 );
342
+
343
+ rhs = strrchr (lhs , ':' );
344
+ if (rhs ) {
345
+ rhs ++ ;
346
+ rlen = strlen (rhs );
347
+ is_glob = (2 <= rlen && !strcmp (rhs + rlen - 2 , "/*" ));
348
+ if (is_glob )
349
+ rlen -= 2 ;
350
+ rs [i ].dst = xstrndup (rhs , rlen );
351
+ }
352
+
353
+ llen = (rhs ? (rhs - lhs - 1 ) : strlen (lhs ));
354
+ if (2 <= llen && !memcmp (lhs + llen - 2 , "/*" , 2 )) {
355
+ if ((rhs && !is_glob ) || (!rhs && fetch ))
356
+ goto invalid ;
357
+ is_glob = 1 ;
358
+ llen -= 2 ;
359
+ } else if (rhs && is_glob ) {
360
+ goto invalid ;
361
+ }
362
+
363
+ rs [i ].pattern = is_glob ;
364
+ rs [i ].src = xstrndup (lhs , llen );
365
+
366
+ if (fetch ) {
367
+ /*
368
+ * LHS
369
+ * - empty is allowed; it means HEAD.
370
+ * - otherwise it must be a valid looking ref.
371
+ */
372
+ if (!* rs [i ].src )
373
+ ; /* empty is ok */
374
+ else {
375
+ st = check_ref_format (rs [i ].src );
376
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
377
+ goto invalid ;
378
+ }
379
+ /*
380
+ * RHS
381
+ * - missing is ok, and is same as empty.
382
+ * - empty is ok; it means not to store.
383
+ * - otherwise it must be a valid looking ref.
384
+ */
385
+ if (!rs [i ].dst ) {
386
+ ; /* ok */
387
+ } else if (!* rs [i ].dst ) {
388
+ ; /* ok */
389
+ } else {
390
+ st = check_ref_format (rs [i ].dst );
391
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
392
+ goto invalid ;
333
393
}
334
394
} else {
335
- ep = sp + strlen (sp );
336
- }
337
- if (gp ) {
338
- rs [i ].pattern = 1 ;
339
- ep = gp ;
395
+ /*
396
+ * LHS
397
+ * - empty is allowed; it means delete.
398
+ * - when wildcarded, it must be a valid looking ref.
399
+ * - otherwise, it must be an extended SHA-1, but
400
+ * there is no existing way to validate this.
401
+ */
402
+ if (!* rs [i ].src )
403
+ ; /* empty is ok */
404
+ else if (is_glob ) {
405
+ st = check_ref_format (rs [i ].src );
406
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
407
+ goto invalid ;
408
+ }
409
+ else
410
+ ; /* anything goes, for now */
411
+ /*
412
+ * RHS
413
+ * - missing is allowed, but LHS then must be a
414
+ * valid looking ref.
415
+ * - empty is not allowed.
416
+ * - otherwise it must be a valid looking ref.
417
+ */
418
+ if (!rs [i ].dst ) {
419
+ st = check_ref_format (rs [i ].src );
420
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
421
+ goto invalid ;
422
+ } else if (!* rs [i ].dst ) {
423
+ goto invalid ;
424
+ } else {
425
+ st = check_ref_format (rs [i ].dst );
426
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL )
427
+ goto invalid ;
428
+ }
340
429
}
341
- rs [i ].src = xstrndup (sp , ep - sp );
342
430
}
343
431
return rs ;
432
+
433
+ invalid :
434
+ die ("Invalid refspec '%s'" , refspec [i ]);
435
+ }
436
+
437
+ struct refspec * parse_fetch_refspec (int nr_refspec , const char * * refspec )
438
+ {
439
+ return parse_refspec_internal (nr_refspec , refspec , 1 );
440
+ }
441
+
442
+ struct refspec * parse_push_refspec (int nr_refspec , const char * * refspec )
443
+ {
444
+ return parse_refspec_internal (nr_refspec , refspec , 0 );
344
445
}
345
446
346
447
static int valid_remote_nick (const char * name )
@@ -371,8 +472,8 @@ struct remote *remote_get(const char *name)
371
472
add_url (ret , name );
372
473
if (!ret -> url )
373
474
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 );
475
+ ret -> fetch = parse_fetch_refspec (ret -> fetch_refspec_nr , ret -> fetch_refspec );
476
+ ret -> push = parse_push_refspec (ret -> push_refspec_nr , ret -> push_refspec );
376
477
return ret ;
377
478
}
378
479
@@ -385,11 +486,11 @@ int for_each_remote(each_remote_fn fn, void *priv)
385
486
if (!r )
386
487
continue ;
387
488
if (!r -> fetch )
388
- r -> fetch = parse_ref_spec (r -> fetch_refspec_nr ,
389
- r -> fetch_refspec );
489
+ r -> fetch = parse_fetch_refspec (r -> fetch_refspec_nr ,
490
+ r -> fetch_refspec );
390
491
if (!r -> push )
391
- r -> push = parse_ref_spec (r -> push_refspec_nr ,
392
- r -> push_refspec );
492
+ r -> push = parse_push_refspec (r -> push_refspec_nr ,
493
+ r -> push_refspec );
393
494
result = fn (r , priv );
394
495
}
395
496
return result ;
@@ -455,7 +556,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)
455
556
if (!fetch -> dst )
456
557
continue ;
457
558
if (fetch -> pattern ) {
458
- if (!prefixcmp (needle , key )) {
559
+ if (!prefixcmp (needle , key ) &&
560
+ needle [strlen (key )] == '/' ) {
459
561
* result = xmalloc (strlen (value ) +
460
562
strlen (needle ) -
461
563
strlen (key ) + 1 );
@@ -695,7 +797,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
695
797
{
696
798
int i ;
697
799
for (i = 0 ; i < rs_nr ; i ++ ) {
698
- if (rs [i ].pattern && !prefixcmp (src -> name , rs [i ].src ))
800
+ if (rs [i ].pattern &&
801
+ !prefixcmp (src -> name , rs [i ].src ) &&
802
+ src -> name [strlen (rs [i ].src )] == '/' )
699
803
return rs + i ;
700
804
}
701
805
return NULL ;
@@ -710,7 +814,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
710
814
int nr_refspec , const char * * refspec , int flags )
711
815
{
712
816
struct refspec * rs =
713
- parse_ref_spec (nr_refspec , (const char * * ) refspec );
817
+ parse_push_refspec (nr_refspec , (const char * * ) refspec );
714
818
int send_all = flags & MATCH_REFS_ALL ;
715
819
int send_mirror = flags & MATCH_REFS_MIRROR ;
716
820
@@ -894,7 +998,7 @@ int get_fetch_map(const struct ref *remote_refs,
894
998
struct ref * * * tail ,
895
999
int missing_ok )
896
1000
{
897
- struct ref * ref_map , * rm ;
1001
+ struct ref * ref_map , * * rmp ;
898
1002
899
1003
if (refspec -> pattern ) {
900
1004
ref_map = get_expanded_map (remote_refs , refspec );
@@ -911,10 +1015,20 @@ int get_fetch_map(const struct ref *remote_refs,
911
1015
}
912
1016
}
913
1017
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 );
1018
+ for (rmp = & ref_map ; * rmp ; ) {
1019
+ if ((* rmp )-> peer_ref ) {
1020
+ int st = check_ref_format ((* rmp )-> peer_ref -> name + 5 );
1021
+ if (st && st != CHECK_REF_FORMAT_ONELEVEL ) {
1022
+ struct ref * ignore = * rmp ;
1023
+ error ("* Ignoring funny ref '%s' locally" ,
1024
+ (* rmp )-> peer_ref -> name );
1025
+ * rmp = (* rmp )-> next ;
1026
+ free (ignore -> peer_ref );
1027
+ free (ignore );
1028
+ continue ;
1029
+ }
1030
+ }
1031
+ rmp = & ((* rmp )-> next );
918
1032
}
919
1033
920
1034
if (ref_map )
0 commit comments