@@ -171,7 +171,7 @@ static void read_branches_file(struct remote *remote)
171171{
172172 const char * slash = strchr (remote -> name , '/' );
173173 char * frag ;
174- char * branch ;
174+ struct strbuf branch ;
175175 int n = slash ? slash - remote -> name : 1000 ;
176176 FILE * f = fopen (git_path ("branches/%.*s" , n , remote -> name ), "r" );
177177 char * s , * p ;
@@ -197,17 +197,33 @@ static void read_branches_file(struct remote *remote)
197197 strcpy (p , s );
198198 if (slash )
199199 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 );
200213 frag = strchr (p , '#' );
201214 if (frag ) {
202215 * (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 );
206221 } else {
207- branch = "refs/heads/master" ;
222+ strbuf_reset (& branch );
223+ strbuf_addstr (& branch , "HEAD:" );
208224 }
209225 add_url (remote , p );
210- add_fetch_refspec (remote , branch );
226+ add_fetch_refspec (remote , strbuf_detach ( & branch , 0 ) );
211227 remote -> fetch_tags = 1 ; /* always auto-follow */
212228}
213229
@@ -305,42 +321,127 @@ static void read_config(void)
305321 git_config (handle_config );
306322}
307323
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 )
309325{
310326 int i ;
327+ int st ;
311328 struct refspec * rs = xcalloc (sizeof (* rs ), nr_refspec );
329+
312330 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 == '+' ) {
316339 rs [i ].force = 1 ;
317- sp ++ ;
340+ lhs ++ ;
318341 }
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 ;
333393 }
334394 } 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+ }
340429 }
341- rs [i ].src = xstrndup (sp , ep - sp );
342430 }
343431 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 );
344445}
345446
346447static int valid_remote_nick (const char * name )
@@ -371,8 +472,8 @@ struct remote *remote_get(const char *name)
371472 add_url (ret , name );
372473 if (!ret -> url )
373474 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 );
376477 return ret ;
377478}
378479
@@ -385,11 +486,11 @@ int for_each_remote(each_remote_fn fn, void *priv)
385486 if (!r )
386487 continue ;
387488 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 );
390491 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 );
393494 result = fn (r , priv );
394495 }
395496 return result ;
@@ -455,7 +556,8 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec)
455556 if (!fetch -> dst )
456557 continue ;
457558 if (fetch -> pattern ) {
458- if (!prefixcmp (needle , key )) {
559+ if (!prefixcmp (needle , key ) &&
560+ needle [strlen (key )] == '/' ) {
459561 * result = xmalloc (strlen (value ) +
460562 strlen (needle ) -
461563 strlen (key ) + 1 );
@@ -695,7 +797,9 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
695797{
696798 int i ;
697799 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 )] == '/' )
699803 return rs + i ;
700804 }
701805 return NULL ;
@@ -710,7 +814,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
710814 int nr_refspec , const char * * refspec , int flags )
711815{
712816 struct refspec * rs =
713- parse_ref_spec (nr_refspec , (const char * * ) refspec );
817+ parse_push_refspec (nr_refspec , (const char * * ) refspec );
714818 int send_all = flags & MATCH_REFS_ALL ;
715819 int send_mirror = flags & MATCH_REFS_MIRROR ;
716820
@@ -894,7 +998,7 @@ int get_fetch_map(const struct ref *remote_refs,
894998 struct ref * * * tail ,
895999 int missing_ok )
8961000{
897- struct ref * ref_map , * rm ;
1001+ struct ref * ref_map , * * rmp ;
8981002
8991003 if (refspec -> pattern ) {
9001004 ref_map = get_expanded_map (remote_refs , refspec );
@@ -911,10 +1015,20 @@ int get_fetch_map(const struct ref *remote_refs,
9111015 }
9121016 }
9131017
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 );
9181032 }
9191033
9201034 if (ref_map )
0 commit comments