Anki/build/runner/src/pyenv.rs

53 lines
1.6 KiB
Rust

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use std::fs;
use std::process::Command;
use camino::Utf8Path;
use clap::Args;
use crate::run::run_command;
#[derive(Args)]
pub struct PyenvArgs {
uv_bin: String,
pyenv_folder: String,
#[arg(trailing_var_arg = true)]
extra_args: Vec<String>,
}
/// 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);
// On first run, ninja creates an empty bin/ folder which breaks the initial
// install. But we don't want to indiscriminately remove the folder, or
// macOS Gatekeeper needs to rescan the files each time.
if pyenv_folder.exists() {
let cache_tag = pyenv_folder.join("CACHEDIR.TAG");
if !cache_tag.exists() {
fs::remove_dir_all(pyenv_folder).expect("Failed to remove existing pyenv folder");
}
}
let mut command = Command::new(args.uv_bin);
// remove UV_* environment variables to avoid interference
for (key, _) in std::env::vars() {
if key.starts_with("UV_") || key == "VIRTUAL_ENV" {
command.env_remove(key);
}
}
run_command(
command
.env("UV_PROJECT_ENVIRONMENT", args.pyenv_folder.clone())
.args(["sync", "--locked", "--no-config"])
.args(args.extra_args),
);
// Write empty stamp file
fs::write(pyenv_folder.join(".stamp"), "").expect("Failed to write stamp file");
}