// Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html use std::process::Command; use camino::Utf8Path; use clap::Args; use crate::run::run_command; #[derive(Args)] pub struct PyenvArgs { python_bin: String, pyenv_folder: String, initial_reqs: String, reqs: Vec, #[arg(long, allow_hyphen_values(true))] venv_args: Vec, } /// Set up a venv if one doesn't already exist, and then sync packages with /// provided requirements file. pub fn setup_pyenv(args: PyenvArgs) { let pyenv_folder = Utf8Path::new(&args.pyenv_folder); let pyenv_bin_folder = pyenv_folder.join(if cfg!(windows) { "scripts" } else { "bin" }); let pyenv_python = pyenv_bin_folder.join("python"); let pip_sync = pyenv_bin_folder.join("pip-sync"); if !pyenv_python.exists() { run_command( Command::new(&args.python_bin) .args(["-m", "venv"]) .args(args.venv_args) .arg(pyenv_folder), ); if cfg!(windows) { // the first install on Windows throws an error the first time pip is upgraded, // so we install it twice and swallow the first error let _output = Command::new(&pyenv_python) .args(["-m", "pip", "install", "-r", &args.initial_reqs]) .output() .unwrap(); } run_command(Command::new(pyenv_python).args([ "-m", "pip", "install", "-r", &args.initial_reqs, ])); } run_command(Command::new(pip_sync).args(&args.reqs)); }