2
2
// SPDX-License-Identifier: Apache-2.0
3
3
// https://github.com/spkenv/spk
4
4
5
+ use std:: borrow:: Cow ;
5
6
use std:: ffi:: OsString ;
6
7
#[ cfg( feature = "sentry" ) ]
7
8
use std:: sync:: atomic:: Ordering ;
@@ -13,6 +14,7 @@ use cli::configure_sentry;
13
14
use miette:: { Context , Result } ;
14
15
#[ cfg( unix) ]
15
16
use spfs:: monitor:: SPFS_MONITOR_FOREGROUND_LOGGING_VAR ;
17
+ use spfs:: runtime:: EnvKeyValue ;
16
18
use spfs:: storage:: fs:: RenderSummary ;
17
19
use spfs_cli_common as cli;
18
20
use spfs_cli_common:: CommandName ;
@@ -82,13 +84,34 @@ pub struct RemountArgs {
82
84
enabled : bool ,
83
85
}
84
86
87
+ fn parse_env_key_value ( s : & str ) -> Result < EnvKeyValue > {
88
+ let parts: Vec < & str > = s. splitn ( 2 , '=' ) . collect ( ) ;
89
+ if parts. len ( ) != 2 {
90
+ miette:: bail!( "Invalid environment key-value pair (missing '='): {s}" ) ;
91
+ }
92
+ if parts[ 0 ] . is_empty ( ) {
93
+ miette:: bail!( "Invalid environment key-value pair (empty key): {s}" ) ;
94
+ }
95
+ if parts[ 0 ] . contains ( |c : char | c. is_whitespace ( ) ) {
96
+ miette:: bail!( "Invalid environment key-value pair (key contains whitespace): {s}" ) ;
97
+ }
98
+ Ok ( EnvKeyValue ( parts[ 0 ] . to_string ( ) , parts[ 1 ] . to_string ( ) ) )
99
+ }
100
+
85
101
#[ derive( Debug , Args ) ]
86
102
#[ group( id = "enter_grp" ) ]
87
103
pub struct EnterArgs {
88
104
/// The value to set $TMPDIR to in new environment
105
+ ///
106
+ /// Deprecated: use --environment-override instead
89
107
#[ clap( long) ]
90
108
tmpdir : Option < String > ,
91
109
110
+ /// Optional keys and values to set in the new environment, in the form
111
+ /// KEY=VALUE. This option can be repeated.
112
+ #[ clap( long, value_parser = parse_env_key_value) ]
113
+ environment_override : Vec < EnvKeyValue > ,
114
+
92
115
/// Put the rendering and syncing times into environment variables
93
116
#[ clap( long) ]
94
117
metrics_in_env : bool ,
@@ -140,6 +163,7 @@ impl CmdEnter {
140
163
// this function will eventually be required to discover the overlayfs
141
164
// attributes. It can take many milliseconds to run so we prime the cache as
142
165
// soon as possible in a separate thread
166
+
143
167
std:: thread:: spawn ( spfs:: runtime:: overlayfs:: overlayfs_available_options_prime_cache) ;
144
168
145
169
let mut runtime = self . load_runtime ( config) . await ?;
@@ -233,7 +257,14 @@ impl CmdEnter {
233
257
}
234
258
} ;
235
259
236
- owned. ensure_startup_scripts ( self . enter . tmpdir . as_ref ( ) ) ?;
260
+ let mut environment_overrides = Cow :: Borrowed ( & self . enter . environment_override ) ;
261
+ if let Some ( tmpdir) = & self . enter . tmpdir {
262
+ environment_overrides
263
+ . to_mut ( )
264
+ . push ( EnvKeyValue ( "TMPDIR" . to_string ( ) , tmpdir. to_string ( ) ) ) ;
265
+ }
266
+
267
+ owned. ensure_startup_scripts ( environment_overrides. as_slice ( ) ) ?;
237
268
std:: env:: set_var ( "SPFS_RUNTIME" , owned. name ( ) ) ;
238
269
239
270
Ok ( Some ( owned) )
@@ -256,7 +287,15 @@ impl CmdEnter {
256
287
let start_time = Instant :: now ( ) ;
257
288
let render_summary = spfs:: initialize_runtime ( & mut owned) . await ?;
258
289
self . report_render_summary ( render_summary, start_time. elapsed ( ) . as_secs_f64 ( ) ) ;
259
- owned. ensure_startup_scripts ( self . enter . tmpdir . as_ref ( ) ) ?;
290
+
291
+ let mut environment_overrides = Cow :: Borrowed ( & self . enter . environment_override ) ;
292
+ if let Some ( tmpdir) = & self . enter . tmpdir {
293
+ environment_overrides
294
+ . to_mut ( )
295
+ . push ( EnvKeyValue ( "TMPDIR" . to_string ( ) , tmpdir. to_string ( ) ) ) ;
296
+ }
297
+
298
+ owned. ensure_startup_scripts ( environment_overrides. as_slice ( ) ) ?;
260
299
std:: env:: set_var ( "SPFS_RUNTIME" , owned. name ( ) ) ;
261
300
262
301
Ok ( Some ( owned) )
0 commit comments