1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! # installer
//!
//! Installs external dependencies for tasks.<br>
//! There are 2 types of dependencies: install_crate, install_script.<br>
//! install_crate ensures the crate command is available and if not installs the crate based on the provided name.<br>
//! install_script always gets executed before the task command.
//!

#[cfg(test)]
#[path = "./installer_test.rs"]
mod installer_test;

use command;
use std::process::Command;
use types::Task;

fn is_crate_installed(crate_name: &str) -> bool {
    debug!("Getting list of installed cargo commands.");
    let result = Command::new("cargo").arg("--list").output();

    match result {
        Ok(output) => {
            let mut found = false;

            let exit_code = command::get_exit_code(Ok(output.status), false);
            command::validate_exit_code(exit_code);

            let stdout = String::from_utf8_lossy(&output.stdout);
            let lines: Vec<&str> = stdout.split(' ').collect();
            for mut line in lines {
                line = line.trim();

                debug!("Checking: {}", &line);

                if line.contains(crate_name) && crate_name.contains(line) {
                    found = true;
                    debug!("Found installed crate.");

                    break;
                }
            }

            found
        }
        Err(error) => {
            error!("Unable to check if crate is installed: {} {:#?}", crate_name, &error);
            false
        }
    }
}

fn get_install_crate_args(
    crate_name: &str,
    args: &Option<Vec<String>>,
) -> Vec<String> {
    let mut install_args = vec!["install".to_string()];

    match *args {
        Some(ref args_vec) => {
            for arg in args_vec.iter() {
                install_args.push(arg.to_string());
            }
        }
        None => debug!("No crate installation args defined."),
    };

    install_args.push(crate_name.to_string());

    install_args
}

pub fn install_crate(
    cargo_command: &str,
    crate_name: &str,
    args: &Option<Vec<String>>,
    validate: bool,
) {
    if !is_crate_installed(cargo_command) {
        let install_args = get_install_crate_args(crate_name, args);

        command::run_command("cargo", &Some(install_args), validate);
    }
}

pub fn install(task_config: &Task) {
    let validate = !task_config.is_force();

    match task_config.install_crate {
        Some(ref crate_name) => {
            let cargo_command = match task_config.args {
                Some(ref args) => &args[0],
                None => {
                    error!("Missing cargo command to invoke.");
                    panic!("Missing cargo command to invoke.");
                }
            };

            install_crate(cargo_command, crate_name, &task_config.install_crate_args, validate);
        }
        None => {
            match task_config.install_script {
                Some(ref script) => {
                    command::run_script(&script, task_config.script_runner.clone(), validate);
                    ()
                }
                None => {
                    match task_config.command {
                        Some(ref command) => {
                            if command == "cargo" {
                                match task_config.args {
                                    Some(ref args) => {
                                        // create crate name
                                        let mut crate_name = "cargo-".to_string();
                                        crate_name = crate_name + &args[0];

                                        install_crate(&args[0], &crate_name, &task_config.install_crate_args, validate);
                                    }
                                    None => debug!("No installation script defined."),
                                }
                            }
                        }
                        None => debug!("No installation script defined."),
                    }
                }
            }
        }
    }
}