@@ -14,7 +14,7 @@ use dialoguer::{Select, theme::ColorfulTheme};
1414use semver:: VersionReq ;
1515
1616use crate :: {
17- command:: utils:: InstallOptions ,
17+ command:: utils:: { InstallOptions , KeyValuePair } ,
1818 consts:: GOUP_GO_VERSION ,
1919 dir:: Dir ,
2020 registries:: { go_index:: GoIndex , registry:: Registry } ,
@@ -36,6 +36,9 @@ pub struct Shell {
3636 /// skip autodetect go.work/go.mod.
3737 #[ arg( long) ]
3838 skip_autodetect : bool ,
39+ /// custom env vars
40+ #[ arg( short, long) ]
41+ envs : Vec < KeyValuePair > ,
3942 /// env file path
4043 #[ arg( short, long) ]
4144 filename : Option < PathBuf > ,
@@ -45,22 +48,26 @@ pub struct Shell {
4548
4649impl Run for Shell {
4750 fn run ( & self ) -> Result < ( ) , anyhow:: Error > {
48- let envs = if let Some ( ref filename) = self . filename {
51+ let filter_keys = [ "GOROOT" , GOUP_GO_VERSION ] ;
52+
53+ let mut envs = if let Some ( ref filename) = self . filename {
4954 dotenvy:: from_filename_iter ( filename) ?
5055 . filter_map ( |v| {
5156 v. ok ( ) . and_then ( |( k, v) | {
5257 // 过滤 GOROOT 和 GOUP_GO_VERSION
53- if k == "GOROOT" || k == GOUP_GO_VERSION {
54- None
55- } else {
56- Some ( ( k, v) )
57- }
58+ ( !filter_keys. contains ( & k. as_str ( ) ) ) . then_some ( ( k, v) )
5859 } )
5960 } )
6061 . collect ( )
6162 } else {
6263 HashMap :: new ( )
6364 } ;
65+ // 合并命令行的 -e KEY=VALUE
66+ for kv in & self . envs {
67+ if !filter_keys. contains ( & kv. key . as_str ( ) ) {
68+ envs. insert ( kv. key . clone ( ) , kv. value . clone ( ) ) ;
69+ }
70+ }
6471
6572 let local_versions = Version :: list_go_version ( ) ?;
6673 let target_go_version = self . get_target_version ( & local_versions) ?;
@@ -88,16 +95,27 @@ impl Run for Shell {
8895 } ) ;
8996 let parent_env_path = env:: var ( "PATH" ) . unwrap_or_default ( ) ;
9097
91- let extra_path = envs. get ( "path" ) . map ( |v| v. as_ref ( ) ) ;
9298 let child_env_go_root = go_root_path. to_string_lossy ( ) ;
9399 let child_go_root_bin = go_root_bin_path. to_string_lossy ( ) ;
94- let child_env_path = Self :: merger_env_path_as_child_path (
95- & parent_env_path,
96- extra_path,
97- parent_go_root_bin. as_deref ( ) ,
98- & child_go_root_bin,
99- env_separator,
100- ) ;
100+ let child_env_path = {
101+ let mut seen = HashSet :: new ( ) ;
102+ envs. get ( "path" )
103+ . map ( |v| v. split ( env_separator) )
104+ . into_iter ( )
105+ . flatten ( )
106+ . chain ( std:: iter:: once ( child_go_root_bin. as_ref ( ) ) )
107+ . chain ( parent_env_path. split ( env_separator) . filter ( |v| {
108+ if let Some ( parent_bin) = parent_go_root_bin. as_deref ( )
109+ && * v == parent_bin
110+ {
111+ return false ;
112+ }
113+ true
114+ } ) )
115+ . filter ( |v| seen. insert ( * v) ) // 去重,保持顺序
116+ . collect :: < Vec < _ > > ( )
117+ . join ( env_separator)
118+ } ;
101119
102120 log:: info!( "Enter new shell session with Go {target_go_version}" ) ;
103121 let mut command = Command :: new ( shell. to_string ( ) ) ;
@@ -126,45 +144,6 @@ impl Run for Shell {
126144}
127145
128146impl Shell {
129- fn merger_env_path_as_child_path (
130- parent_env_path : & str ,
131- extra_path : Option < & str > ,
132- parent_go_root_bin : Option < & str > ,
133- child_go_root_bin : & str ,
134- env_separator : & str ,
135- ) -> String {
136- // parent_env_path
137- // .split(env_separator)
138- // .filter(|v| {
139- // if let Some(parent_bin) = parent_go_root_bin
140- // && *v == parent_bin
141- // {
142- // return false;
143- // }
144- // true
145- // })
146- // .chain(std::iter::once(child_go_root_bin))
147- // .collect::<Vec<_>>()
148- // .join(env_separator)
149- let mut seen = HashSet :: new ( ) ;
150- extra_path
151- . map ( |v| v. split ( env_separator) )
152- . into_iter ( )
153- . flatten ( )
154- . chain ( std:: iter:: once ( child_go_root_bin) )
155- . chain ( parent_env_path. split ( env_separator) . filter ( |v| {
156- if let Some ( parent_bin) = parent_go_root_bin
157- && * v == parent_bin
158- {
159- return false ;
160- }
161- true
162- } ) )
163- . filter ( |v| seen. insert ( * v) ) // 去重,保持顺序
164- . collect :: < Vec < _ > > ( )
165- . join ( env_separator)
166- }
167-
168147 fn get_target_version ( & self , local_versions : & [ Version ] ) -> Result < String , anyhow:: Error > {
169148 if let Some ( version) = & self . version {
170149 // 指定了版本号,直接使用该版本
0 commit comments