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