https://en.m.wikipedia.org/wiki/Shebang_(Unix)
(reader: &mut impl Read)
| 243 | |
| 244 | // https://en.m.wikipedia.org/wiki/Shebang_(Unix) |
| 245 | fn parse_python_shebang(reader: &mut impl Read) -> Option<RequestedVersion> { |
| 246 | let mut shebang_buffer = [0; 2]; |
| 247 | log::info!("Looking for a Python-related shebang"); |
| 248 | if reader.read(&mut shebang_buffer).is_err() || shebang_buffer != [0x23, 0x21] { |
| 249 | // Doesn't start w/ `#!` in ASCII/UTF-8. |
| 250 | log::debug!("No '#!' at the start of the first line of the file"); |
| 251 | return None; |
| 252 | } |
| 253 | |
| 254 | let mut buffered_reader = BufReader::new(reader); |
| 255 | let mut first_line = String::new(); |
| 256 | |
| 257 | if buffered_reader.read_line(&mut first_line).is_err() { |
| 258 | log::debug!("Can't read first line of the file"); |
| 259 | return None; |
| 260 | }; |
| 261 | |
| 262 | // Whitespace between `#!` and the path is allowed. |
| 263 | let line = first_line.trim(); |
| 264 | |
| 265 | let accepted_paths = [ |
| 266 | "python", |
| 267 | "/usr/bin/python", |
| 268 | "/usr/local/bin/python", |
| 269 | "/usr/bin/env python", |
| 270 | ]; |
| 271 | |
| 272 | for acceptable_path in &accepted_paths { |
| 273 | if !line.starts_with(acceptable_path) { |
| 274 | continue; |
| 275 | } |
| 276 | |
| 277 | log::debug!("Found shebang: {acceptable_path}"); |
| 278 | let version = line[acceptable_path.len()..].to_string(); |
| 279 | log::debug!("Found version: {version}"); |
| 280 | return RequestedVersion::from_str(&version).ok(); |
| 281 | } |
| 282 | |
| 283 | None |
| 284 | } |
| 285 | |
| 286 | fn find_executable(version: RequestedVersion, args: &[String]) -> crate::Result<PathBuf> { |
| 287 | let mut requested_version = version; |
no outgoing calls
no test coverage detected