@@ -665,7 +665,6 @@ fn apply_configure_options(
665665 environment_directories : Option < Vec < PathBuf > > ,
666666) -> Result < ( ) , String > {
667667 let mut state = configuration. write ( ) . unwrap ( ) ;
668- let previous_config = state. config . clone ( ) ;
669668 let mut next_config = state. config . clone ( ) ;
670669 let next_generation = state. generation + 1 ;
671670
@@ -687,18 +686,27 @@ fn apply_configure_options(
687686 next_config
688687 ) ;
689688
690- if let Err ( panic_payload) = panic:: catch_unwind ( AssertUnwindSafe ( || {
691- configure_locators ( locators, & next_config) ;
692- } ) ) {
693- let panic_message = panic_payload_message ( panic_payload. as_ref ( ) ) ;
694- error ! (
695- "Locator configuration panicked for generation {}: {}" ,
696- next_generation, panic_message
697- ) ;
698- rollback_locator_config ( locators, & previous_config, next_generation) ;
699- return Err ( format ! (
700- "Locator configuration failed for generation {next_generation}: {panic_message}"
701- ) ) ;
689+ let mut configured_locator_count = 0 ;
690+ for locator in locators. iter ( ) {
691+ if let Err ( panic_payload) = panic:: catch_unwind ( AssertUnwindSafe ( || {
692+ locator. configure ( & next_config) ;
693+ } ) ) {
694+ let panic_message = panic_payload_message ( panic_payload. as_ref ( ) ) ;
695+ error ! (
696+ "Locator configuration panicked for generation {}: {}" ,
697+ next_generation, panic_message
698+ ) ;
699+ rollback_locator_config (
700+ locators,
701+ & state. config ,
702+ next_generation,
703+ configured_locator_count + 1 ,
704+ ) ;
705+ return Err ( format ! (
706+ "Locator configuration failed for generation {next_generation}: {panic_message}"
707+ ) ) ;
708+ }
709+ configured_locator_count += 1 ;
702710 }
703711
704712 if let Some ( cache_directory) = cache_directory {
@@ -710,7 +718,12 @@ fn apply_configure_options(
710718 "Cache directory configuration panicked for generation {}: {}" ,
711719 next_generation, panic_message
712720 ) ;
713- rollback_locator_config ( locators, & previous_config, next_generation) ;
721+ rollback_locator_config (
722+ locators,
723+ & state. config ,
724+ next_generation,
725+ configured_locator_count,
726+ ) ;
714727 return Err ( format ! (
715728 "Cache directory configuration failed for generation {next_generation}: {panic_message}"
716729 ) ) ;
@@ -731,15 +744,19 @@ fn rollback_locator_config(
731744 locators : & Arc < Vec < Arc < dyn Locator > > > ,
732745 previous_config : & Configuration ,
733746 failed_generation : u64 ,
747+ configured_locator_count : usize ,
734748) {
735749 if let Err ( panic_payload) = panic:: catch_unwind ( AssertUnwindSafe ( || {
736- configure_locators ( locators, previous_config) ;
750+ for locator in locators. iter ( ) . take ( configured_locator_count) {
751+ locator. configure ( previous_config) ;
752+ }
737753 } ) ) {
738754 error ! (
739- "Rollback after failed locator configuration for generation {} also panicked: {}" ,
755+ "Rollback after failed locator configuration for generation {} also panicked: {}. Aborting process to avoid continuing with inconsistent locator state. " ,
740756 failed_generation,
741757 panic_payload_message( panic_payload. as_ref( ) )
742758 ) ;
759+ std:: process:: abort ( ) ;
743760 }
744761}
745762
@@ -1339,7 +1356,9 @@ mod tests {
13391356 configured_workspace_directories : Mutex < Option < Vec < PathBuf > > > ,
13401357 }
13411358
1342- struct PanicConfigureLocator ;
1359+ struct PanicConfigureLocator {
1360+ configured_workspace_directories : Mutex < Option < Vec < PathBuf > > > ,
1361+ }
13431362
13441363 struct RecordingConfigureLocator {
13451364 configured_workspace_directories : Mutex < Option < Vec < PathBuf > > > ,
@@ -1404,8 +1423,12 @@ mod tests {
14041423 LocatorKind :: Venv
14051424 }
14061425
1407- fn configure ( & self , _config : & Configuration ) {
1408- panic ! ( "configure boom" ) ;
1426+ fn configure ( & self , config : & Configuration ) {
1427+ * self . configured_workspace_directories . lock ( ) . unwrap ( ) =
1428+ config. workspace_directories . clone ( ) ;
1429+ if config. workspace_directories . is_some ( ) || config. conda_executable . is_some ( ) {
1430+ panic ! ( "configure boom" ) ;
1431+ }
14091432 }
14101433
14111434 fn supported_categories ( & self ) -> Vec < PythonEnvironmentKind > {
@@ -1627,7 +1650,10 @@ mod tests {
16271650 #[ test]
16281651 fn test_configure_panic_does_not_publish_state_or_poison_lock ( ) {
16291652 let configuration = RwLock :: new ( ConfigurationState :: default ( ) ) ;
1630- let locators = Arc :: new ( vec ! [ Arc :: new( PanicConfigureLocator ) as Arc <dyn Locator >] ) ;
1653+ let panic_locator = Arc :: new ( PanicConfigureLocator {
1654+ configured_workspace_directories : Mutex :: new ( None ) ,
1655+ } ) ;
1656+ let locators = Arc :: new ( vec ! [ panic_locator. clone( ) as Arc <dyn Locator >] ) ;
16311657 let workspace_directories = vec ! [ PathBuf :: from( "/workspace" ) ] ;
16321658
16331659 let result = apply_configure_options (
@@ -1650,6 +1676,11 @@ mod tests {
16501676 assert_eq ! ( state. generation, 0 ) ;
16511677 assert ! ( state. config. workspace_directories. is_none( ) ) ;
16521678 assert ! ( state. config. conda_executable. is_none( ) ) ;
1679+ assert ! ( panic_locator
1680+ . configured_workspace_directories
1681+ . lock( )
1682+ . unwrap( )
1683+ . is_none( ) ) ;
16531684 }
16541685
16551686 #[ test]
@@ -1658,9 +1689,12 @@ mod tests {
16581689 let recording_locator = Arc :: new ( RecordingConfigureLocator {
16591690 configured_workspace_directories : Mutex :: new ( None ) ,
16601691 } ) ;
1692+ let panic_locator = Arc :: new ( PanicConfigureLocator {
1693+ configured_workspace_directories : Mutex :: new ( None ) ,
1694+ } ) ;
16611695 let locators = Arc :: new ( vec ! [
16621696 recording_locator. clone( ) as Arc <dyn Locator >,
1663- Arc :: new ( PanicConfigureLocator ) as Arc <dyn Locator >,
1697+ panic_locator . clone ( ) as Arc <dyn Locator >,
16641698 ] ) ;
16651699
16661700 let result = apply_configure_options (
@@ -1684,6 +1718,11 @@ mod tests {
16841718 . lock( )
16851719 . unwrap( )
16861720 . is_none( ) ) ;
1721+ assert ! ( panic_locator
1722+ . configured_workspace_directories
1723+ . lock( )
1724+ . unwrap( )
1725+ . is_none( ) ) ;
16871726 }
16881727
16891728 #[ test]
0 commit comments