1 // Copyright 2023 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 extern crate core;
16 
17 use clap::Parser as _;
18 use cmd_runner::run_cmd_shell;
19 use env_logger::Env;
20 use std::{env, path};
21 
22 mod ctap_protocol;
23 mod platform;
24 mod remote_auth_protocol;
25 
main() -> anyhow::Result<()>26 fn main() -> anyhow::Result<()> {
27     env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
28     let cli: Cli = Cli::parse();
29 
30     let root_dir: path::PathBuf = env::var("CARGO_MANIFEST_DIR")
31         .expect("Must be run via Cargo to establish root directory")
32         .into();
33 
34     match cli.subcommand {
35         Subcommand::CheckEverything(ref options) => check_everything(&root_dir, options)?,
36         Subcommand::CheckWorkspace(ref options) => check_workspace(&root_dir, options)?,
37         Subcommand::CheckCtapProtocol => ctap_protocol::check_ctap_protocol(&root_dir)?,
38         Subcommand::CheckPlatform => platform::check_platform(&root_dir)?,
39         Subcommand::CheckRemoteAuthProtocol => {
40             remote_auth_protocol::check_remote_auth_protocol(&root_dir)?
41         }
42     }
43 
44     Ok(())
45 }
46 
check_everything(root: &path::Path, check_options: &CheckOptions) -> anyhow::Result<()>47 pub fn check_everything(root: &path::Path, check_options: &CheckOptions) -> anyhow::Result<()> {
48     check_workspace(root, check_options)?;
49     ctap_protocol::check_ctap_protocol(root)?;
50     platform::check_platform(root)?;
51     remote_auth_protocol::check_remote_auth_protocol(root)?;
52     Ok(())
53 }
54 
check_workspace(root: &path::Path, options: &CheckOptions) -> anyhow::Result<()>55 pub fn check_workspace(root: &path::Path, options: &CheckOptions) -> anyhow::Result<()> {
56     log::info!("Running cargo checks on workspace");
57 
58     let fmt_command = if options.reformat {
59         "cargo fmt"
60     } else {
61         "cargo fmt --check"
62     };
63 
64     for cargo_cmd in [
65         fmt_command,
66         "cargo check --workspace --all-targets --quiet",
67         "cargo test --workspace --quiet -- --color=always",
68         "cargo doc --quiet --no-deps",
69         "cargo deny --workspace check",
70         "cargo clippy --all-targets --workspace -- --deny warnings",
71     ] {
72         run_cmd_shell(root, cargo_cmd)?;
73     }
74 
75     Ok(())
76 }
77 
78 #[derive(clap::Parser)]
79 struct Cli {
80     #[clap(subcommand)]
81     subcommand: Subcommand,
82 }
83 
84 #[derive(clap::Subcommand, Debug, Clone)]
85 #[allow(clippy::enum_variant_names)]
86 enum Subcommand {
87     /// Checks everything in remoteauth
88     CheckEverything(CheckOptions),
89     /// Checks everything included in the top level workspace
90     CheckWorkspace(CheckOptions),
91     /// Build and run tests for the CTAP Protocol
92     CheckCtapProtocol,
93     /// Builds and run tests for the Platform
94     CheckPlatform,
95     /// Builds and run tests for the Remote Auth Protocol
96     CheckRemoteAuthProtocol,
97 }
98 
99 #[derive(clap::Args, Debug, Clone, Default)]
100 pub struct CheckOptions {
101     #[arg(long, help = "reformat files with cargo fmt")]
102     reformat: bool,
103 }
104