1
+ use miette:: miette;
1
2
use std:: env;
2
3
use std:: fs;
3
4
use std:: io:: { self , BufRead } ;
4
5
use std:: os:: unix:: process:: CommandExt ;
5
6
use std:: path:: { Path , PathBuf } ;
6
7
use std:: process:: Command ;
7
8
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
-
16
9
fn find_pyvenv_cfg ( start_path : & Path ) -> Option < PathBuf > {
17
10
let parent = start_path. parent ( ) ?. parent ( ) ?;
18
11
let cfg_path = parent. join ( "pyvenv.cfg" ) ;
@@ -39,7 +32,30 @@ fn extract_pyvenv_version_info(cfg_path: &Path) -> Result<Option<String>, io::Er
39
32
Ok ( None )
40
33
}
41
34
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 > > {
43
59
let python_prefix = format ! ( "python{}" , version_from_cfg) ;
44
60
let path_env = env:: var_os ( "PATH" ) ?;
45
61
@@ -63,80 +79,65 @@ fn find_python_executables(version_from_cfg: &str, exclude_dir: &Path) -> Option
63
79
}
64
80
}
65
81
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 < ( ) > {
76
83
let current_exe = env:: current_exe ( ) . unwrap ( ) ;
77
84
let args: Vec < _ > = env:: args ( ) . collect ( ) ;
78
- println ! ( "In the Aspect venv shim!" ) ;
85
+
86
+ #[ cfg( feature = "debug" ) ]
79
87
println ! ( "[aspect] Current executable path: {:?}" , current_exe) ;
80
88
81
89
let pyvenv_cfg_path = match find_pyvenv_cfg ( & current_exe) {
82
90
Some ( path) => {
83
- println ! ( "[aspect] Found pyvenv.cfg at: {:?}" , path) ;
91
+ #[ cfg( feature = "debug" ) ]
92
+ eprintln ! ( "[aspect] Found pyvenv.cfg at: {:?}" , path) ;
84
93
path
85
94
}
86
95
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." ) ) ;
89
97
}
90
98
} ;
91
99
92
100
let version_info_result = extract_pyvenv_version_info ( & pyvenv_cfg_path) . unwrap ( ) ;
93
101
let version_info = match version_info_result {
94
102
Some ( v) => {
95
- println ! ( "[aspect] version_info from pyvenv.cfg: {}" , v) ;
103
+ #[ cfg( feature = "debug" ) ]
104
+ eprintln ! ( "[aspect] version_info from pyvenv.cfg: {}" , v) ;
96
105
v
97
106
}
98
107
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." ) ) ;
101
109
}
102
110
} ;
103
111
104
112
let target_python_version = match parse_version_info ( & version_info) {
105
113
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) ;
107
116
v
108
117
}
109
118
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." ) ) ;
112
120
}
113
121
} ;
114
122
115
- if target_python_version. is_empty ( ) {
116
- eprintln ! ( "Target Python version is empty." ) ;
117
- return ;
118
- }
119
-
120
123
let exclude_dir = current_exe. parent ( ) . unwrap ( ) ;
121
124
if let Some ( python_executables) = find_python_executables ( & target_python_version, exclude_dir) {
122
- if python_executables. is_empty ( ) {
125
+ #[ cfg( feature = "debug" ) ]
126
+ {
123
127
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:"
126
129
) ;
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
+ }
133
133
}
134
134
135
135
let interpreter_path = & python_executables[ 0 ] ;
136
136
let exe_path = current_exe. to_string_lossy ( ) . into_owned ( ) ;
137
137
let exec_args = & args[ 1 ..] ;
138
138
139
- println ! (
139
+ #[ cfg( feature = "debug" ) ]
140
+ eprintln ! (
140
141
"[aspect] Attempting to execute: {:?} with argv[0] as {:?} and args as {:?}" ,
141
142
interpreter_path, exe_path, exec_args,
142
143
) ;
@@ -162,5 +163,12 @@ fn main() -> () {
162
163
}
163
164
164
165
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
+ ) ) ;
165
173
}
166
174
}
0 commit comments