Skip to content

Commit

Permalink
create venv symlink on 'init_venv'
Browse files Browse the repository at this point in the history
  • Loading branch information
jpopesculian committed Feb 19, 2024
1 parent 64ecc55 commit 5c4574e
Showing 1 changed file with 46 additions and 7 deletions.
53 changes: 46 additions & 7 deletions src/dirs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ use crate::error::{self, Result};
use aqora_config::PyProject;
use aqora_runner::python::PyEnv;
use std::path::{Path, PathBuf};
use thiserror::Error;

const AQORA_DIRNAME: &str = ".aqora";
const DATA_DIRNAME: &str = "data";
const VENV_DIRNAME: &str = "venv";
const PYPROJECT_FILENAME: &str = "pyproject.toml";
const USE_CASE_FILENAME: &str = "use_case.toml";

pub async fn config_dir() -> Result<PathBuf> {
let mut path = dirs::data_dir().or_else(dirs::config_dir).ok_or_else(|| {
Expand All @@ -25,25 +32,25 @@ pub async fn config_dir() -> Result<PathBuf> {
}

pub fn project_config_dir(project_dir: impl AsRef<Path>) -> PathBuf {
project_dir.as_ref().join(".aqora")
project_dir.as_ref().join(AQORA_DIRNAME)
}

pub fn project_venv_dir(project_dir: impl AsRef<Path>) -> PathBuf {
project_config_dir(project_dir).join("venv")
project_config_dir(project_dir).join(VENV_DIRNAME)
}

pub fn project_data_dir(project_dir: impl AsRef<Path>, kind: impl ToString) -> PathBuf {
project_config_dir(project_dir)
.join("data")
.join(DATA_DIRNAME)
.join(kind.to_string())
}

pub fn pyproject_path(project_dir: impl AsRef<Path>) -> PathBuf {
project_dir.as_ref().join("pyproject.toml")
project_dir.as_ref().join(PYPROJECT_FILENAME)
}

pub fn project_use_case_toml_path(project_dir: impl AsRef<Path>) -> PathBuf {
project_data_dir(project_dir, "use_case.toml")
project_data_dir(project_dir, USE_CASE_FILENAME)
}

pub async fn read_pyproject(project_dir: impl AsRef<Path>) -> Result<PyProject> {
Expand All @@ -68,15 +75,47 @@ pub async fn read_pyproject(project_dir: impl AsRef<Path>) -> Result<PyProject>
})
}

#[derive(Debug, Error)]
enum SymlinkError {
#[error("Failed to create symlink from {0} to {1}: {2}")]
CreateSymlink(PathBuf, PathBuf, std::io::Error),
#[error("{0} directory already exists. Symlink to {1} could not be created.")]
VenvDirExists(PathBuf, PathBuf),
}

fn create_venv_symlink(project_dir: impl AsRef<Path>) -> Result<(), SymlinkError> {
let symlink_dir = project_dir.as_ref().join(VENV_DIRNAME);
let venv_dir = [AQORA_DIRNAME, VENV_DIRNAME].iter().collect::<PathBuf>();

if symlink_dir.exists() {
if symlink_dir.read_link().ok().as_ref() != Some(&venv_dir) {
return Err(SymlinkError::VenvDirExists(symlink_dir, venv_dir));
}
return Ok(());
}

#[cfg(unix)]
use std::os::unix::fs::symlink;
#[cfg(windows)]
use std::os::windows::fs::symlink_dir as symlink;

symlink(&venv_dir, &symlink_dir)
.map_err(|err| SymlinkError::CreateSymlink(symlink_dir, venv_dir, err))
}

pub async fn init_venv(project_dir: impl AsRef<Path>) -> Result<PyEnv> {
let venv_dir = project_venv_dir(&project_dir);
PyEnv::init(&venv_dir).await.map_err(|e| {
let env = PyEnv::init(&venv_dir).await.map_err(|e| {
error::user(
&format!("Failed to setup virtualenv: {}", e),
&format!(
"Please make sure you have permissions to write to {}",
venv_dir.display()
),
)
})
})?;
if let Err(err) = create_venv_symlink(&project_dir) {
eprintln!("WARN: {err}");
}
Ok(env)
}

0 comments on commit 5c4574e

Please sign in to comment.