@@ -448,25 +448,25 @@ pub(crate) fn matching_legacy_profile_layouts(
448448 profile_root : & Path ,
449449 excluded_project_id : Option < & str > ,
450450) -> Result < ( Vec < StoreLayout > , bool ) > {
451- matching_legacy_profile_layouts_with_git_resolver (
451+ matching_legacy_profile_layouts_with_git_identity_resolver (
452452 project_root,
453453 profile_root,
454454 excluded_project_id,
455455 crate :: worktree:: is_detached_linked_worktree,
456- crate :: worktree:: git_common_dir ,
456+ crate :: worktree:: git_repo_identity_outcome ,
457457 )
458458}
459459
460- fn matching_legacy_profile_layouts_with_git_resolver < D , G > (
460+ fn matching_legacy_profile_layouts_with_git_identity_resolver < D , G > (
461461 project_root : & Path ,
462462 profile_root : & Path ,
463463 excluded_project_id : Option < & str > ,
464464 mut is_detached_linked_worktree : D ,
465- mut git_common_dir : G ,
465+ mut git_identity : G ,
466466) -> Result < ( Vec < StoreLayout > , bool ) >
467467where
468468 D : FnMut ( & Path ) -> bool ,
469- G : FnMut ( & Path ) -> Option < PathBuf > ,
469+ G : FnMut ( & Path ) -> crate :: worktree :: GitRepoIdentityOutcome ,
470470{
471471 let projects_root = profile_root. join ( "projects" ) ;
472472 let Ok ( entries) = fs:: read_dir ( & projects_root) else {
@@ -507,7 +507,13 @@ where
507507 selected_manifest_matches_exact_root && exact_manifests. is_empty ( ) ;
508508 let matching_manifests = if exact_manifests. is_empty ( ) {
509509 let project_git_common_dir = ( !is_detached_linked_worktree ( project_root) )
510- . then ( || git_common_dir ( project_root) )
510+ . then ( || match git_identity ( project_root) {
511+ crate :: worktree:: GitRepoIdentityOutcome :: Resolved ( identity) => {
512+ Some ( identity. common_dir )
513+ }
514+ crate :: worktree:: GitRepoIdentityOutcome :: Unknown
515+ | crate :: worktree:: GitRepoIdentityOutcome :: NotFound => None ,
516+ } )
511517 . flatten ( ) ;
512518 let mut legacy_git_common_dirs = HashMap :: < PathBuf , Option < PathBuf > > :: new ( ) ;
513519 non_exact_manifests
@@ -520,7 +526,13 @@ where
520526 manifest
521527 . project_root
522528 . is_dir ( )
523- . then ( || git_common_dir ( & manifest. project_root ) )
529+ . then ( || match git_identity ( & manifest. project_root ) {
530+ crate :: worktree:: GitRepoIdentityOutcome :: Resolved ( identity) => {
531+ Some ( identity. common_dir )
532+ }
533+ crate :: worktree:: GitRepoIdentityOutcome :: Unknown
534+ | crate :: worktree:: GitRepoIdentityOutcome :: NotFound => None ,
535+ } )
524536 . flatten ( )
525537 } )
526538 . as_deref ( )
@@ -1314,6 +1326,67 @@ mod tests {
13141326 use std:: cell:: RefCell ;
13151327 use std:: sync:: { Arc , Barrier } ;
13161328
1329+ #[ test]
1330+ fn legacy_shared_git_probe_skips_timeout_and_unresolvable_roots ( ) {
1331+ let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
1332+ let project_root = dir. path ( ) . join ( "repo" ) ;
1333+ let legacy_root = dir. path ( ) . join ( "legacy" ) ;
1334+ let profile_root = dir. path ( ) . join ( "profile" ) ;
1335+ let data_root = profile_root. join ( "projects" ) . join ( "proj_legacy" ) ;
1336+ for root in [ & project_root, & legacy_root, & data_root] {
1337+ fs:: create_dir_all ( root) . unwrap ( ) ;
1338+ }
1339+ write_store_manifest_to_path (
1340+ & data_root. join ( STORE_MANIFEST_FILENAME ) ,
1341+ & StoreManifest {
1342+ schema_version : STORE_MANIFEST_SCHEMA_VERSION ,
1343+ project_id : Some ( "proj_legacy" . to_string ( ) ) ,
1344+ store_kind : StoreKind :: CodeProject ,
1345+ storage_mode : StorageMode :: ProfileSharded ,
1346+ project_root : legacy_root. clone ( ) ,
1347+ data_root,
1348+ graph_db_relpath : "tracedecay.db" . into ( ) ,
1349+ sessions_db_relpath : "sessions.db" . into ( ) ,
1350+ branch_meta_relpath : "branch-meta.json" . into ( ) ,
1351+ } ,
1352+ )
1353+ . unwrap ( ) ;
1354+
1355+ let ( layouts, _) = matching_legacy_profile_layouts_with_git_identity_resolver (
1356+ & project_root,
1357+ & profile_root,
1358+ None ,
1359+ |_| false ,
1360+ |_| crate :: worktree:: GitRepoIdentityOutcome :: Unknown ,
1361+ )
1362+ . unwrap ( ) ;
1363+ assert ! ( layouts. is_empty( ) , "a timed-out current root cannot match" ) ;
1364+
1365+ let ( layouts, _) = matching_legacy_profile_layouts_with_git_identity_resolver (
1366+ & project_root,
1367+ & profile_root,
1368+ None ,
1369+ |_| false ,
1370+ |root| {
1371+ if root == project_root {
1372+ crate :: worktree:: GitRepoIdentityOutcome :: Resolved (
1373+ crate :: worktree:: GitRepoIdentity {
1374+ worktree_root : project_root. clone ( ) ,
1375+ common_dir : dir. path ( ) . join ( "shared.git" ) ,
1376+ } ,
1377+ )
1378+ } else {
1379+ crate :: worktree:: GitRepoIdentityOutcome :: NotFound
1380+ }
1381+ } ,
1382+ )
1383+ . unwrap ( ) ;
1384+ assert ! (
1385+ layouts. is_empty( ) ,
1386+ "an unresolvable legacy root cannot be selected"
1387+ ) ;
1388+ }
1389+
13171390 #[ test]
13181391 fn exact_root_manifest_overrides_shared_git_discovery ( ) {
13191392 fn write_manifest ( profile_root : & Path , project_id : & str , project_root : & Path ) {
@@ -1347,14 +1420,19 @@ mod tests {
13471420
13481421 let resolver_calls = RefCell :: new ( Vec :: new ( ) ) ;
13491422 let ( layouts, selected_is_sole_exact_root) =
1350- matching_legacy_profile_layouts_with_git_resolver (
1423+ matching_legacy_profile_layouts_with_git_identity_resolver (
13511424 & project_root,
13521425 & profile_root,
13531426 None ,
13541427 |_| false ,
13551428 |root| {
13561429 resolver_calls. borrow_mut ( ) . push ( root. to_path_buf ( ) ) ;
1357- Some ( dir. path ( ) . join ( "shared.git" ) )
1430+ crate :: worktree:: GitRepoIdentityOutcome :: Resolved (
1431+ crate :: worktree:: GitRepoIdentity {
1432+ worktree_root : root. to_path_buf ( ) ,
1433+ common_dir : dir. path ( ) . join ( "shared.git" ) ,
1434+ } ,
1435+ )
13581436 } ,
13591437 )
13601438 . unwrap ( ) ;
@@ -1371,14 +1449,19 @@ mod tests {
13711449
13721450 resolver_calls. borrow_mut ( ) . clear ( ) ;
13731451 let ( layouts, selected_is_sole_exact_root) =
1374- matching_legacy_profile_layouts_with_git_resolver (
1452+ matching_legacy_profile_layouts_with_git_identity_resolver (
13751453 & project_root,
13761454 & profile_root,
13771455 Some ( "proj_exact" ) ,
13781456 |_| false ,
13791457 |root| {
13801458 resolver_calls. borrow_mut ( ) . push ( root. to_path_buf ( ) ) ;
1381- Some ( dir. path ( ) . join ( "shared.git" ) )
1459+ crate :: worktree:: GitRepoIdentityOutcome :: Resolved (
1460+ crate :: worktree:: GitRepoIdentity {
1461+ worktree_root : root. to_path_buf ( ) ,
1462+ common_dir : dir. path ( ) . join ( "shared.git" ) ,
1463+ } ,
1464+ )
13821465 } ,
13831466 )
13841467 . unwrap ( ) ;
@@ -1422,12 +1505,12 @@ mod tests {
14221505 )
14231506 . unwrap ( ) ;
14241507
1425- let error = matching_legacy_profile_layouts_with_git_resolver (
1508+ let error = matching_legacy_profile_layouts_with_git_identity_resolver (
14261509 & project_root,
14271510 & profile_root,
14281511 None ,
14291512 |_| false ,
1430- |_| None ,
1513+ |_| crate :: worktree :: GitRepoIdentityOutcome :: NotFound ,
14311514 )
14321515 . expect_err ( "missing project_id must fail closed" ) ;
14331516 assert ! ( error. to_string( ) . contains( "project_id is missing" ) ) ;
@@ -1468,14 +1551,19 @@ mod tests {
14681551
14691552 let resolver_calls = RefCell :: new ( Vec :: new ( ) ) ;
14701553 let ( layouts, selected_is_sole_exact_root) =
1471- matching_legacy_profile_layouts_with_git_resolver (
1554+ matching_legacy_profile_layouts_with_git_identity_resolver (
14721555 & worktree_root,
14731556 & profile_root,
14741557 Some ( "proj_selected" ) ,
14751558 |_| false ,
14761559 |root| {
14771560 resolver_calls. borrow_mut ( ) . push ( root. to_path_buf ( ) ) ;
1478- Some ( dir. path ( ) . join ( "shared.git" ) )
1561+ crate :: worktree:: GitRepoIdentityOutcome :: Resolved (
1562+ crate :: worktree:: GitRepoIdentity {
1563+ worktree_root : root. to_path_buf ( ) ,
1564+ common_dir : dir. path ( ) . join ( "shared.git" ) ,
1565+ } ,
1566+ )
14791567 } ,
14801568 )
14811569 . unwrap ( ) ;
0 commit comments