Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uv install python into tools path #151

Merged
merged 2 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/env_vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ impl EnvVars {
pub const PRE_COMMIT_ALLOW_NO_CONFIG: &'static str = "PRE_COMMIT_ALLOW_NO_CONFIG";
pub const PRE_COMMIT_NO_CONCURRENCY: &'static str = "PRE_COMMIT_NO_CONCURRENCY";
pub const _PRE_COMMIT_SKIP_POST_CHECKOUT: &'static str = "_PRE_COMMIT_SKIP_POST_CHECKOUT";

pub const UV_NO_CACHE: &'static str = "UV_NO_CACHE";
pub const UV_PYTHON_INSTALL_DIR: &'static str = "UV_PYTHON_INSTALL_DIR";
}
16 changes: 11 additions & 5 deletions src/languages/python/impl.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use crate::config::LanguageVersion;
use crate::env_vars::EnvVars;
use crate::hook::Hook;
use crate::languages::python::uv::UvInstaller;
use crate::languages::LanguageImpl;
use crate::process::Cmd;
use crate::run::run_by_batch;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use crate::store::{Store, ToolBucket};

#[derive(Debug, Copy, Clone)]
pub struct Python;
Expand All @@ -23,17 +25,21 @@ impl LanguageImpl for Python {

let uv = UvInstaller::install().await?;

let store = Store::from_settings()?;
let python_install_dir = store.tools_path(ToolBucket::Python);

let uv_cmd = |summary| {
#[allow(unused_mut)]
let mut cmd = Cmd::new(&uv, summary);
// Don't use cache in Windows, multiple uv instances will conflict with each other.
// See https://github.com/astral-sh/uv/issues/8664
#[cfg(windows)]
cmd.env("UV_NO_CACHE", "1");
cmd.env(EnvVars::UV_NO_CACHE, "1");

cmd.env(EnvVars::UV_PYTHON_INSTALL_DIR, &python_install_dir);
cmd
};

// TODO: Set uv cache dir? tools dir? python dir?
// Create venv
let mut cmd = uv_cmd("create venv");
cmd.arg("venv").arg(&venv);
Expand Down
4 changes: 2 additions & 2 deletions src/languages/python/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use tracing::{debug, enabled, trace, warn};

use crate::fs::LockedFile;
use crate::process::Cmd;
use crate::store::Store;
use crate::store::{Store, ToolBucket};

// The version of `uv` to install. Should update periodically.
const UV_VERSION: &str = "0.5.8";
Expand Down Expand Up @@ -207,7 +207,7 @@ impl UvInstaller {
// 2) Check if `uv` is installed by `prefligit`
let store = Store::from_settings()?;

let uv_dir = store.uv_path();
let uv_dir = store.tools_path(ToolBucket::Uv);
let uv = uv_dir.join("uv").with_extension(env::consts::EXE_EXTENSION);
if uv.is_file() {
trace!(uv = %uv.display(), "Found managed uv");
Expand Down
67 changes: 46 additions & 21 deletions src/store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::path::{Path, PathBuf};
use std::sync::LazyLock;

use anyhow::Result;
use rusqlite::Connection;
Expand Down Expand Up @@ -29,6 +30,28 @@ pub enum Error {
Git(#[from] crate::git::Error),
}

static STORE_HOME: LazyLock<Option<PathBuf>> = LazyLock::new(|| {
if let Some(path) = std::env::var_os(EnvVars::PRE_COMMIT_HOME) {
debug!(
path = %path.to_string_lossy(),
"Loading store from PRE_COMMIT_HOME",
);
Some(path.into())
} else if let Some(path) = std::env::var_os(EnvVars::XDG_CACHE_HOME) {
let path = PathBuf::from(path).join("pre-commit");
debug!(
path = %path.to_string_lossy(),
"Loading store from XDG_CACHE_HOME",
);
Some(path)
} else {
let home = home::home_dir()?;
let path = home.join(".cache").join("pre-commit");
debug!(path = %path.display(), "Loading store from ~/.cache");
Some(path)
}
});

/// A store for managing repos.
#[derive(Debug)]
pub struct Store {
Expand All @@ -38,25 +61,9 @@ pub struct Store {

impl Store {
pub fn from_settings() -> Result<Self, Error> {
if let Some(path) = std::env::var_os(EnvVars::PRE_COMMIT_HOME) {
debug!(
path = %path.to_string_lossy(),
"Loading store from PRE_COMMIT_HOME",
);
return Ok(Self::from_path(path));
} else if let Some(path) = std::env::var_os(EnvVars::XDG_CACHE_HOME) {
let path = PathBuf::from(path).join("pre-commit");
debug!(
path = %path.to_string_lossy(),
"Loading store from XDG_CACHE_HOME",
);
return Ok(Self::from_path(path));
}

let home = home::home_dir().ok_or(Error::HomeNotFound)?;
let path = home.join(".cache").join("pre-commit");
debug!(path = %path.display(), "Loading store from ~/.cache");
Ok(Self::from_path(path))
Ok(Self::from_path(
STORE_HOME.as_ref().ok_or(Error::HomeNotFound)?,
))
}

pub fn from_path(path: impl Into<PathBuf>) -> Self {
Expand Down Expand Up @@ -267,8 +274,26 @@ impl Store {
LockedFile::acquire(self.path.join(".lock"), "store").await
}

pub fn uv_path(&self) -> PathBuf {
self.path.join("tools").join("uv")
/// The path to the tool directory in the store.
pub fn tools_path(&self, tool: ToolBucket) -> PathBuf {
self.path.join("tools").join(tool.as_str())
}
}

#[derive(Copy, Clone)]
pub enum ToolBucket {
Uv,
Python,
Node,
}

impl ToolBucket {
pub fn as_str(&self) -> &str {
match self {
ToolBucket::Uv => "uv",
ToolBucket::Python => "python",
ToolBucket::Node => "node",
}
}
}

Expand Down
Loading