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