use anyhow::Result;
use std::{collections::HashMap, fs, path::PathBuf};
use crate::{
config::{load_global_config, load_repo_config},
constants::{APICURIO_CONFIG, APICURIO_LOCK},
dependency::Dependency,
lockfile::{LockFile, LockedDependency},
registry::RegistryClient,
};
use sha2::{Digest, Sha256};
pub async fn run() -> Result<()> {
let repo_cfg = load_repo_config(&PathBuf::from(APICURIO_CONFIG))?;
let global_cfg = load_global_config()?;
let regs = repo_cfg.merge_registries(global_cfg)?;
let mut clients = HashMap::new();
for r in ®s {
clients.insert(r.name.clone(), RegistryClient::new(r)?);
}
let mut locked: Vec<LockedDependency> = Vec::new();
for dep_cfg in &repo_cfg.dependencies {
let dep = Dependency::from_config(dep_cfg)?;
let client = &clients[&dep.registry];
let versions = client
.list_versions(&dep.group_id, &dep.artifact_id)
.await?;
let selected = versions
.iter()
.filter(|v| dep.req.matches(v))
.max()
.ok_or_else(|| anyhow::anyhow!("no matching version for {}", dep.name))?;
let data = client
.download(&dep.group_id, &dep.artifact_id, selected)
.await?;
let file_path = PathBuf::from(&dep.output_path);
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent)?;
}
fs::write(&file_path, &data)?;
let sha = {
let mut h = Sha256::new();
h.update(&data);
hex::encode(h.finalize())
};
locked.push(LockedDependency {
name: dep.name.clone(),
registry: dep.registry.clone(),
resolved_version: selected.to_string(),
download_url: client.get_download_url(&dep.group_id, &dep.artifact_id, selected),
sha256: sha,
output_path: dep.output_path.clone(),
group_id: dep.group_id.clone(),
artifact_id: dep.artifact_id.clone(),
version_spec: dep_cfg.version.clone(),
});
}
let lock_path = PathBuf::from(APICURIO_LOCK);
let config_path = PathBuf::from(APICURIO_CONFIG);
let config_content = std::fs::read_to_string(&config_path)?;
let config_hash = LockFile::compute_config_hash(&config_content, &repo_cfg.dependencies);
let config_modified = LockFile::get_config_modification_time(&config_path).ok();
let lf = LockFile::with_config_modified(locked, config_hash, config_modified);
lf.save(&lock_path)?;
println!("✅ update complete");
Ok(())
}