Skip to content

Commit

Permalink
feat(up golang): ✨ Add GOPATH isolation for gcalls to go install (#283)
Browse files Browse the repository at this point in the history
This follows #277 by making it so the
golang up operation also gets an updated GOPATH for calls to `go
install`.
  • Loading branch information
xaf authored Dec 14, 2023
1 parent 8283422 commit a3bca18
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 31 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ lazy_static = "1.4.0"
libz-sys = { version = "1.1.12", features = ["static"] }
machine-uid = "0.5.1"
node-semver = "2.1.0"
normalize-path = "0.2.1"
once_cell = "1.19.0"
openssl = { version = "0.10", features = ["vendored"] }
package-json = "0.4.0"
Expand Down
6 changes: 3 additions & 3 deletions src/internal/commands/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::io;
use std::io::Write;
use std::path::{Path, PathBuf};

use normalize_path::NormalizePath;
use path_clean::PathClean;

use requestty::question::{completions, Completions};

use crate::internal::env::omni_cmd_file;
Expand All @@ -16,7 +16,7 @@ pub fn split_name(string: &str, split_on: &str) -> Vec<String> {

pub fn abs_or_rel_path(path: &str) -> String {
let current_dir = std::env::current_dir().unwrap();
let path = std::path::PathBuf::from(&path);
let path = std::path::PathBuf::from(&path).normalize();
let path = if path.is_absolute() {
path
} else {
Expand Down Expand Up @@ -44,7 +44,7 @@ pub fn abs_or_rel_path(path: &str) -> String {
}

pub fn abs_path(path: impl AsRef<Path>) -> PathBuf {
let path = path.as_ref();
let path = path.as_ref().normalize();

let absolute_path = if path.is_absolute() {
path.to_path_buf()
Expand Down
38 changes: 26 additions & 12 deletions src/internal/config/up/asdf_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use itertools::any;
use lazy_static::lazy_static;
use node_semver::Range as semverRange;
use node_semver::Version as semverVersion;
use normalize_path::NormalizePath;
use once_cell::sync::OnceCell;
use serde::Deserialize;
use serde::Serialize;
Expand All @@ -18,6 +19,7 @@ use walkdir::WalkDir;
use crate::internal::cache::AsdfOperationCache;
use crate::internal::cache::CacheObject;
use crate::internal::cache::UpEnvironmentsCache;
use crate::internal::config::up::utils::force_remove_dir_all;
use crate::internal::config::up::utils::run_progress;
use crate::internal::config::up::utils::PrintProgressHandler;
use crate::internal::config::up::utils::ProgressHandler;
Expand Down Expand Up @@ -192,12 +194,12 @@ pub struct UpConfigAsdfBase {
}

impl UpConfigAsdfBase {
pub fn new(tool: &str, version: &str) -> Self {
pub fn new(tool: &str, version: &str, dirs: BTreeSet<String>) -> Self {
UpConfigAsdfBase {
tool: tool.to_string(),
tool_url: None,
version: version.to_string(),
dirs: BTreeSet::new(),
dirs: dirs.clone(),
detect_version_funcs: vec![],
post_install_funcs: vec![],
actual_version: OnceCell::new(),
Expand Down Expand Up @@ -259,15 +261,27 @@ impl UpConfigAsdfBase {
} else if let Some(value) = config_value.as_integer() {
version = value.to_string();
} else {
if let Some(value) = config_value.get("version") {
version = value.as_str().unwrap().to_string();
if let Some(value) = config_value.get_as_str_forced("version") {
version = value.to_string();
}

if let Some(value) = config_value.get_as_str("dir") {
dirs.insert(value.to_string());
dirs.insert(
PathBuf::from(value)
.normalize()
.to_string_lossy()
.to_string(),
);
} else if let Some(array) = config_value.get_as_array("dir") {
for value in array {
dirs.insert(value.as_str().unwrap().to_string());
if let Some(value) = value.as_str_forced() {
dirs.insert(
PathBuf::from(value)
.normalize()
.to_string_lossy()
.to_string(),
);
}
}
}
}
Expand Down Expand Up @@ -780,7 +794,7 @@ impl UpConfigAsdfBase {

// If any data path in the versions
if !any(&env_tools, |tool| tool.data_path.is_some()) {
std::fs::remove_dir_all(wd_data_path).map_err(|err| {
force_remove_dir_all(wd_data_path).map_err(|err| {
UpError::Exec(format!(
"failed to remove workdir data path {}: {}",
wd_data_path.display(),
Expand Down Expand Up @@ -811,10 +825,10 @@ impl UpConfigAsdfBase {

// Remove the tool directory if the tool is not expected
if !expected_tools.contains(&tool_dir_name) {
std::fs::remove_dir_all(tool_dir.path()).map_err(|err| {
force_remove_dir_all(tool_dir.path()).map_err(|err| {
UpError::Exec(format!(
"failed to remove workdir data path for workdir {}: {}",
workdir_id, err
"failed to remove workdir data path for tool {}: {}",
tool_dir_name, err
))
})?;
continue;
Expand Down Expand Up @@ -847,7 +861,7 @@ impl UpConfigAsdfBase {

// Remove the version directory if the version is not expected
if !expected_versions.contains(&version_dir_name) {
std::fs::remove_dir_all(version_dir.path()).map_err(|err| {
force_remove_dir_all(version_dir.path()).map_err(|err| {
UpError::Exec(format!(
"failed to remove workdir data path for workdir {}, tool {} and version {}: {}",
workdir_id, tool_dir_name, version_dir_name, err
Expand Down Expand Up @@ -890,7 +904,7 @@ impl UpConfigAsdfBase {

// Remove the path directory if the path is not expected
if !expected_paths.contains(&path_dir_name) {
std::fs::remove_dir_all(path_dir.path()).map_err(|err| {
force_remove_dir_all(path_dir.path()).map_err(|err| {
UpError::Exec(format!(
"failed to remove workdir data path for workdir {}, tool {}, version {} and path {}: {}",
workdir_id, tool_dir_name, version_dir_name, path_dir_name, err
Expand Down
109 changes: 103 additions & 6 deletions src/internal/config/up/golang.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
use std::collections::BTreeSet;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::path::Path;
use std::path::PathBuf;

use normalize_path::NormalizePath;
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};

use crate::internal::cache::utils::CacheObject;
use crate::internal::cache::UpEnvironmentsCache;
use crate::internal::commands::utils::abs_path;
use crate::internal::config::up::utils::data_path_dir_hash;
use crate::internal::config::up::AsdfToolUpVersion;
use crate::internal::config::up::ProgressHandler;
use crate::internal::config::up::UpConfigAsdfBase;
use crate::internal::config::up::UpError;
use crate::internal::config::up::UpOptions;
use crate::internal::env::current_dir;
use crate::internal::workdir;
use crate::internal::ConfigValue;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UpConfigGolang {
pub version: Option<String>,
pub version_file: Option<String>,
pub dirs: BTreeSet<String>,
#[serde(skip)]
pub asdf_base: OnceCell<UpConfigAsdfBase>,
}
Expand All @@ -25,6 +35,7 @@ impl UpConfigGolang {
pub fn from_config_value(config_value: Option<&ConfigValue>) -> Self {
let mut version = None;
let mut version_file = None;
let mut dirs = BTreeSet::new();

if let Some(config_value) = config_value {
if let Some(value) = config_value.as_str() {
Expand All @@ -33,11 +44,31 @@ impl UpConfigGolang {
version = Some(value.to_string());
} else if let Some(value) = config_value.as_integer() {
version = Some(value.to_string());
} else if let Some(value) = config_value.as_table() {
if let Some(value) = value.get("version") {
version = Some(value.as_str().unwrap().to_string());
} else if let Some(value) = value.get("version_file") {
version_file = Some(value.as_str().unwrap().to_string());
} else {
if let Some(value) = config_value.get_as_str_forced("version") {
version = Some(value.to_string());
} else if let Some(value) = config_value.get_as_str_forced("version_file") {
version_file = Some(value.to_string());
}

if let Some(value) = config_value.get_as_str("dir") {
dirs.insert(
PathBuf::from(value)
.normalize()
.to_string_lossy()
.to_string(),
);
} else if let Some(array) = config_value.get_as_array("dir") {
for value in array {
if let Some(value) = value.as_str_forced() {
dirs.insert(
PathBuf::from(value)
.normalize()
.to_string_lossy()
.to_string(),
);
}
}
}
}
}
Expand All @@ -46,6 +77,7 @@ impl UpConfigGolang {
asdf_base: OnceCell::new(),
version,
version_file,
dirs,
}
}

Expand All @@ -67,8 +99,10 @@ impl UpConfigGolang {
"latest".to_string()
};

let mut asdf_base = UpConfigAsdfBase::new("golang", version.as_ref());
let mut asdf_base =
UpConfigAsdfBase::new("golang", version.as_ref(), self.dirs.clone());
asdf_base.add_detect_version_func(detect_version_from_gomod);
asdf_base.add_post_install_func(setup_individual_gopath);

Ok(asdf_base)
})
Expand Down Expand Up @@ -140,3 +174,66 @@ fn extract_version_from_gomod_file(
version_file.display(),
)))
}

fn setup_individual_gopath(
progress_handler: &dyn ProgressHandler,
tool: String,
versions: Vec<AsdfToolUpVersion>,
) -> Result<(), UpError> {
if tool != "golang" {
panic!("setup_individual_gopath called with wrong tool: {}", tool);
}

// Get the data path for the work directory
let workdir = workdir(".");

let workdir_id = if let Some(workdir_id) = workdir.id() {
workdir_id
} else {
return Err(UpError::Exec(format!(
"failed to get workdir id for {}",
current_dir().display()
)));
};

let data_path = if let Some(data_path) = workdir.data_path() {
data_path
} else {
return Err(UpError::Exec(format!(
"failed to get data path for {}",
current_dir().display()
)));
};

// Handle each version individually
for version in &versions {
if let Err(err) = UpEnvironmentsCache::exclusive(|up_env| {
let mut any_changed = false;
for dir in &version.dirs {
let gopath_dir = data_path_dir_hash(dir);

let gopath = data_path
.join(&tool)
.join(&version.version)
.join(&gopath_dir);

any_changed = up_env.add_version_data_path(
&workdir_id,
&tool,
&version.version,
dir,
&gopath.to_string_lossy(),
) || any_changed;
}
any_changed
}) {
progress_handler.progress(format!("failed to update tool cache: {}", err));
return Err(UpError::Cache(format!(
"failed to update tool cache: {}",
err
)));
}
}

Ok(())
}
12 changes: 2 additions & 10 deletions src/internal/config/up/python.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::path::PathBuf;

use blake3::Hasher;
use semver::Version;
use serde::{Deserialize, Serialize};
use tokio::process::Command as TokioCommand;
Expand All @@ -9,6 +8,7 @@ use crate::internal::cache::utils::CacheObject;
use crate::internal::cache::UpEnvironmentsCache;
use crate::internal::config::up::asdf_tool_path;
use crate::internal::config::up::run_progress;
use crate::internal::config::up::utils::data_path_dir_hash;
use crate::internal::config::up::utils::RunConfig;
use crate::internal::config::up::AsdfToolUpVersion;
use crate::internal::config::up::ProgressHandler;
Expand Down Expand Up @@ -120,15 +120,7 @@ fn setup_python_venv_per_dir(
};

// Get the hash of the relative path
let venv_dir = if dir.is_empty() {
"root".to_string()
} else {
let mut hasher = Hasher::new();
hasher.update(dir.as_bytes());
let hash_bytes = hasher.finalize();
let hash_b62 = base_62::encode(hash_bytes.as_bytes())[..20].to_string();
hash_b62
};
let venv_dir = data_path_dir_hash(&dir);

let venv_path = data_path
.join("python")
Expand Down
Loading

0 comments on commit a3bca18

Please sign in to comment.