1+ use miette:: miette;
12use std:: env;
23use std:: fs;
34use std:: io:: { self , BufRead } ;
45use std:: os:: unix:: process:: CommandExt ;
56use std:: path:: { Path , PathBuf } ;
67use std:: process:: Command ;
78
8- fn compare_versions ( version_from_cfg : & str , executable_path : & Path ) -> bool {
9- if let Some ( file_name) = executable_path. file_name ( ) . and_then ( |n| n. to_str ( ) ) {
10- return file_name. ends_with ( & format ! ( "python{}" , version_from_cfg) ) ;
11- } else {
12- false
13- }
14- }
15-
169fn find_pyvenv_cfg ( start_path : & Path ) -> Option < PathBuf > {
1710 let parent = start_path. parent ( ) ?. parent ( ) ?;
1811 let cfg_path = parent. join ( "pyvenv.cfg" ) ;
@@ -39,7 +32,30 @@ fn extract_pyvenv_version_info(cfg_path: &Path) -> Result<Option<String>, io::Er
3932 Ok ( None )
4033}
4134
42- fn find_python_executables ( version_from_cfg : & str , exclude_dir : & Path ) -> Option < Vec < PathBuf > > {
35+ fn parse_version_info ( version_str : & str ) -> Option < String > {
36+ // To avoid pulling in the regex crate, we're gonna do this by hand.
37+ let parts: Vec < _ > = version_str. split ( "." ) . collect ( ) ;
38+ match parts[ ..] {
39+ [ major, minor, ..] => Some ( format ! ( "{}.{}" , major, minor) ) ,
40+ _ => None ,
41+ }
42+ }
43+
44+ fn compare_versions (
45+ version_from_cfg : & str ,
46+ executable_path : & Path ,
47+ ) -> bool {
48+ if let Some ( file_name) = executable_path. file_name ( ) . and_then ( |n| n. to_str ( ) ) {
49+ return file_name. ends_with ( & format ! ( "python{}" , version_from_cfg) ) ;
50+ } else {
51+ false
52+ }
53+ }
54+
55+ fn find_python_executables (
56+ version_from_cfg : & str ,
57+ exclude_dir : & Path ,
58+ ) -> Option < Vec < PathBuf > > {
4359 let python_prefix = format ! ( "python{}" , version_from_cfg) ;
4460 let path_env = env:: var_os ( "PATH" ) ?;
4561
@@ -63,80 +79,65 @@ fn find_python_executables(version_from_cfg: &str, exclude_dir: &Path) -> Option
6379 }
6480}
6581
66- fn parse_version_info ( version_str : & str ) -> Option < String > {
67- // To avoid pulling in the regex crate, we're gonna do this by hand.
68- let parts: Vec < _ > = version_str. split ( "." ) . collect ( ) ;
69- match parts[ ..] {
70- [ major, minor, ..] => Some ( format ! ( "{}.{}" , major, minor) ) ,
71- _ => None ,
72- }
73- }
74-
75- fn main ( ) -> ( ) {
82+ fn main ( ) -> miette:: Result < ( ) > {
7683 let current_exe = env:: current_exe ( ) . unwrap ( ) ;
7784 let args: Vec < _ > = env:: args ( ) . collect ( ) ;
78- println ! ( "In the Aspect venv shim!" ) ;
85+
86+ #[ cfg( feature = "debug" ) ]
7987 println ! ( "[aspect] Current executable path: {:?}" , current_exe) ;
8088
8189 let pyvenv_cfg_path = match find_pyvenv_cfg ( & current_exe) {
8290 Some ( path) => {
83- println ! ( "[aspect] Found pyvenv.cfg at: {:?}" , path) ;
91+ #[ cfg( feature = "debug" ) ]
92+ eprintln ! ( "[aspect] Found pyvenv.cfg at: {:?}" , path) ;
8493 path
8594 }
8695 None => {
87- eprintln ! ( "pyvenv.cfg not found one directory level up." ) ;
88- return ;
96+ return Err ( miette ! ( "pyvenv.cfg not found one directory level up." ) ) ;
8997 }
9098 } ;
9199
92100 let version_info_result = extract_pyvenv_version_info ( & pyvenv_cfg_path) . unwrap ( ) ;
93101 let version_info = match version_info_result {
94102 Some ( v) => {
95- println ! ( "[aspect] version_info from pyvenv.cfg: {}" , v) ;
103+ #[ cfg( feature = "debug" ) ]
104+ eprintln ! ( "[aspect] version_info from pyvenv.cfg: {}" , v) ;
96105 v
97106 }
98107 None => {
99- eprintln ! ( "version_info key not found in pyvenv.cfg." ) ;
100- return ;
108+ return Err ( miette ! ( "version_info key not found in pyvenv.cfg." ) ) ;
101109 }
102110 } ;
103111
104112 let target_python_version = match parse_version_info ( & version_info) {
105113 Some ( v) => {
106- println ! ( "[aspect] Parsed target Python version (major.minor): {}" , v) ;
114+ #[ cfg( feature = "debug" ) ]
115+ eprintln ! ( "[aspect] Parsed target Python version (major.minor): {}" , v) ;
107116 v
108117 }
109118 None => {
110- eprintln ! ( "Could not parse version_info as x.y." ) ;
111- return ;
119+ return Err ( miette ! ( "Could not parse version_info as x.y." ) ) ;
112120 }
113121 } ;
114122
115- if target_python_version. is_empty ( ) {
116- eprintln ! ( "Target Python version is empty." ) ;
117- return ;
118- }
119-
120123 let exclude_dir = current_exe. parent ( ) . unwrap ( ) ;
121124 if let Some ( python_executables) = find_python_executables ( & target_python_version, exclude_dir) {
122- if python_executables. is_empty ( ) {
125+ #[ cfg( feature = "debug" ) ]
126+ {
123127 eprintln ! (
124- "No suitable Python interpreter found in PATH matching version '{}'." ,
125- target_python_version
128+ "[aspect] Found potential Python interpreters in PATH with matching version:"
126129 ) ;
127- return ;
128- }
129-
130- println ! ( "[aspect] Found potential Python interpreters in PATH with matching version:" ) ;
131- for exe in & python_executables {
132- println ! ( "[aspect] - {:?}" , exe) ;
130+ for exe in & python_executables {
131+ println ! ( "[aspect] - {:?}" , exe) ;
132+ }
133133 }
134134
135135 let interpreter_path = & python_executables[ 0 ] ;
136136 let exe_path = current_exe. to_string_lossy ( ) . into_owned ( ) ;
137137 let exec_args = & args[ 1 ..] ;
138138
139- println ! (
139+ #[ cfg( feature = "debug" ) ]
140+ eprintln ! (
140141 "[aspect] Attempting to execute: {:?} with argv[0] as {:?} and args as {:?}" ,
141142 interpreter_path, exe_path, exec_args,
142143 ) ;
@@ -162,5 +163,12 @@ fn main() -> () {
162163 }
163164
164165 let _ = cmd. exec ( ) ;
166+
167+ return Ok ( ( ) ) ;
168+ } else {
169+ return Err ( miette ! (
170+ "No suitable Python interpreter found in PATH matching version '{}'." ,
171+ & version_info,
172+ ) ) ;
165173 }
166174}
0 commit comments