flowey_lib_common/
run_cargo_clippy.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Clippy
5
6use crate::run_cargo_build::CargoBuildProfile;
7use crate::run_cargo_build::CargoFeatureSet;
8use flowey::node::prelude::*;
9
10#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
11pub enum CargoPackage {
12    Workspace,
13    Crate(String),
14}
15
16flowey_request! {
17    pub struct Request {
18        pub in_folder: ReadVar<PathBuf>,
19        pub package: CargoPackage,
20        pub profile: CargoBuildProfile,
21        pub features: CargoFeatureSet,
22        pub target: target_lexicon::Triple,
23        pub extra_env: Option<Vec<(String, String)>>,
24        pub exclude: ReadVar<Option<Vec<String>>>,
25        pub keep_going: bool,
26        pub all_targets: bool,
27        /// Wait for specified side-effects to resolve before running cargo-run.
28        ///
29        /// (e.g: to allow for some ambient packages / dependencies to get
30        /// installed).
31        pub pre_build_deps: Vec<ReadVar<SideEffect>>,
32        pub done: WriteVar<SideEffect>,
33    }
34}
35
36new_flow_node!(struct Node);
37
38impl FlowNode for Node {
39    type Request = Request;
40
41    fn imports(ctx: &mut ImportCtx<'_>) {
42        ctx.import::<crate::cfg_cargo_common_flags::Node>();
43        ctx.import::<crate::install_rust::Node>();
44    }
45
46    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
47        let rust_toolchain = ctx.reqv(crate::install_rust::Request::GetRustupToolchain);
48        let flags = ctx.reqv(crate::cfg_cargo_common_flags::Request::GetFlags);
49
50        for Request {
51            in_folder,
52            package,
53            profile,
54            features,
55            target,
56            extra_env,
57            exclude,
58            keep_going,
59            all_targets,
60            pre_build_deps,
61            done,
62        } in requests
63        {
64            ctx.req(crate::install_rust::Request::InstallTargetTriple(
65                target.clone(),
66            ));
67
68            ctx.emit_rust_step("cargo clippy", |ctx| {
69                pre_build_deps.claim(ctx);
70                done.claim(ctx);
71                let rust_toolchain = rust_toolchain.clone().claim(ctx);
72                let flags = flags.clone().claim(ctx);
73                let in_folder = in_folder.claim(ctx);
74                let exclude = exclude.claim(ctx);
75                move |rt| {
76                    let rust_toolchain = rt.read(rust_toolchain);
77                    let flags = rt.read(flags);
78                    let in_folder = rt.read(in_folder);
79                    let exclude = rt.read(exclude);
80
81                    let crate::cfg_cargo_common_flags::Flags { locked, verbose } = flags;
82
83                    let target = target.to_string();
84
85                    let cargo_profile = match &profile {
86                        CargoBuildProfile::Debug => "dev",
87                        CargoBuildProfile::Release => "release",
88                        CargoBuildProfile::Custom(s) => s,
89                    };
90
91                    let mut args = Vec::new();
92
93                    args.push("clippy");
94                    if verbose {
95                        args.push("--verbose");
96                    }
97                    if locked {
98                        args.push("--locked");
99                    }
100                    if keep_going {
101                        args.push("--keep-going");
102                    }
103                    if all_targets {
104                        args.push("--all-targets");
105                    }
106                    match &package {
107                        CargoPackage::Workspace => args.push("--workspace"),
108                        CargoPackage::Crate(crate_name) => {
109                            args.push("-p");
110                            args.push(crate_name);
111                        }
112                    }
113                    let feature_strings = features.to_cargo_arg_strings();
114                    args.extend(feature_strings.iter().map(|s| s.as_str()));
115                    args.push("--target");
116                    args.push(&target);
117                    args.push("--profile");
118                    args.push(cargo_profile);
119                    if let Some(exclude) = &exclude {
120                        for excluded_crate in exclude {
121                            args.push("--exclude");
122                            args.push(excluded_crate);
123                        }
124                    }
125
126                    let sh = xshell::Shell::new()?;
127
128                    sh.change_dir(in_folder);
129
130                    let mut cmd = if let Some(rust_toolchain) = &rust_toolchain {
131                        xshell::cmd!(sh, "rustup run {rust_toolchain} cargo")
132                    } else {
133                        xshell::cmd!(sh, "cargo")
134                    };
135
136                    // if running in CI, no need to waste time with incremental
137                    // build artifacts
138                    if !matches!(rt.backend(), FlowBackend::Local) {
139                        cmd = cmd.env("CARGO_INCREMENTAL", "0");
140                    }
141                    if let Some(env) = extra_env {
142                        for (key, val) in env {
143                            log::info!("env: {key}={val}");
144                            cmd = cmd.env(key, val);
145                        }
146                    }
147
148                    cmd.args(args).run()?;
149
150                    Ok(())
151                }
152            });
153        }
154
155        Ok(())
156    }
157}