|
1 |
| -use std::io::Write; |
| 1 | +use std::{ |
| 2 | + io::{self, Read, Write}, |
| 3 | + iter, |
| 4 | + path::PathBuf, |
| 5 | +}; |
2 | 6 |
|
3 | 7 | use clap::Parser;
|
4 | 8 |
|
@@ -156,7 +160,20 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
156 | 160 |
|
157 | 161 | let mut typos_found = false;
|
158 | 162 | let mut errors_found = false;
|
159 |
| - for path in args.path.iter() { |
| 163 | + |
| 164 | + let paths_from_stdin = if args.stdin_paths { |
| 165 | + io::stdin() |
| 166 | + .lines() |
| 167 | + .map(|res| res.map(PathBuf::from)) |
| 168 | + .collect::<Result<_, _>>() |
| 169 | + .with_code(proc_exit::sysexits::IO_ERR)? |
| 170 | + } else if args.stdin_paths0 { |
| 171 | + unix_read_paths_from_stdin()? |
| 172 | + } else { |
| 173 | + vec![] |
| 174 | + }; |
| 175 | + |
| 176 | + for path in args.path.iter().chain(&paths_from_stdin) { |
160 | 177 | let cwd = if path == std::path::Path::new("-") {
|
161 | 178 | global_cwd.clone()
|
162 | 179 | } else if path.is_file() {
|
@@ -269,6 +286,46 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
269 | 286 | }
|
270 | 287 | }
|
271 | 288 |
|
| 289 | +#[cfg(target_family = "unix")] |
| 290 | +fn unix_read_paths_from_stdin() -> Result<Vec<PathBuf>, proc_exit::Exit> { |
| 291 | + use std::ffi::OsString; |
| 292 | + use std::os::unix::ffi::OsStringExt; |
| 293 | + |
| 294 | + let mut buf = Vec::new(); |
| 295 | + io::stdin() |
| 296 | + .read_to_end(&mut buf) |
| 297 | + .with_code(proc_exit::sysexits::IO_ERR)?; |
| 298 | + |
| 299 | + Ok(buf |
| 300 | + .into_iter() |
| 301 | + // ensure we always end with a terminator |
| 302 | + .chain(iter::once(0)) |
| 303 | + .fold( |
| 304 | + (vec![], vec![]), |
| 305 | + |(mut paths, mut cur_path): (Vec<PathBuf>, Vec<u8>), byte| { |
| 306 | + if byte == 0 { |
| 307 | + if cur_path.is_empty() { |
| 308 | + // ignore duplicated \0 |
| 309 | + // TODO: is this OK? If not, we could not append trailing 0, and handle "rest" after `fold` ends |
| 310 | + (paths, cur_path) |
| 311 | + } else { |
| 312 | + paths.push(PathBuf::from(OsString::from_vec(cur_path))); |
| 313 | + (paths, vec![]) |
| 314 | + } |
| 315 | + } else { |
| 316 | + cur_path.push(byte); |
| 317 | + (paths, cur_path) |
| 318 | + } |
| 319 | + }, |
| 320 | + ) |
| 321 | + .0) |
| 322 | +} |
| 323 | + |
| 324 | +#[cfg(not(target_family = "unix"))] |
| 325 | +fn unix_read_paths_from_stdin() -> Result<Vec<PathBuf>, proc_exit::Exit> { |
| 326 | + Err(proc_exit::sysexits::CONFIG_ERR) |
| 327 | +} |
| 328 | + |
272 | 329 | fn init_logging(level: Option<log::Level>) {
|
273 | 330 | if let Some(level) = level {
|
274 | 331 | let mut builder = env_logger::Builder::new();
|
|
0 commit comments