#![allow(dead_code)]
use std::path::Path;
use indicatif::{ProgressBar, ProgressStyle};
use crate::error::CliError;
use crate::github::GithubClient;
use crate::tarball;
pub fn download_and_extract(
client: &GithubClient,
org: &str,
repo: &str,
tag: &str,
target: &Path,
expected_top_level: &str,
) -> Result<(), CliError> {
let (content_length, body_reader) = client.release_asset_body(org, repo, tag)?;
let bar = ProgressBar::new(content_length);
bar.set_style(
ProgressStyle::default_bar()
.template("{msg} [{bar:30.cyan/dim}] {bytes}/{total_bytes} ({eta})")
.unwrap()
.progress_chars("█▓░"),
);
bar.set_message(format!("Downloading {org}/{repo} {tag}"));
let wrapped = bar.wrap_read(body_reader);
tarball::extract_safe(wrapped, target)?;
bar.finish_with_message("downloaded");
let expected_dir = target.join(expected_top_level);
if !expected_dir.is_dir() {
return Err(CliError::TarballLayoutMismatch {
expected: expected_top_level.to_string(),
found: list_top_level_entries(target),
});
}
Ok(())
}
fn list_top_level_entries(dir: &Path) -> Vec<String> {
std::fs::read_dir(dir)
.ok()
.map(|entries| {
entries
.filter_map(|e| e.ok())
.map(|e| e.file_name().to_string_lossy().into_owned())
.collect()
})
.unwrap_or_default()
}