blob: 2d8accc276e4ab05bde8915231ae67baaed713da [file] [log] [blame]
Brian Silverman5f6f2762022-08-13 19:30:05 -07001use std::env;
2use std::fs;
3use std::path::{Path, PathBuf};
4
5/// The expected extension of rustfmt manifest files generated by `rustfmt_aspect`.
6pub const RUSTFMT_MANIFEST_EXTENSION: &str = "rustfmt";
7
8/// A struct containing details used for executing rustfmt.
9#[derive(Debug)]
10pub struct RustfmtConfig {
11 /// The rustfmt binary from the currently active toolchain
12 pub rustfmt: PathBuf,
13
14 /// The rustfmt config file containing rustfmt settings.
15 /// https://rust-lang.github.io/rustfmt/
16 pub config: PathBuf,
17}
18
19/// Parse command line arguments and environment variables to
20/// produce config data for running rustfmt.
21pub fn parse_rustfmt_config() -> RustfmtConfig {
22 let runfiles = runfiles::Runfiles::create().unwrap();
23
24 let rustfmt = runfiles.rlocation(concat!(env!("RUSTFMT_WORKSPACE"), "/", env!("RUSTFMT")));
25 if !rustfmt.exists() {
26 panic!("rustfmt does not exist at: {}", rustfmt.display());
27 }
28
29 let config = runfiles.rlocation(concat!(
30 env!("RUSTFMT_WORKSPACE"),
31 "/",
32 env!("RUSTFMT_CONFIG")
33 ));
34 if !config.exists() {
35 panic!(
36 "rustfmt config file does not exist at: {}",
37 config.display()
38 );
39 }
40
41 RustfmtConfig { rustfmt, config }
42}
43
44/// A struct of target specific information for use in running `rustfmt`.
45#[derive(Debug)]
46pub struct RustfmtManifest {
47 /// The Rust edition of the Bazel target
48 pub edition: String,
49
50 /// A list of all (non-generated) source files for formatting.
51 pub sources: Vec<PathBuf>,
52}
53
54/// Parse rustfmt flags from a manifest generated by builds using `rustfmt_aspect`.
55pub fn parse_rustfmt_manifest(manifest: &Path) -> RustfmtManifest {
56 let content = fs::read_to_string(manifest)
57 .unwrap_or_else(|_| panic!("Failed to read rustfmt manifest: {}", manifest.display()));
58
59 let mut lines: Vec<String> = content
60 .split('\n')
61 .into_iter()
62 .filter(|s| !s.is_empty())
63 .map(|s| s.to_owned())
64 .collect();
65
66 let edition = lines
67 .pop()
68 .expect("There should always be at least 1 line in the manifest");
69 edition
70 .parse::<i32>()
71 .expect("The edition should be a numeric value. eg `2018`.");
72
73 let runfiles = runfiles::Runfiles::create().unwrap();
74
75 RustfmtManifest {
76 edition,
77 sources: lines
78 .into_iter()
79 .map(|src| runfiles.rlocation(format!("{}/{}", env!("RUSTFMT_WORKSPACE"), src)))
80 .collect(),
81 }
82}
83
84#[cfg(target_family = "windows")]
85const PATH_ENV_SEP: &str = ";";
86
87#[cfg(target_family = "unix")]
88const PATH_ENV_SEP: &str = ":";
89
90/// Parse the runfiles of the current executable for manifests generated
91/// by the `rustfmt_aspect` aspect.
92pub fn find_manifests() -> Vec<PathBuf> {
93 let runfiles = runfiles::Runfiles::create().unwrap();
94
95 std::env::var("RUSTFMT_MANIFESTS")
96 .map(|var| {
97 var.split(PATH_ENV_SEP)
98 .map(|path| runfiles.rlocation(format!("{}/{}", env!("RUSTFMT_WORKSPACE"), path)))
99 .collect()
100 })
101 .unwrap_or_default()
102}