@@ -317,8 +317,6 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev)
317
317
static char * config_repo ;
318
318
static char * config_remote ;
319
319
static const char * start_ref ;
320
- static int start_len ;
321
- static int base_len ;
322
320
323
321
static int get_remote_branch_name (const char * value )
324
322
{
@@ -334,26 +332,41 @@ static int get_remote_branch_name(const char *value)
334
332
335
333
end = value + strlen (value );
336
334
337
- /* Try an exact match first. */
335
+ /*
336
+ * Try an exact match first. I.e. handle the case where the
337
+ * value is "$anything:refs/foo/bar/baz" and start_ref is exactly
338
+ * "refs/foo/bar/baz". Then the name at the remote is $anything.
339
+ */
338
340
if (!strcmp (colon + 1 , start_ref )) {
339
- /* Truncate the value before the colon. */
341
+ /* Truncate the value before the colon. */
340
342
nfasprintf (& config_repo , "%.*s" , colon - value , value );
341
343
return 1 ;
342
344
}
343
345
344
- /* Try with a wildcard match now. */
345
- if (end - value > 2 && end [-2 ] == '/' && end [-1 ] == '*' &&
346
- colon - value > 2 && colon [-2 ] == '/' && colon [-1 ] == '*' &&
347
- (end - 2 ) - (colon + 1 ) == base_len &&
348
- !strncmp (colon + 1 , start_ref , base_len )) {
349
- /* Replace the star with the remote branch name. */
350
- nfasprintf (& config_repo , "%.*s%s" ,
351
- (colon - 2 ) - value , value ,
352
- start_ref + base_len );
353
- return 1 ;
354
- }
346
+ /*
347
+ * Is this a wildcard match?
348
+ */
349
+ if ((end - 2 <= value ) || end [-2 ] != '/' || end [-1 ] != '*' ||
350
+ (colon - 2 <= value ) || colon [-2 ] != '/' || colon [-1 ] != '*' )
351
+ return 0 ;
355
352
356
- return 0 ;
353
+ /*
354
+ * Value is "refs/foo/bar/<asterisk>:refs/baz/boa/<asterisk>"
355
+ * and start_ref begins with "refs/baz/boa/"; the name at the
356
+ * remote is refs/foo/bar/ with the remaining part of the
357
+ * start_ref. The length of the prefix on the RHS is (end -
358
+ * colon - 2), including the slash immediately before the
359
+ * asterisk.
360
+ */
361
+ if ((strlen (start_ref ) < end - colon - 2 ) ||
362
+ memcmp (start_ref , colon + 1 , end - colon - 2 ))
363
+ return 0 ; /* does not match prefix */
364
+
365
+ /* Replace the asterisk with the remote branch name. */
366
+ nfasprintf (& config_repo , "%.*s%s" ,
367
+ (colon - 1 ) - value , value ,
368
+ start_ref + (end - colon - 2 ));
369
+ return 1 ;
357
370
}
358
371
359
372
static int get_remote_config (const char * key , const char * value )
@@ -363,10 +376,12 @@ static int get_remote_config(const char *key, const char *value)
363
376
return 0 ;
364
377
365
378
var = strrchr (key , '.' );
366
- if (var == key + 6 )
379
+ if (var == key + 6 || strcmp ( var , ".fetch" ) )
367
380
return 0 ;
368
-
369
- if (!strcmp (var , ".fetch" ) && get_remote_branch_name (value ))
381
+ /*
382
+ * Ok, we are looking at key == "remote.$foo.fetch";
383
+ */
384
+ if (get_remote_branch_name (value ))
370
385
nfasprintf (& config_remote , "%.*s" , var - (key + 7 ), key + 7 );
371
386
372
387
return 0 ;
@@ -392,14 +407,14 @@ static void set_branch_merge(const char *name, const char *config_remote,
392
407
393
408
static void set_branch_defaults (const char * name , const char * real_ref )
394
409
{
395
- const char * slash = strrchr (real_ref , '/' );
396
-
397
- if (!slash )
398
- return ;
399
-
410
+ /*
411
+ * name is the name of new branch under refs/heads;
412
+ * real_ref is typically refs/remotes/$foo/$bar, where
413
+ * $foo is the remote name (there typically are no slashes)
414
+ * and $bar is the branch name we map from the remote
415
+ * (it could have slashes).
416
+ */
400
417
start_ref = real_ref ;
401
- start_len = strlen (real_ref );
402
- base_len = slash - real_ref ;
403
418
git_config (get_remote_config );
404
419
if (!config_repo && !config_remote &&
405
420
!prefixcmp (real_ref , "refs/heads/" )) {
0 commit comments