Skip to content
Merged
1 change: 1 addition & 0 deletions e2e/backend/test_aqua
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ test aqua:BurntSushi/ripgrep@14.0.0 "rg --version" "ripgrep 14.0.0"
test age@1.2.0 "age --version" "v1.2.0"
test aqua:helm/helm@3.16.3 "helm version" "v3.16.3"
test aqua:crate-ci/typos@1.27.3 "typos --version" "typos-cli 1.27.3"
test aqua:biomejs/biome@2.0.0 "biome --version" "Version: 2.0.0"
2 changes: 1 addition & 1 deletion registry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ benthos.backends = ["aqua:benthosdev/benthos", "asdf:benthosdev/benthos-asdf"]
bfs.backends = ["asdf:mise-plugins/mise-bfs"]
binnacle.backends = ["aqua:Traackr/binnacle", "asdf:Traackr/asdf-binnacle"]
biome.backends = ["aqua:biomejs/biome", "ubi:biomejs/biome"]
# biome.test = ["biome --version", "Version: {{version}}"] # 2.0.0 cannot be installed
biome.test = ["biome --version", "Version: {{version}}"]
bitwarden.backends = ["aqua:bitwarden/clients", "asdf:vixus0/asdf-bitwarden"]
bitwarden.test = [
"bw --version",
Expand Down
108 changes: 69 additions & 39 deletions src/backend/aqua.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ use eyre::{ContextCompat, Result, bail};
use indexmap::IndexSet;
use itertools::Itertools;
use regex::Regex;
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::{collections::HashSet, sync::Arc};

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

Expand All @@ -57,58 +59,46 @@ impl Backend for AquaBackend {
}

async fn _list_remote_versions(&self, _config: &Arc<Config>) -> Result<Vec<String>> {
let pkg = AQUA_REGISTRY.package(&self.id).await?;
if !pkg.repo_owner.is_empty() && !pkg.repo_name.is_empty() {
let versions = get_versions(&pkg).await?;
Ok(versions
.into_iter()
.filter_map(|v| {
let mut v = v.as_str();
match pkg.version_filter_ok(v) {
Ok(true) => {}
Ok(false) => return None,
Err(e) => {
warn!("[{}] aqua version filter error: {e}", self.ba);
}
}
let pkg = pkg.clone().with_version(v);
if pkg.no_asset || pkg.error_message.is_some() {
return None;
}
if let Some(prefix) = &pkg.version_prefix {
if let Some(_v) = v.strip_prefix(prefix) {
v = _v
} else {
return None;
}
}
v = v.strip_prefix('v').unwrap_or(v);
Some(v.to_string())
})
.rev()
.collect())
} else {
warn!("no aqua registry found for {}", self.ba);
Ok(vec![])
let version_tags_map = self.get_version_tags_map().await?;
let mut versions = Vec::new();
for (v, tag) in version_tags_map.iter() {
let pkg = AQUA_REGISTRY
.package_with_version(&self.id, tag)
.await
.unwrap_or_default();
if !pkg.no_asset && pkg.error_message.is_none() {
versions.push(v.clone());
}
}
Ok(versions)
}

async fn install_version_(
&self,
ctx: &InstallContext,
mut tv: ToolVersion,
) -> Result<ToolVersion> {
let mut v = format!("v{}", tv.version);
let pkg = AQUA_REGISTRY.package_with_version(&self.id, &v).await?;
let mut v;
let pkg;
match self.get_version_tags_map().await?.get(&tv.version).cloned() {
Some(tag) => {
v = tag;
pkg = AQUA_REGISTRY.package_with_version(&self.id, &v).await?;
}
None => {
v = format!("v{}", tv.version);
pkg = AQUA_REGISTRY.package_with_version(&self.id, &v).await?;
if let Some(prefix) = &pkg.version_prefix {
v = format!("{prefix}{v}");
}
}
}
if pkg.no_asset {
bail!("no asset released");
}
if pkg.error_message.is_some() {
bail!(pkg.error_message.unwrap());
}
if let Some(prefix) = &pkg.version_prefix {
v = format!("{prefix}{v}");
}
validate(&pkg)?;
let url = match self.fetch_url(&pkg, &v).await {
Ok(url) => url,
Expand Down Expand Up @@ -210,13 +200,53 @@ impl AquaBackend {
id
});
}
let cache_path = ba.cache_path.clone();
Self {
id: id.to_string(),
ba: Arc::new(ba),
version_tags_cache: CacheManagerBuilder::new(cache_path.join("version_tags.msgpack.z"))
.with_fresh_duration(Settings::get().fetch_remote_versions_cache())
.build(),
bin_path_caches: Default::default(),
}
}

async fn get_version_tags_map(&self) -> Result<&BTreeMap<String, String>> {
self.version_tags_cache
.get_or_try_init_async(|| async {
let pkg = AQUA_REGISTRY.package(&self.id).await?;
let mut map = BTreeMap::new();
if !pkg.repo_owner.is_empty() && !pkg.repo_name.is_empty() {
let tags = get_tags(&pkg).await?;
for tag in tags.into_iter().rev() {
let mut version = tag.as_str();
match pkg.version_filter_ok(version) {
Ok(true) => {}
Ok(false) => continue,
Err(e) => {
warn!("[{}] aqua version filter error: {e}", self.ba());
continue;
}
}
let pkg = pkg.clone().with_version(version);
if let Some(prefix) = &pkg.version_prefix {
if let Some(_v) = version.strip_prefix(prefix) {
version = _v;
} else {
continue;
}
}
version = version.strip_prefix('v').unwrap_or(version);
map.insert(version.to_string(), tag);
}
} else {
warn!("no aqua registry found for {}", self.ba());
}
Ok(map)
})
.await
}

async fn fetch_url(&self, pkg: &AquaPackage, v: &str) -> Result<String> {
match pkg.r#type {
AquaPackageType::GithubRelease => self.github_release_url(pkg, v).await,
Expand Down Expand Up @@ -691,7 +721,7 @@ impl AquaBackend {
}
}

async fn get_versions(pkg: &AquaPackage) -> Result<Vec<String>> {
async fn get_tags(pkg: &AquaPackage) -> Result<Vec<String>> {
if let Some("github_tag") = pkg.version_source.as_deref() {
let versions = github::list_tags(&format!("{}/{}", pkg.repo_owner, pkg.repo_name)).await?;
return Ok(versions);
Expand Down
Loading