use anyhow::{anyhow, Context, Result};
use crate::{
archive::download,
config::Config,
http::HttpClient,
remote::{index, release::Release},
tempdir::TempDir,
};
pub fn download_source(
client: &HttpClient,
config: &Config,
release: &Release,
version: &crate::version::GoVersion,
) -> Result<std::path::PathBuf> {
let src_file = release.source_file().ok_or_else(|| {
anyhow!(
"No source tarball found for {}. \
Source tarballs are only available for stable releases.",
version.tag()
)
})?;
let src_archive = config.tmp_dir().join(&src_file.filename);
println!(
"{} Downloading {}...",
"->".cyan(),
src_file.filename.bold()
);
download::fetch(client, &index::download_url(&src_file.filename), &src_archive)
.with_context(|| format!("Failed to download source tarball {}", src_file.filename))?;
if !src_file.sha256.is_empty() {
println!("{} Verifying checksum...", "->".cyan());
download::verify_sha256(&src_archive, &src_file.sha256)
.context("Source tarball checksum mismatch")?;
}
Ok(src_archive)
}
pub fn extract_source(
archive_path: &std::path::Path,
config: &Config,
version_tag: &str,
) -> Result<std::path::PathBuf> {
let staging_dir = TempDir::new_in(config.tmp_dir(), format!("src-{}", version_tag))?;
crate::archive::extract::unpack(archive_path, staging_dir.path())
.context("Failed to extract source tarball")?;
let _ = std::fs::remove_file(archive_path);
let source_root = staging_dir.path().join("go");
if !source_root.exists() {
anyhow::bail!(
"Unexpected archive layout: expected 'go/' inside {}",
staging_dir.path().display()
);
}
staging_dir.keep();
Ok(source_root)
}