Skip to content
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
6 changes: 3 additions & 3 deletions .github/workflows/hyperfine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ on:
branches: ["main"]
pull_request:
branches: ["main"]
paths:
- ".github/workflows/hyperfine.yml"
- "Cargo.toml"
# paths:
# - ".github/workflows/hyperfine.yml"
# - "Cargo.toml"
workflow_dispatch:

concurrency:
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ comfy-table = "7.1.3"
confique = { version = "0.3", default-features = false }
console = "0.15"
contracts = "0.6"
dashmap = "6"
demand = "1"
digest = "0.10.7"
dotenvy = "0.15"
Expand Down Expand Up @@ -96,7 +97,7 @@ number_prefix = "0.4"
once_cell = "1"
openssl = { version = "0.10", optional = true }
os-release = "0.1"
path-absolutize = "3"
path-absolutize = { version = "3", features = ["unsafe_cache"] }
petgraph = "0.8"
rand = "0.9"
regex = "1"
Expand Down
1 change: 1 addition & 0 deletions e2e/run_test
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ within_isolated_env() {
MISE_DATA_DIR="$MISE_DATA_DIR" \
MISE_DEBUG="${MISE_DEBUG:-0}" \
MISE_EXPERIMENTAL=1 \
MISE_GPG_VERIFY="${MISE_GPG_VERIFY:-}" \
MISE_LOG_LEVEL="${MISE_LOG_LEVEL:-}" \
MISE_STATE_DIR="$MISE_STATE_DIR" \
MISE_SYSTEM_DIR="$MISE_SYSTEM_DIR" \
Expand Down
8 changes: 5 additions & 3 deletions hk.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ local bash_glob = List("*.sh", "xtasks/**", "scripts/**", "e2e/**")
local bash_exclude = List("*.ps1", "*.fish", "*.ts", "*.js", "*.json", "*.bat", "**/.*", "src/assets/bash_zsh_support/**")
local linters = new Mapping<String, Step> {
// uses builtin prettier linter config
["prettier"] = Builtins.prettier
["prettier"] = (Builtins.prettier) {
batch = false
}
["clippy"] = (Builtins.cargo_clippy) {
check = "cargo clippy --manifest-path {{workspace_indicator}} --all-features"
fix = "cargo clippy --manifest-path {{workspace_indicator}} --all-features --fix --allow-dirty --allow-staged"
check = "cargo clippy --manifest-path {{workspace_indicator}} --all-features -- -Dwarnings"
fix = "cargo clippy --manifest-path {{workspace_indicator}} --all-features --fix --allow-dirty --allow-staged -- -Dwarnings"
}
["shellcheck"] = (Builtins.shellcheck) {
glob = bash_glob
Expand Down
5 changes: 5 additions & 0 deletions mise.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@
"path": ".",
},
],
"settings": {
"shellcheck.ignorePatterns": {
"completions/mise.bash": true,
},
},
}
9 changes: 9 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@
"aqua": {
"additionalProperties": false,
"properties": {
"baked_registry": {
"default": true,
"description": "Use baked-in aqua registry (if compiled in).",
"type": "boolean"
},
"cosign": {
"default": true,
"description": "Use cosign to verify aqua tool signatures.",
Expand Down Expand Up @@ -494,6 +499,10 @@
"description": "Set to true to skip checksum verification when downloading go sdk tarballs.",
"type": "boolean"
},
"gpg_verify": {
"description": "Use gpg to verify all tool signatures.",
"type": "boolean"
},
"http_timeout": {
"default": "30s",
"description": "Timeout in seconds for all HTTP requests in mise.",
Expand Down
12 changes: 12 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ env = "MISE_ALWAYS_KEEP_INSTALL"
type = "Bool"
description = "should mise keep install files after installation even if the installation fails"

[aqua.baked_registry]
env = "MISE_AQUA_BAKED_REGISTRY"
type = "Bool"
default = true
description = "Use baked-in aqua registry (if compiled in)."

[aqua.cosign]
env = "MISE_AQUA_COSIGN"
type = "Bool"
Expand Down Expand Up @@ -457,6 +463,12 @@ env = "MISE_GO_SKIP_CHECKSUM"
type = "Bool"
description = "Set to true to skip checksum verification when downloading go sdk tarballs."

[gpg_verify]
env = "MISE_GPG_VERIFY"
type = "Bool"
optional = true
description = "Use gpg to verify all tool signatures."

[http_timeout]
env = "MISE_HTTP_TIMEOUT"
type = "Duration"
Expand Down
75 changes: 42 additions & 33 deletions src/aqua/aqua_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,44 +204,14 @@ impl AquaRegistry {
pub async fn package(&self, id: &str) -> Result<AquaPackage> {
static CACHE: LazyLock<Mutex<HashMap<String, AquaPackage>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
static RATE_LIMITED: AtomicBool = AtomicBool::new(false);
if let Some(pkg) = CACHE.lock().await.get(id) {
return Ok(pkg.clone());
}
let path_id = id.split('/').join(std::path::MAIN_SEPARATOR_STR);
let path = self.path.join("pkgs").join(&path_id).join("registry.yaml");
let registry: RegistryYaml = if !self.repo_exists {
if let Some(registry) = AQUA_STANDARD_REGISTRY_FILES.get(id) {
trace!("reading baked-in aqua-registry for {id}");
serde_yaml::from_str(registry)?
} else if !path.exists() || file::modified_duration(&path)? > DAILY {
if RATE_LIMITED.load(Ordering::Relaxed) {
warn!("aqua-registry rate limited, skipping {id}");
return Err(eyre!("aqua-registry rate limited"));
}
trace!("downloading aqua-registry for {id} to {path:?}");
let url: Url =
format!("https://mise-versions.jdx.dev/aqua-registry/{path_id}/registry.yaml")
.parse()?;
match http::HTTP_FETCH.download_file(url, &path, None).await {
Ok(_) => {}
Err(e) if http::error_code(&e) == Some(429) => {
warn!("aqua-registry rate limited, skipping {id}");
RATE_LIMITED.store(true, Ordering::Relaxed);
return Err(e);
}
Err(e) => return Err(e),
}
serde_yaml::from_reader(file::open(&path)?)?
} else {
trace!("reading cached aqua-registry for {id} from {path:?}");
serde_yaml::from_reader(file::open(&path)?)?
}
} else {
trace!("reading aqua-registry for {id} from repo at {path:?}");
serde_yaml::from_reader(file::open(&path)?)?
};
let mut pkg = registry
let mut pkg = self
.fetch_package_yaml(id, &path, &path_id)
.await?
.packages
.into_iter()
.next()
Expand All @@ -256,6 +226,45 @@ impl AquaRegistry {
pub async fn package_with_version(&self, id: &str, v: &str) -> Result<AquaPackage> {
Ok(self.package(id).await?.with_version(v))
}

async fn fetch_package_yaml(
&self,
id: &str,
path: &PathBuf,
path_id: &str,
) -> Result<RegistryYaml> {
let registry = if self.repo_exists {
trace!("reading aqua-registry for {id} from repo at {path:?}");
serde_yaml::from_reader(file::open(path)?)?
} else if SETTINGS.aqua.baked_registry && AQUA_STANDARD_REGISTRY_FILES.contains_key(id) {
trace!("reading baked-in aqua-registry for {id}");
serde_yaml::from_str(AQUA_STANDARD_REGISTRY_FILES.get(id).unwrap())?
} else if !path.exists() || file::modified_duration(path)? > DAILY {
static RATE_LIMITED: AtomicBool = AtomicBool::new(false);
if RATE_LIMITED.load(Ordering::Relaxed) {
warn!("aqua-registry rate limited, skipping {id}");
return Err(eyre!("aqua-registry rate limited"));
}
trace!("downloading aqua-registry for {id} to {path:?}");
let url =
format!("https://mise-versions.jdx.dev/aqua-registry/{path_id}/registry.yaml");
let url: Url = url.parse()?;
match http::HTTP_FETCH.download_file(url, path, None).await {
Ok(_) => {}
Err(e) if http::error_code(&e) == Some(429) => {
warn!("aqua-registry rate limited, skipping {id}");
RATE_LIMITED.store(true, Ordering::Relaxed);
return Err(e);
}
Err(e) => return Err(e),
}
serde_yaml::from_reader(file::open(path)?)?
} else {
trace!("reading cached aqua-registry for {id} from {path:?}");
serde_yaml::from_reader(file::open(path)?)?
};
Ok(registry)
}
}

fn fetch_latest_repo(repo: &Git) -> Result<()> {
Expand Down
61 changes: 44 additions & 17 deletions src/backend/aqua.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
use crate::aqua::aqua_registry::{
AQUA_REGISTRY, AquaChecksumType, AquaMinisignType, AquaPackage, AquaPackageType,
};
use crate::backend::Backend;
use crate::backend::backend_type::BackendType;
use crate::cli::args::BackendArg;
Expand All @@ -10,23 +7,31 @@ use crate::config::SETTINGS;
use crate::file::TarOptions;
use crate::http::HTTP;
use crate::install_context::InstallContext;
use crate::path::{Path, PathBuf, PathExt};
use crate::plugins::VERSION_REGEX;
use crate::registry::REGISTRY;
use crate::toolset::ToolVersion;
use crate::{
aqua::aqua_registry::{
AQUA_REGISTRY, AquaChecksumType, AquaMinisignType, AquaPackage, AquaPackageType,
},
cache::{CacheManager, CacheManagerBuilder},
};
use crate::{file, github, minisign};
use async_trait::async_trait;
use dashmap::DashMap;
use eyre::{ContextCompat, Result, bail};
use indexmap::IndexSet;
use itertools::Itertools;
use regex::Regex;
use std::fmt::Debug;
use std::path::{Path, PathBuf};
use std::{collections::HashSet, sync::Arc};

#[derive(Debug)]
pub struct AquaBackend {
ba: Arc<BackendArg>,
id: String,
bin_path_caches: DashMap<String, CacheManager<Vec<PathBuf>>>,
}

#[async_trait]
Expand Down Expand Up @@ -118,21 +123,42 @@ impl Backend for AquaBackend {
}

async fn list_bin_paths(&self, tv: &ToolVersion) -> Result<Vec<PathBuf>> {
let pkg = AQUA_REGISTRY
.package_with_version(&self.id, &tv.version)
.await?;

let srcs = self.srcs(&pkg, tv)?;
if srcs.is_empty() {
return Ok(vec![tv.install_path()]);
}
// TODO: instead of caching it would probably be better to create this as part of installation
let cache = self
.bin_path_caches
.entry(tv.version.clone())
.or_insert_with(|| {
CacheManagerBuilder::new(tv.cache_path().join("bin_paths.msgpack.z"))
.with_fresh_duration(SETTINGS.fetch_remote_versions_cache())
.build()
});
let install_path = tv.install_path();
let paths = cache
.get_or_try_init_async(async || {
let pkg = AQUA_REGISTRY
.package_with_version(&self.id, &tv.version)
.await?;

Ok(srcs
let srcs = self.srcs(&pkg, tv)?;
let paths = if srcs.is_empty() {
vec![install_path.clone()]
} else {
srcs.iter()
.map(|(_, dst)| dst.parent().unwrap().to_path_buf())
.collect()
};
Ok(paths
.into_iter()
.unique()
.filter(|p| p.exists())
.map(|p| p.strip_prefix(&install_path).unwrap().to_path_buf())
.collect())
})
.await?
.iter()
.map(|(_, dst)| dst.parent().unwrap().to_path_buf())
.filter(|p| p.exists())
.unique()
.collect())
.map(|p| p.mount(&install_path))
.collect();
Ok(paths)
}

fn fuzzy_match_filter(&self, versions: Vec<String>, query: &str) -> eyre::Result<Vec<String>> {
Expand Down Expand Up @@ -175,6 +201,7 @@ impl AquaBackend {
Self {
id: id.to_string(),
ba: Arc::new(ba),
bin_path_caches: Default::default(),
}
}

Expand Down
11 changes: 4 additions & 7 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::{BTreeMap, HashMap, HashSet};
use dashmap::DashMap;
use std::collections::{BTreeMap, HashSet};
use std::ffi::OsString;
use std::fmt::{Debug, Display, Formatter};
use std::fs::File;
Expand Down Expand Up @@ -659,14 +660,10 @@ pub trait Backend: Debug + Send + Sync {
}

fn get_remote_version_cache(&self) -> Arc<TokioMutex<VersionCacheManager>> {
// use a mutex to prevent deadlocks that occurs due to reentrant cache access
static REMOTE_VERSION_CACHE: Lazy<
Mutex<HashMap<String, Arc<TokioMutex<VersionCacheManager>>>>,
> = Lazy::new(Default::default);
static REMOTE_VERSION_CACHE: Lazy<DashMap<String, Arc<TokioMutex<VersionCacheManager>>>> =
Lazy::new(Default::default);

REMOTE_VERSION_CACHE
.lock()
.unwrap()
.entry(self.ba().full())
.or_insert_with(|| {
let mut cm = CacheManagerBuilder::new(
Expand Down
Loading
Loading