cli/installer/
crate_installer.rs

1//! # crate_installer
2//!
3//! Installs crates via rustup/cargo.
4//!
5
6#[cfg(test)]
7#[path = "crate_installer_test.rs"]
8mod crate_installer_test;
9
10use crate::command;
11use crate::error::CargoMakeError;
12use crate::installer::crate_version_check;
13use crate::installer::{cargo_plugin_installer, rustup_component_installer};
14use crate::toolchain::wrap_command;
15use crate::types::{CommandSpec, InstallCrateInfo, InstallRustupComponentInfo, ToolchainSpecifier};
16
17fn invoke_rustup_install(toolchain: &Option<ToolchainSpecifier>, info: &InstallCrateInfo) -> bool {
18    match info.rustup_component_name {
19        Some(ref component) => {
20            let rustup_component_info = InstallRustupComponentInfo {
21                rustup_component_name: component.to_string(),
22                binary: Some(info.binary.clone()),
23                test_arg: Some(info.test_arg.clone()),
24            };
25            rustup_component_installer::invoke_rustup_install(&toolchain, &rustup_component_info)
26        }
27        None => false,
28    }
29}
30
31fn invoke_cargo_install(
32    toolchain: &Option<ToolchainSpecifier>,
33    info: &InstallCrateInfo,
34    args: &Option<Vec<String>>,
35    validate: bool,
36) -> Result<(), CargoMakeError> {
37    let (automatic_lock_version, version_option) = if info.min_version.is_some() {
38        (false, &info.min_version)
39    } else {
40        (info.version.is_some(), &info.version)
41    };
42
43    let remove_lock =
44        if automatic_lock_version && !envmnt::is("CARGO_MAKE_CRATE_INSTALLATION_LOCKED") {
45            envmnt::set_bool("CARGO_MAKE_CRATE_INSTALLATION_LOCKED", true);
46            true
47        } else {
48            false
49        };
50
51    let install_args = cargo_plugin_installer::get_install_crate_args(
52        &info.crate_name,
53        info.force.unwrap_or(true),
54        &args,
55        version_option,
56        &info.install_command,
57    );
58
59    let command_spec = match toolchain {
60        Some(ref toolchain_string) => wrap_command(toolchain_string, "cargo", &Some(install_args)),
61        None => CommandSpec {
62            command: "cargo".to_string(),
63            args: Some(install_args),
64        },
65    };
66
67    command::run_command(&command_spec.command, &command_spec.args, validate)?;
68
69    if remove_lock {
70        envmnt::remove("CARGO_MAKE_CRATE_INSTALLATION_LOCKED");
71    }
72
73    Ok(())
74}
75
76fn is_crate_only_info(info: &InstallCrateInfo) -> bool {
77    match info.rustup_component_name {
78        Some(_) => false,
79        None => true,
80    }
81}
82
83pub(crate) fn install(
84    toolchain: &Option<ToolchainSpecifier>,
85    info: &InstallCrateInfo,
86    args: &Option<Vec<String>>,
87    validate: bool,
88) -> Result<(), CargoMakeError> {
89    let installed =
90        rustup_component_installer::is_installed(&toolchain, &info.binary, &info.test_arg);
91    let crate_only_info = is_crate_only_info(&info);
92    let run_installation = if !installed {
93        true
94    } else if crate_only_info && toolchain.is_none() {
95        match info.min_version {
96            Some(ref version) => !crate_version_check::is_min_version_valid(
97                &info.crate_name,
98                version,
99                Some(&info.binary),
100            ),
101            None => match info.version {
102                Some(ref version) => !crate_version_check::is_version_valid(
103                    &info.crate_name,
104                    version,
105                    Some(&info.binary),
106                ),
107                None => false,
108            },
109        }
110    } else {
111        false
112    };
113
114    if run_installation {
115        debug!("Crate: {} not installed.", &info.crate_name);
116
117        if !invoke_rustup_install(&toolchain, &info) {
118            invoke_cargo_install(&toolchain, &info, &args, validate)?;
119        }
120    }
121    Ok(())
122}