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
use colored::*;
use std::path::PathBuf;

mod cmd;
mod dependencies;
mod error;
#[cfg(unix)]
mod execv;
mod lock;
mod operations;
mod paths;
mod project;
mod python_info;
mod run;
mod settings;
#[cfg(windows)]
mod win_job;

pub use crate::cmd::Command;
use crate::cmd::SubCommand;
pub use crate::cmd::{print_error, print_info_1, print_info_2};
pub use crate::error::Error;
use crate::operations::{InitOptions, LockOptions};
pub use crate::paths::{DEV_LOCK_FILENAME, PROD_LOCK_FILENAME};
use crate::project::{PostInstallAction, Project};
use crate::python_info::PythonInfo;
pub use crate::settings::Settings;

pub fn run(cmd: Command) -> Result<(), Error> {
    let settings = Settings::from_shell(&cmd);
    let project_path = if let Some(project_path) = cmd.project_path {
        PathBuf::from(project_path)
    } else {
        std::env::current_dir().map_err(|e| Error::Other {
            message: format!("Could not get current directory: {}", e),
        })?
    };
    // Perform additional sanity checks when using `dmenv run`
    // TODO: try and handle this using StructOpt instead
    if let SubCommand::Run { ref cmd, .. } = cmd.sub_cmd {
        if cmd.is_empty() {
            return Err(Error::Other {
                message: format!("Missing argument after '{}'", "run".green()),
            });
        }
    }
    let python_info = PythonInfo::new(&cmd.python_binary)?;
    let mut project = Project::new(project_path, python_info, settings)?;

    // Note: keep the `match()` here so that we know every variant of the SubCommand
    // enum is handled.
    match &cmd.sub_cmd {
        SubCommand::Install {
            no_develop,
            system_site_packages,
        } => {
            if *system_site_packages {
                project.use_system_site_packages()
            }
            let post_install_action = if *no_develop {
                PostInstallAction::None
            } else {
                PostInstallAction::RunSetupPyDevelop
            };
            project.install(post_install_action)
        }
        SubCommand::Clean {} => project.clean(),
        SubCommand::Develop {} => project.develop(),
        SubCommand::Init {
            name,
            version,
            author,
            no_setup_cfg,
        } => {
            let mut options = InitOptions::new(name, version, author);
            if *no_setup_cfg {
                options.no_setup_cfg()
            };
            project.init(&options)
        }
        SubCommand::Lock {
            python_version,
            sys_platform,
            system_site_packages,
        } => {
            let lock_options = LockOptions {
                python_version: python_version.clone(),
                sys_platform: sys_platform.clone(),
            };
            if *system_site_packages {
                project.use_system_site_packages();
            }
            project.lock(&lock_options)
        }
        SubCommand::BumpInLock { name, version, git } => project.bump_in_lock(name, version, *git),
        SubCommand::Run { ref cmd, no_exec } => {
            if *no_exec {
                project.run_no_exec(cmd)
            } else {
                project.run(cmd)
            }
        }
        SubCommand::ShowDeps {} => project.show_deps(),
        SubCommand::ShowOutDated {} => project.show_outdated(),
        SubCommand::ShowVenvPath {} => project.show_venv_path(),
        SubCommand::ShowVenvBin {} => project.show_venv_bin_path(),

        SubCommand::UpgradePip {} => project.upgrade_pip(),
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_not_in_venv() {
        if std::env::var("VIRTUAL_ENV").is_ok() {
            panic!("Please exit virtualenv before running tests");
        }
    }
}