• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::env;
2 use std::fs;
3 use std::path::{Path, PathBuf};
4 
5 /// The expected extension of rustfmt manifest files generated by `rustfmt_aspect`.
6 pub const RUSTFMT_MANIFEST_EXTENSION: &str = "rustfmt";
7 
8 /// A struct containing details used for executing rustfmt.
9 #[derive(Debug)]
10 pub 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.
parse_rustfmt_config() -> RustfmtConfig21 pub fn parse_rustfmt_config() -> RustfmtConfig {
22     let runfiles = runfiles::Runfiles::create().unwrap();
23 
24     let rustfmt = runfiles.rlocation(format!(
25         "{}/{}",
26         runfiles.current_repository(),
27         env!("RUSTFMT")
28     ));
29     if !rustfmt.exists() {
30         panic!("rustfmt does not exist at: {}", rustfmt.display());
31     }
32 
33     let config = runfiles.rlocation(format!(
34         "{}/{}",
35         runfiles.current_repository(),
36         env!("RUSTFMT_CONFIG")
37     ));
38     if !config.exists() {
39         panic!(
40             "rustfmt config file does not exist at: {}",
41             config.display()
42         );
43     }
44 
45     RustfmtConfig { rustfmt, config }
46 }
47 
48 /// A struct of target specific information for use in running `rustfmt`.
49 #[derive(Debug)]
50 pub struct RustfmtManifest {
51     /// The Rust edition of the Bazel target
52     pub edition: String,
53 
54     /// A list of all (non-generated) source files for formatting.
55     pub sources: Vec<PathBuf>,
56 }
57 
58 /// Parse rustfmt flags from a manifest generated by builds using `rustfmt_aspect`.
parse_rustfmt_manifest(manifest: &Path) -> RustfmtManifest59 pub fn parse_rustfmt_manifest(manifest: &Path) -> RustfmtManifest {
60     let content = fs::read_to_string(manifest)
61         .unwrap_or_else(|_| panic!("Failed to read rustfmt manifest: {}", manifest.display()));
62 
63     let mut lines: Vec<String> = content
64         .split('\n')
65         .filter(|s| !s.is_empty())
66         .map(|s| s.to_owned())
67         .collect();
68 
69     let edition = lines
70         .pop()
71         .expect("There should always be at least 1 line in the manifest");
72     edition
73         .parse::<i32>()
74         .expect("The edition should be a numeric value. eg `2018`.");
75 
76     let runfiles = runfiles::Runfiles::create().unwrap();
77 
78     RustfmtManifest {
79         edition,
80         sources: lines
81             .into_iter()
82             .map(|src| runfiles.rlocation(format!("{}/{}", runfiles.current_repository(), src)))
83             .collect(),
84     }
85 }
86 
87 #[cfg(target_family = "windows")]
88 const PATH_ENV_SEP: &str = ";";
89 
90 #[cfg(target_family = "unix")]
91 const PATH_ENV_SEP: &str = ":";
92 
93 /// Parse the runfiles of the current executable for manifests generated
94 /// by the `rustfmt_aspect` aspect.
find_manifests() -> Vec<PathBuf>95 pub fn find_manifests() -> Vec<PathBuf> {
96     let runfiles = runfiles::Runfiles::create().unwrap();
97 
98     std::env::var("RUSTFMT_MANIFESTS")
99         .map(|var| {
100             var.split(PATH_ENV_SEP)
101                 .filter_map(|path| match path.is_empty() {
102                     true => None,
103                     false => Some(runfiles.rlocation(format!(
104                         "{}/{}",
105                         runfiles.current_repository(),
106                         path
107                     ))),
108                 })
109                 .collect()
110         })
111         .unwrap_or_default()
112 }
113