@@ -4,12 +4,13 @@ use std::{
4
4
io,
5
5
} ;
6
6
7
+ use camino:: { Utf8Path , Utf8PathBuf } ;
7
8
use convert_case:: { Case , Casing } ;
8
9
use miette:: { Diagnostic , NamedSource , SourceSpan } ;
9
10
use serde:: Deserialize ;
10
11
use struct_iterable:: Iterable ;
11
12
use thiserror:: Error ;
12
- use turbopath:: { AbsoluteSystemPathBuf , AnchoredSystemPath } ;
13
+ use turbopath:: { AbsoluteSystemPathBuf , AnchoredSystemPath , RelativeUnixPath } ;
13
14
use turborepo_auth:: { TURBO_TOKEN_DIR , TURBO_TOKEN_FILE , VERCEL_TOKEN_DIR , VERCEL_TOKEN_FILE } ;
14
15
use turborepo_dirs:: { config_dir, vercel_config_dir} ;
15
16
use turborepo_errors:: TURBO_SITE ;
@@ -161,6 +162,14 @@ pub enum Error {
161
162
#[ error( transparent) ]
162
163
#[ diagnostic( transparent) ]
163
164
TurboJsonParseError ( #[ from] turbo_json:: parser:: Error ) ,
165
+ #[ error( "found absolute path in `cacheDir`" ) ]
166
+ #[ diagnostic( help( "if absolute paths are required, use `--cache-dir` or `TURBO_CACHE_DIR`" ) ) ]
167
+ AbsoluteCacheDir {
168
+ #[ label( "make `cacheDir` value a relative unix path" ) ]
169
+ span : Option < SourceSpan > ,
170
+ #[ source_code]
171
+ text : NamedSource ,
172
+ } ,
164
173
}
165
174
166
175
macro_rules! create_builder {
@@ -215,6 +224,8 @@ pub struct ConfigurationOptions {
215
224
pub ( crate ) env_mode : Option < EnvMode > ,
216
225
pub ( crate ) scm_base : Option < String > ,
217
226
pub ( crate ) scm_head : Option < String > ,
227
+ #[ serde( rename = "cacheDir" ) ]
228
+ pub ( crate ) cache_dir : Option < Utf8PathBuf > ,
218
229
}
219
230
220
231
#[ derive( Default ) ]
@@ -306,6 +317,16 @@ impl ConfigurationOptions {
306
317
pub fn env_mode ( & self ) -> EnvMode {
307
318
self . env_mode . unwrap_or_default ( )
308
319
}
320
+
321
+ pub fn cache_dir ( & self ) -> & Utf8Path {
322
+ self . cache_dir . as_deref ( ) . unwrap_or_else ( || {
323
+ Utf8Path :: new ( if cfg ! ( windows) {
324
+ ".turbo\\ cache"
325
+ } else {
326
+ ".turbo/cache"
327
+ } )
328
+ } )
329
+ }
309
330
}
310
331
311
332
// Maps Some("") to None to emulate how Go handles empty strings
@@ -332,6 +353,21 @@ impl ResolvedConfigurationOptions for RawTurboJson {
332
353
} else {
333
354
ConfigurationOptions :: default ( )
334
355
} ;
356
+
357
+ let cache_dir = if let Some ( cache_dir) = self . cache_dir {
358
+ let cache_dir_str: & str = & cache_dir;
359
+ let cache_dir_unix = RelativeUnixPath :: new ( cache_dir_str) . map_err ( |_| {
360
+ let ( span, text) = cache_dir. span_and_text ( "turbo.json" ) ;
361
+ Error :: AbsoluteCacheDir { span, text }
362
+ } ) ?;
363
+ // Convert the relative unix path to an anchored system path
364
+ // For unix/macos this is a no-op
365
+ let cache_dir_system = cache_dir_unix. to_anchored_system_path_buf ( ) ;
366
+ Some ( Utf8PathBuf :: from ( cache_dir_system. to_string ( ) ) )
367
+ } else {
368
+ None
369
+ } ;
370
+
335
371
// Don't allow token to be set for shared config.
336
372
opts. token = None ;
337
373
opts. spaces_id = self
@@ -342,6 +378,7 @@ impl ResolvedConfigurationOptions for RawTurboJson {
342
378
opts. allow_no_package_manager = self . allow_no_package_manager ;
343
379
opts. daemon = self . daemon . map ( |daemon| * daemon. as_inner ( ) ) ;
344
380
opts. env_mode = self . env_mode ;
381
+ opts. cache_dir = cache_dir;
345
382
Ok ( opts)
346
383
}
347
384
}
@@ -380,6 +417,7 @@ fn get_env_var_config(
380
417
) ;
381
418
turbo_mapping. insert ( OsString :: from ( "turbo_daemon" ) , "daemon" ) ;
382
419
turbo_mapping. insert ( OsString :: from ( "turbo_env_mode" ) , "env_mode" ) ;
420
+ turbo_mapping. insert ( OsString :: from ( "turbo_cache_dir" ) , "cache_dir" ) ;
383
421
turbo_mapping. insert ( OsString :: from ( "turbo_preflight" ) , "preflight" ) ;
384
422
turbo_mapping. insert ( OsString :: from ( "turbo_scm_base" ) , "scm_base" ) ;
385
423
turbo_mapping. insert ( OsString :: from ( "turbo_scm_head" ) , "scm_head" ) ;
@@ -490,6 +528,8 @@ fn get_env_var_config(
490
528
_ => None ,
491
529
} ) ;
492
530
531
+ let cache_dir = output_map. get ( "cache_dir" ) . map ( |s| s. clone ( ) . into ( ) ) ;
532
+
493
533
// We currently don't pick up a Spaces ID via env var, we likely won't
494
534
// continue using the Spaces name, we can add an env var when we have the
495
535
// name we want to stick with.
@@ -517,6 +557,7 @@ fn get_env_var_config(
517
557
upload_timeout,
518
558
spaces_id,
519
559
env_mode,
560
+ cache_dir,
520
561
} ;
521
562
522
563
Ok ( output)
@@ -580,6 +621,7 @@ fn get_override_env_var_config(
580
621
spaces_id : None ,
581
622
allow_no_package_manager : None ,
582
623
env_mode : None ,
624
+ cache_dir : None ,
583
625
} ;
584
626
585
627
Ok ( output)
@@ -722,6 +764,7 @@ impl TurborepoConfigBuilder {
722
764
) ;
723
765
create_builder ! ( with_daemon, daemon, Option <bool >) ;
724
766
create_builder ! ( with_env_mode, env_mode, Option <EnvMode >) ;
767
+ create_builder ! ( with_cache_dir, cache_dir, Option <Utf8PathBuf >) ;
725
768
726
769
pub fn build ( & self ) -> Result < ConfigurationOptions , Error > {
727
770
// Priority, from least significant to most significant:
@@ -816,6 +859,9 @@ impl TurborepoConfigBuilder {
816
859
if let Some ( scm_head) = current_source_config. scm_head {
817
860
acc. scm_head = Some ( scm_head) ;
818
861
}
862
+ if let Some ( cache_dir) = current_source_config. cache_dir {
863
+ acc. cache_dir = Some ( cache_dir) ;
864
+ }
819
865
820
866
acc
821
867
} )
@@ -828,6 +874,7 @@ impl TurborepoConfigBuilder {
828
874
mod test {
829
875
use std:: { collections:: HashMap , ffi:: OsString } ;
830
876
877
+ use camino:: Utf8PathBuf ;
831
878
use tempfile:: TempDir ;
832
879
use turbopath:: AbsoluteSystemPathBuf ;
833
880
@@ -865,6 +912,7 @@ mod test {
865
912
let turbo_team = "vercel" ;
866
913
let turbo_teamid = "team_nLlpyC6REAqxydlFKbrMDlud" ;
867
914
let turbo_token = "abcdef1234567890abcdef" ;
915
+ let cache_dir = Utf8PathBuf :: from ( "nebulo9" ) ;
868
916
let turbo_remote_cache_timeout = 200 ;
869
917
870
918
env. insert ( "turbo_api" . into ( ) , turbo_api. into ( ) ) ;
@@ -884,6 +932,7 @@ mod test {
884
932
env. insert ( "turbo_daemon" . into ( ) , "true" . into ( ) ) ;
885
933
env. insert ( "turbo_preflight" . into ( ) , "true" . into ( ) ) ;
886
934
env. insert ( "turbo_env_mode" . into ( ) , "strict" . into ( ) ) ;
935
+ env. insert ( "turbo_cache_dir" . into ( ) , cache_dir. clone ( ) . into ( ) ) ;
887
936
888
937
let config = get_env_var_config ( & env) . unwrap ( ) ;
889
938
assert ! ( config. preflight( ) ) ;
@@ -897,6 +946,7 @@ mod test {
897
946
assert_eq ! ( Some ( true ) , config. allow_no_package_manager) ;
898
947
assert_eq ! ( Some ( true ) , config. daemon) ;
899
948
assert_eq ! ( Some ( EnvMode :: Strict ) , config. env_mode) ;
949
+ assert_eq ! ( cache_dir, config. cache_dir. unwrap( ) ) ;
900
950
}
901
951
902
952
#[ test]
0 commit comments