• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use std::ffi::OsStr;
16 
17 use xshell::cmd;
18 
19 #[derive(clap::Subcommand, Debug, Clone)]
20 pub enum CargoWorkspaceSubcommand {
21     /// Checks test, clippy, and cargo deny in the workspace
22     CheckWorkspace(CargoOptions),
23     /// Checks the formatting of the workspace
24     CheckFormat(FormatterOptions),
25 }
26 
27 impl CargoWorkspaceSubcommand {
run(&self, tag: &str, sh: &xshell::Shell) -> anyhow::Result<()>28     pub fn run(&self, tag: &str, sh: &xshell::Shell) -> anyhow::Result<()> {
29         match self {
30             CargoWorkspaceSubcommand::CheckWorkspace(cargo_options) => {
31                 cargo_options.check_workspace(sh, tag)
32             }
33             CargoWorkspaceSubcommand::CheckFormat(formatter_options) => {
34                 formatter_options.check_format(sh)
35             }
36         }
37     }
38 }
39 
40 #[derive(clap::Args, Debug, Clone, Default)]
41 pub struct CargoOptions {
42     #[arg(long, help = "whether to run cargo with --locked")]
43     locked: bool,
44     #[arg(long, help = "gather coverage metrics")]
45     coverage: bool,
46 }
47 
48 impl CargoOptions {
49     /// Run `cargo test` or `cargo llvm-cov` depending on the configured options.
test<'sh, S: AsRef<OsStr>>( &self, sh: &'sh xshell::Shell, tag: &str, args: impl IntoIterator<Item = S>, ) -> xshell::Cmd<'sh>50     pub fn test<'sh, S: AsRef<OsStr>>(
51         &self,
52         sh: &'sh xshell::Shell,
53         tag: &str,
54         args: impl IntoIterator<Item = S>,
55     ) -> xshell::Cmd<'sh> {
56         let locked = if self.locked { "--locked" } else { "" };
57         if self.coverage {
58             cmd!(
59                 sh,
60                 "cargo llvm-cov {locked} {args...} --lcov --output-path target/{tag}.info -- --color=always"
61             )
62         } else {
63             cmd!(sh, "cargo test {locked} {args...} -- --color=always")
64         }
65     }
66 
67     /// Run the default set of checks on a cargo workspace
check_workspace(&self, sh: &xshell::Shell, tag: &str) -> anyhow::Result<()>68     pub fn check_workspace(&self, sh: &xshell::Shell, tag: &str) -> anyhow::Result<()> {
69         self.test(sh, tag, ["--workspace"]).run()?;
70         cmd!(
71             sh,
72             "cargo clippy --all-targets --workspace -- --deny warnings"
73         )
74         .run()?;
75         cmd!(sh, "cargo deny --workspace check").run()?;
76         // ensure the docs are valid (cross-references to other code, etc)
77         cmd!(
78             sh,
79             "cargo doc --quiet --workspace --no-deps --document-private-items
80                 --target-dir target/dist_docs/{tag}"
81         )
82         .env("RUSTDOCFLAGS", "--deny warnings")
83         .run()?;
84         Ok(())
85     }
86 }
87 
88 #[derive(clap::Args, Debug, Clone, Default)]
89 pub struct FormatterOptions {
90     #[arg(
91         long,
92         help = "reformat files files in the workspace with the code formatter"
93     )]
94     pub reformat: bool,
95 }
96 
97 impl FormatterOptions {
check_format(&self, sh: &xshell::Shell) -> anyhow::Result<()>98     pub fn check_format(&self, sh: &xshell::Shell) -> anyhow::Result<()> {
99         if self.reformat {
100             cmd!(sh, "cargo fmt").run()?;
101         } else {
102             cmd!(sh, "cargo fmt --check").run()?;
103         }
104         Ok(())
105     }
106 }
107