@@ -42,27 +42,30 @@ impl Executables {
42
42
}
43
43
44
44
let executable_name = executable_spec. name . clone ( ) ;
45
- // `or_insert` will always insert as we've already assured ourselves that the key does not exist.
46
- let executable = self
47
- . cache
48
- . entry ( executable_name. clone ( ) )
49
- . or_insert_with ( || Executable :: new ( executable_spec) ) ;
50
-
51
- // TODO: if we fail to start, the exe remains in the cache and start cannot be called again
52
- // solving ^^ was a borrow checker fight and I (future-highway) lost this round.
45
+ let mut executable = Executable :: new ( executable_spec) ;
46
+
47
+ // start the exe before we add it to the cache, as otherwise a failure leads to the
48
+ // executable remaining in the cache and start cannot be called again.
53
49
executable. start ( ) . map_err ( |e| {
54
50
ExecutablesError :: FailedToStartExecutable {
55
- executable_name,
51
+ executable_name : executable_name . clone ( ) ,
56
52
source : e,
57
53
}
58
54
} ) ?;
59
55
60
- Ok ( executable)
56
+ // `or_insert` will always insert as we've already assured ourselves that the key does not
57
+ // exist.
58
+ let inserted_executable =
59
+ self . cache . entry ( executable_name) . or_insert_with ( || executable) ;
60
+
61
+ Ok ( inserted_executable)
61
62
}
62
63
63
64
pub fn get ( & self , executable_name : & ExecutableName ) -> Result < & Executable > {
64
65
let Some ( executable) = self . cache . get ( executable_name) else {
65
- return Err ( ExecutablesError :: ExecutableNotFound { executable_name : executable_name. clone ( ) } ) ;
66
+ return Err ( ExecutablesError :: ExecutableNotFound {
67
+ executable_name : executable_name. clone ( ) ,
68
+ } ) ;
66
69
} ;
67
70
Ok ( executable)
68
71
}
@@ -72,7 +75,9 @@ impl Executables {
72
75
executable_name : & ExecutableName ,
73
76
) -> Result < ExitStatus > {
74
77
let Some ( executable) = self . cache . get_mut ( executable_name) else {
75
- return Err ( ExecutablesError :: ExecutableNotFound { executable_name : executable_name. clone ( ) } ) ;
78
+ return Err ( ExecutablesError :: ExecutableNotFound {
79
+ executable_name : executable_name. clone ( ) ,
80
+ } ) ;
76
81
} ;
77
82
78
83
let exit_status = executable. kill ( ) . await . map_err ( |e| {
@@ -84,7 +89,8 @@ impl Executables {
84
89
85
90
let Some ( exit_status) = exit_status else {
86
91
// Exes that never started return None
87
- let executable = self . cache . remove ( executable_name) . expect ( "exe in cache" ) ;
92
+ let executable =
93
+ self . cache . remove ( executable_name) . expect ( "exe in cache" ) ;
88
94
return Err ( ExecutablesError :: ExecutableNotFound {
89
95
executable_name : executable. name ,
90
96
} ) ;
@@ -112,4 +118,4 @@ impl Executables {
112
118
let _ = self . cache . remove ( & name) ;
113
119
}
114
120
}
115
- }
121
+ }
0 commit comments