33use log:: debug;
44use serde:: Deserialize ;
55use std:: default:: Default ;
6+ use std:: fs:: File ;
67use std:: io:: { Error , ErrorKind } ;
78
9+ #[ derive( Debug , Deserialize ) ]
10+ #[ serde( default ) ]
11+ pub struct EnvCreateConfig {
12+ /// If true (default), verify SSL/TLS certificates. This is used for
13+ /// configuring passthrough to micromamba (and indirectly, pip).
14+ pub ssl_verify : bool ,
15+
16+ /// The SSL/TLS certificate bundle to verify with. When None (default), uses
17+ /// the default, which when calling out to micromamba, corresponds to the
18+ /// system chain or "ca-certificates" from conda-forge if installed.
19+ pub ssl_bundle : Option < String > ,
20+
21+ /// Disable SSL/TLS revokation checking (affects passthrough to micromamba).
22+ /// This is equivalent to passing --ssl-no-revoke to micromamba.
23+ pub ssl_no_revoke : bool ,
24+ }
25+
26+ impl Default for EnvCreateConfig {
27+ fn default ( ) -> Self {
28+ EnvCreateConfig {
29+ ssl_verify : true ,
30+ ssl_bundle : None ,
31+ ssl_no_revoke : false ,
32+ }
33+ }
34+ }
35+
836#[ derive( Debug , Deserialize ) ]
937#[ serde( default ) ]
1038pub struct Config {
@@ -30,6 +58,9 @@ pub struct Config {
3058 /// If true, skip checking for LongPaths support on Windows, and never try
3159 /// to set it.
3260 pub skip_longpaths_check : bool ,
61+
62+ /// Options for the 'env create' subcommand
63+ pub env_create : EnvCreateConfig ,
3364}
3465
3566#[ allow( clippy:: derivable_impls) ]
@@ -42,32 +73,53 @@ impl Default for Config {
4273 download_micromamba : true ,
4374 verbose : false ,
4475 skip_longpaths_check : false ,
76+ env_create : EnvCreateConfig :: default ( ) ,
4577 }
4678 }
4779}
4880
4981impl Config {
82+ /// Validate the configuration to check for common errors.
83+ fn validate ( self ) -> Result < Self , std:: io:: Error > {
84+ // Specifying a bundle when ssl_verify is false makes no sense.
85+ // Do the safe thing and bail out - they might have meant to use the
86+ // bundle and we should not just disable verification in this case.
87+ if !self . env_create . ssl_verify && self . env_create . ssl_bundle . is_some ( ) {
88+ return Err ( Error :: new (
89+ ErrorKind :: InvalidData ,
90+ "SSL/TLS verification was disabled, but a bundle was still specified" ,
91+ ) ) ;
92+ }
93+ Ok ( self )
94+ }
95+
5096 /// Read the user's ~/.csmrc if it exists, merging with the Default instance for
5197 /// Config. Return Err if a config file was found but failed to parse, otherwise
5298 /// Ok with the result of merging the config file values with the Default (and
5399 /// simply the Default if no config file exists).
54100 pub fn from_csmrc ( ) -> Result < Self , std:: io:: Error > {
101+ fn parse_or_io_error ( f : File ) -> Result < Config , std:: io:: Error > {
102+ match serde_yaml_ng:: from_reader :: < File , Config > ( f) {
103+ Ok ( cfg) => cfg. validate ( ) ,
104+ Err ( e) => Err ( Error :: new ( ErrorKind :: InvalidData , e) ) ,
105+ }
106+ }
107+
55108 let Some ( home) = std:: env:: home_dir ( ) else {
109+ debug ! ( "Could not determine home directory to read .csmrc, using defaults" ) ;
56110 return Ok ( Self :: default ( ) ) ;
57111 } ;
112+
58113 let csmrc_path = home. join ( ".csmrc" ) ;
59- match std:: fs:: read_to_string ( csmrc_path) {
60- Err ( e) if e. kind ( ) == ErrorKind :: NotFound => {
61- debug ! ( "No .csmrc found, using defaults" ) ;
62- Ok ( Config :: default ( ) )
63- }
64- Err ( e) => Err ( e) ,
65- Ok ( csmrc_data) => {
66- let config = serde_yaml_ng:: from_str ( & csmrc_data)
67- . map_err ( |e| Error :: new ( ErrorKind :: InvalidData , e) ) ;
68- debug ! ( "config: {:?}" , config) ;
69- config
70- }
71- }
114+ File :: open ( csmrc_path)
115+ . and_then ( parse_or_io_error)
116+ . or_else ( |e| {
117+ if e. kind ( ) == ErrorKind :: NotFound {
118+ debug ! ( "No .csmrc found, using defaults" ) ;
119+ Ok ( Config :: default ( ) )
120+ } else {
121+ Err ( e)
122+ }
123+ } )
72124 }
73125}
0 commit comments