@@ -84,27 +84,17 @@ impl CommitSpec {
8484 }
8585
8686 pub fn reference ( & self ) -> GitReference < ' _ > {
87- // Only treat as a commit OID if it's a full 40-character SHA
88- if self . rev . len ( ) == 40 && self . rev . chars ( ) . all ( |c| c. is_ascii_hexdigit ( ) ) {
89- if let Ok ( oid) = git2:: Oid :: from_str ( & self . rev ) {
90- GitReference :: Commit ( oid)
91- } else {
92- GitReference :: Symbolic ( & self . rev )
93- }
87+ if let Ok ( oid) = git2:: Oid :: from_str ( & self . rev ) {
88+ GitReference :: Commit ( oid)
9489 } else {
9590 GitReference :: Symbolic ( & self . rev )
9691 }
9792 }
9893
9994 pub fn prev_reference ( & self ) -> Option < GitReference < ' _ > > {
10095 self . prev_rev . as_ref ( ) . map ( |rev| {
101- // Only treat as a commit OID if it's a full 40-character SHA
102- if rev. len ( ) == 40 && rev. chars ( ) . all ( |c| c. is_ascii_hexdigit ( ) ) {
103- if let Ok ( oid) = git2:: Oid :: from_str ( rev) {
104- GitReference :: Commit ( oid)
105- } else {
106- GitReference :: Symbolic ( rev)
107- }
96+ if let Ok ( oid) = git2:: Oid :: from_str ( rev) {
97+ GitReference :: Commit ( oid)
10898 } else {
10999 GitReference :: Symbolic ( rev)
110100 }
@@ -449,6 +439,26 @@ fn find_matching_submodule(
449439 Ok ( None )
450440}
451441
442+ /// Helper function to determine which SHA to use for the API
443+ /// Returns the original partial SHA if it looks like a partial SHA that would be padded,
444+ /// otherwise returns the resolved SHA
445+ fn get_api_sha ( original : & str , resolved : & str ) -> String {
446+ // Check if original looks like a partial SHA (valid hex, 4-39 chars)
447+ let is_partial = original. len ( ) >= 4 && original. len ( ) < 40 && original. chars ( ) . all ( |c| c. is_ascii_hexdigit ( ) ) ;
448+
449+ // Check if this looks like a padded partial SHA
450+ // The resolved SHA should start with the original and be padded with zeros
451+ let is_padded = resolved. len ( ) == 40
452+ && resolved. starts_with ( original)
453+ && resolved[ original. len ( ) ..] . chars ( ) . all ( |c| c == '0' ) ;
454+
455+ if is_padded && is_partial {
456+ original. to_owned ( ) // Use original partial SHA
457+ } else {
458+ resolved. to_owned ( ) // Use resolved SHA
459+ }
460+ }
461+
452462fn find_matching_revs (
453463 spec : & CommitSpec ,
454464 repos : & [ Repo ] ,
@@ -466,21 +476,21 @@ fn find_matching_revs(
466476 )
467477 }
468478
469- let rev = if let Some ( rev ) = find_matching_rev (
479+ let rev = if let Some ( resolved_sha ) = find_matching_rev (
470480 spec. reference ( ) ,
471481 spec,
472482 repos,
473483 disable_discovery,
474484 remote_name. clone ( ) ,
475485 ) ? {
476- rev
486+ get_api_sha ( & spec . rev , & resolved_sha )
477487 } else {
478488 return Err ( error ( spec. reference ( ) , & spec. repo ) ) ;
479489 } ;
480490
481491 let prev_rev = if let Some ( rev) = spec. prev_reference ( ) {
482- if let Some ( rv ) = find_matching_rev ( rev, spec, repos, disable_discovery, remote_name) ? {
483- Some ( rv )
492+ if let Some ( resolved_sha ) = find_matching_rev ( rev, spec, repos, disable_discovery, remote_name) ? {
493+ Some ( get_api_sha ( spec . prev_rev . as_ref ( ) . unwrap ( ) , & resolved_sha ) )
484494 } else {
485495 return Err ( error ( rev, & spec. repo ) ) ;
486496 }
@@ -1311,71 +1321,6 @@ fn test_git_repo_head_ref() {
13111321 ) ;
13121322}
13131323
1314- #[ test]
1315- fn test_partial_sha_resolution_with_real_git ( ) {
1316- let dir = git_initialize_repo ( ) ;
1317-
1318- git_create_commit ( dir. path ( ) , "test.txt" , b"test content" , "test commit" ) ;
1319-
1320- // Get the full and short SHA
1321- let full_sha_output = std:: process:: Command :: new ( "git" )
1322- . args ( [ "rev-parse" , "HEAD" ] )
1323- . current_dir ( dir. path ( ) )
1324- . output ( )
1325- . expect ( "Failed to get full SHA" ) ;
1326- let full_sha = String :: from_utf8 ( full_sha_output. stdout )
1327- . expect ( "Invalid UTF-8" )
1328- . trim ( )
1329- . to_owned ( ) ;
1330- let short_sha_output = std:: process:: Command :: new ( "git" )
1331- . args ( [ "rev-parse" , "--short" , "HEAD" ] )
1332- . current_dir ( dir. path ( ) )
1333- . output ( )
1334- . expect ( "Failed to get short SHA" ) ;
1335- let short_sha = String :: from_utf8 ( short_sha_output. stdout )
1336- . expect ( "Invalid UTF-8" )
1337- . trim ( )
1338- . to_owned ( ) ;
1339-
1340- let spec = CommitSpec {
1341- repo : "test-repo" . to_owned ( ) ,
1342- path : Some ( dir. path ( ) . to_path_buf ( ) ) ,
1343- rev : short_sha. clone ( ) ,
1344- prev_rev : None ,
1345- } ;
1346-
1347- match spec. reference ( ) {
1348- GitReference :: Symbolic ( s) => {
1349- assert_eq ! ( s, short_sha) ;
1350- }
1351- GitReference :: Commit ( _) => {
1352- panic ! ( "Partial SHA should be treated as symbolic reference" )
1353- }
1354- }
1355-
1356- let reference = spec. reference ( ) ;
1357- let repos = [ Repo {
1358- id : String :: from ( "1" ) ,
1359- name : String :: from ( "test-repo" ) ,
1360- url : Some ( String :: from ( "https://github.com/test/test-repo" ) ) ,
1361- provider : RepoProvider {
1362- id : String :: from ( "integrations:github" ) ,
1363- name : String :: from ( "GitHub" ) ,
1364- } ,
1365- status : String :: from ( "active" ) ,
1366- date_created : chrono:: Utc :: now ( ) ,
1367- } ] ;
1368-
1369- let resolved_sha = find_matching_rev ( reference, & spec, & repos, false , None )
1370- . expect ( "Failed to resolve partial SHA" )
1371- . expect ( "Partial SHA should resolve to a commit" ) ;
1372-
1373- assert_eq ! (
1374- resolved_sha, full_sha,
1375- "Partial SHA {short_sha} should resolve to full SHA {full_sha}, but got {resolved_sha}"
1376- ) ;
1377- }
1378-
13791324#[ cfg( test) ]
13801325mod tests {
13811326 use super :: * ;
@@ -1396,132 +1341,4 @@ mod tests {
13961341 std:: env:: remove_var ( "GITHUB_EVENT_NAME" ) ;
13971342 std:: env:: remove_var ( "GITHUB_REF" ) ;
13981343 }
1399-
1400- #[ test]
1401- fn test_commit_spec_reference_partial_sha ( ) {
1402- let spec = CommitSpec {
1403- repo : "test-repo" . to_owned ( ) ,
1404- path : None ,
1405- rev : "f915d32" . to_owned ( ) ,
1406- prev_rev : None ,
1407- } ;
1408-
1409- match spec. reference ( ) {
1410- GitReference :: Symbolic ( s) => assert_eq ! ( s, "f915d32" ) ,
1411- GitReference :: Commit ( _) => {
1412- panic ! ( "Partial SHA should be treated as symbolic reference" )
1413- }
1414- }
1415- }
1416-
1417- #[ test]
1418- fn test_commit_spec_reference_full_sha ( ) {
1419- let spec = CommitSpec {
1420- repo : "test-repo" . to_owned ( ) ,
1421- path : None ,
1422- rev : "f915d32000000000000000000000000000000000" . to_owned ( ) ,
1423- prev_rev : None ,
1424- } ;
1425-
1426- match spec. reference ( ) {
1427- GitReference :: Commit ( oid) => {
1428- assert_eq ! ( oid. to_string( ) , "f915d32000000000000000000000000000000000" ) ;
1429- }
1430- GitReference :: Symbolic ( _) => panic ! ( "Full SHA should be treated as commit OID" ) ,
1431- }
1432- }
1433-
1434- #[ test]
1435- fn test_commit_spec_reference_symbolic_refs ( ) {
1436- let test_cases = vec ! [
1437- ( "main" , "branch name" ) ,
1438- ( "v1.0.0" , "tag name" ) ,
1439- ( "HEAD~1" , "relative reference" ) ,
1440- ( "f915d32g" , "invalid hex" ) ,
1441- ] ;
1442-
1443- for ( rev, description) in test_cases {
1444- let spec = CommitSpec {
1445- repo : "test-repo" . to_owned ( ) ,
1446- path : None ,
1447- rev : rev. to_owned ( ) ,
1448- prev_rev : None ,
1449- } ;
1450-
1451- match spec. reference ( ) {
1452- GitReference :: Symbolic ( s) => assert_eq ! (
1453- s, rev,
1454- "Failed for {description}: expected '{rev}', got '{s}'"
1455- ) ,
1456- GitReference :: Commit ( _) => {
1457- panic ! ( "{description} should be treated as symbolic reference" )
1458- }
1459- }
1460- }
1461- }
1462-
1463- #[ test]
1464- fn test_commit_spec_prev_reference_partial_sha ( ) {
1465- let spec = CommitSpec {
1466- repo : "test-repo" . to_owned ( ) ,
1467- path : None ,
1468- rev : "HEAD" . to_owned ( ) ,
1469- prev_rev : Some ( "4ebad56" . to_owned ( ) ) ,
1470- } ;
1471-
1472- match spec. prev_reference ( ) . unwrap ( ) {
1473- GitReference :: Symbolic ( s) => assert_eq ! ( s, "4ebad56" ) ,
1474- GitReference :: Commit ( _) => {
1475- panic ! ( "Partial SHA in prev_rev should be treated as symbolic reference" )
1476- }
1477- }
1478- }
1479-
1480- #[ test]
1481- fn test_commit_spec_prev_reference_full_sha ( ) {
1482- let spec = CommitSpec {
1483- repo : "test-repo" . to_owned ( ) ,
1484- path : None ,
1485- rev : "HEAD" . to_owned ( ) ,
1486- prev_rev : Some ( "f915d32000000000000000000000000000000000" . to_owned ( ) ) ,
1487- } ;
1488-
1489- match spec. prev_reference ( ) . unwrap ( ) {
1490- GitReference :: Commit ( oid) => {
1491- assert_eq ! ( oid. to_string( ) , "f915d32000000000000000000000000000000000" ) ;
1492- }
1493- GitReference :: Symbolic ( _) => {
1494- panic ! ( "Full SHA in prev_rev should be treated as commit OID" )
1495- }
1496- }
1497- }
1498-
1499- #[ test]
1500- fn test_commit_spec_prev_reference_symbolic_refs ( ) {
1501- let test_cases = vec ! [
1502- ( "main" , "branch name" ) ,
1503- ( "v1.0.0" , "tag name" ) ,
1504- ( "HEAD~1" , "relative reference" ) ,
1505- ( "f915d32g" , "invalid hex" ) ,
1506- ] ;
1507-
1508- for ( prev_rev, description) in test_cases {
1509- let spec = CommitSpec {
1510- repo : "test-repo" . to_owned ( ) ,
1511- path : None ,
1512- rev : "HEAD" . to_owned ( ) ,
1513- prev_rev : Some ( prev_rev. to_owned ( ) ) ,
1514- } ;
1515-
1516- match spec. prev_reference ( ) . unwrap ( ) {
1517- GitReference :: Symbolic ( s) => assert_eq ! (
1518- s, prev_rev,
1519- "Failed for {description}: expected '{prev_rev}', got '{s}'"
1520- ) ,
1521- GitReference :: Commit ( _) => {
1522- panic ! ( "{description} in prev_rev should be treated as symbolic reference" )
1523- }
1524- }
1525- }
1526- }
15271344}
0 commit comments