| use std::env; |
| use std::fs; |
| use std::path::{Path, PathBuf}; |
| |
| /// The expected extension of rustfmt manifest files generated by `rustfmt_aspect`. |
| pub const RUSTFMT_MANIFEST_EXTENSION: &str = "rustfmt"; |
| |
| /// Generate an absolute path to a file without resolving symlinks |
| fn absolutify_existing<T: AsRef<Path>>(path: &T) -> std::io::Result<PathBuf> { |
| let absolute_path = if path.as_ref().is_absolute() { |
| path.as_ref().to_owned() |
| } else { |
| std::env::current_dir() |
| .expect("Failed to get working directory") |
| .join(path) |
| }; |
| std::fs::metadata(&absolute_path).map(|_| absolute_path) |
| } |
| |
| /// A struct containing details used for executing rustfmt. |
| #[derive(Debug)] |
| pub struct RustfmtConfig { |
| /// The rustfmt binary from the currently active toolchain |
| pub rustfmt: PathBuf, |
| |
| /// The rustfmt config file containing rustfmt settings. |
| /// https://rust-lang.github.io/rustfmt/ |
| pub config: PathBuf, |
| } |
| |
| /// Parse command line arguments and environment variables to |
| /// produce config data for running rustfmt. |
| pub fn parse_rustfmt_config() -> RustfmtConfig { |
| RustfmtConfig { |
| rustfmt: absolutify_existing(&env!("RUSTFMT")).expect("Unable to find rustfmt binary"), |
| config: absolutify_existing(&env!("RUSTFMT_CONFIG")) |
| .expect("Unable to find rustfmt config file"), |
| } |
| } |
| |
| /// A struct of target specific information for use in running `rustfmt`. |
| #[derive(Debug)] |
| pub struct RustfmtManifest { |
| /// The Rust edition of the Bazel target |
| pub edition: String, |
| |
| /// A list of all (non-generated) source files for formatting. |
| pub sources: Vec<String>, |
| } |
| |
| /// Parse rustfmt flags from a manifest generated by builds using `rustfmt_aspect`. |
| pub fn parse_rustfmt_manifest(manifest: &Path) -> RustfmtManifest { |
| let content = fs::read_to_string(manifest) |
| .unwrap_or_else(|_| panic!("Failed to read rustfmt manifest: {}", manifest.display())); |
| |
| let mut lines: Vec<String> = content |
| .split('\n') |
| .into_iter() |
| .filter(|s| !s.is_empty()) |
| .map(|s| s.to_owned()) |
| .collect(); |
| |
| let edition = lines |
| .pop() |
| .expect("There should always be at least 1 line in the manifest"); |
| edition |
| .parse::<i32>() |
| .expect("The edition should be a numeric value. eg `2018`."); |
| |
| RustfmtManifest { |
| edition, |
| sources: lines, |
| } |
| } |