File tree Expand file tree Collapse file tree 3 files changed +58
-8
lines changed Expand file tree Collapse file tree 3 files changed +58
-8
lines changed Original file line number Diff line number Diff line change @@ -490,16 +490,24 @@ static const char *ref_rev_parse_rules[] = {
490
490
NULL
491
491
};
492
492
493
+ #define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
494
+
495
+ /*
496
+ * Is it possible that the caller meant full_name with abbrev_name?
497
+ * If so return a non-zero value to signal "yes"; the magnitude of
498
+ * the returned value gives the precedence used for disambiguation.
499
+ *
500
+ * If abbrev_name cannot mean full_name, return 0.
501
+ */
493
502
int refname_match (const char * abbrev_name , const char * full_name )
494
503
{
495
504
const char * * p ;
496
505
const int abbrev_name_len = strlen (abbrev_name );
506
+ const int num_rules = NUM_REV_PARSE_RULES ;
497
507
498
- for (p = ref_rev_parse_rules ; * p ; p ++ ) {
499
- if (!strcmp (full_name , mkpath (* p , abbrev_name_len , abbrev_name ))) {
500
- return 1 ;
501
- }
502
- }
508
+ for (p = ref_rev_parse_rules ; * p ; p ++ )
509
+ if (!strcmp (full_name , mkpath (* p , abbrev_name_len , abbrev_name )))
510
+ return & ref_rev_parse_rules [num_rules ] - p ;
503
511
504
512
return 0 ;
505
513
}
Original file line number Diff line number Diff line change @@ -1689,11 +1689,18 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
1689
1689
static const struct ref * find_ref_by_name_abbrev (const struct ref * refs , const char * name )
1690
1690
{
1691
1691
const struct ref * ref ;
1692
+ const struct ref * best_match = NULL ;
1693
+ int best_score = 0 ;
1694
+
1692
1695
for (ref = refs ; ref ; ref = ref -> next ) {
1693
- if (refname_match (name , ref -> name ))
1694
- return ref ;
1696
+ int score = refname_match (name , ref -> name );
1697
+
1698
+ if (best_score < score ) {
1699
+ best_match = ref ;
1700
+ best_score = score ;
1701
+ }
1695
1702
}
1696
- return NULL ;
1703
+ return best_match ;
1697
1704
}
1698
1705
1699
1706
struct ref * get_remote_ref (const struct ref * remote_refs , const char * name )
Original file line number Diff line number Diff line change @@ -535,6 +535,41 @@ test_expect_success "should be able to fetch with duplicate refspecs" '
535
535
)
536
536
'
537
537
538
+ test_expect_success ' LHS of refspec follows ref disambiguation rules' '
539
+ mkdir lhs-ambiguous &&
540
+ (
541
+ cd lhs-ambiguous &&
542
+ git init server &&
543
+ test_commit -C server unwanted &&
544
+ test_commit -C server wanted &&
545
+
546
+ git init client &&
547
+
548
+ # Check a name coming after "refs" alphabetically ...
549
+ git -C server update-ref refs/heads/s wanted &&
550
+ git -C server update-ref refs/heads/refs/heads/s unwanted &&
551
+ git -C client fetch ../server +refs/heads/s:refs/heads/checkthis &&
552
+ git -C server rev-parse wanted >expect &&
553
+ git -C client rev-parse checkthis >actual &&
554
+ test_cmp expect actual &&
555
+
556
+ # ... and one before.
557
+ git -C server update-ref refs/heads/q wanted &&
558
+ git -C server update-ref refs/heads/refs/heads/q unwanted &&
559
+ git -C client fetch ../server +refs/heads/q:refs/heads/checkthis &&
560
+ git -C server rev-parse wanted >expect &&
561
+ git -C client rev-parse checkthis >actual &&
562
+ test_cmp expect actual &&
563
+
564
+ # Tags are preferred over branches like refs/{heads,tags}/*
565
+ git -C server update-ref refs/tags/t wanted &&
566
+ git -C server update-ref refs/heads/t unwanted &&
567
+ git -C client fetch ../server +t:refs/heads/checkthis &&
568
+ git -C server rev-parse wanted >expect &&
569
+ git -C client rev-parse checkthis >actual
570
+ )
571
+ '
572
+
538
573
# configured prune tests
539
574
540
575
set_config_tristate () {
You can’t perform that action at this time.
0 commit comments