git-internal 0.8.4

High-performance Rust library for Git internal objects, Pack files, and AI-assisted development objects (Intent, Plan, Task, Run, Evidence, Decision) with delta compression, streaming I/O, and smart protocol support.
Documentation
//! Test helper: download pack files from remote on demand and cache them for the test run.

use std::{
    collections::HashMap,
    io::Read,
    path::{Path, PathBuf},
    sync::{
        LazyLock, Mutex,
        atomic::{AtomicUsize, Ordering},
    },
};

const BASE_URL: &str = "https://download.libra.tools/libra/development/pack";

/// Directory for caching downloaded pack files during test runs.
fn download_dir() -> PathBuf {
    let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/packs");
    std::fs::create_dir_all(&dir).expect("create download dir");
    dir
}

/// Per-file reference counts so the file is only deleted when the last guard drops.
static REF_COUNTS: LazyLock<Mutex<HashMap<PathBuf, &'static AtomicUsize>>> =
    LazyLock::new(|| Mutex::new(HashMap::new()));

fn lock_ref_counts() -> std::sync::MutexGuard<'static, HashMap<PathBuf, &'static AtomicUsize>> {
    REF_COUNTS.lock().unwrap_or_else(|e| e.into_inner())
}

fn acquire_ref(path: &Path) -> &'static AtomicUsize {
    let mut map = lock_ref_counts();
    let counter = map
        .entry(path.to_path_buf())
        .or_insert_with(|| Box::leak(Box::new(AtomicUsize::new(0))));
    counter.fetch_add(1, Ordering::Relaxed);
    counter
}

fn release_ref(path: &Path) -> bool {
    let map = lock_ref_counts();
    if let Some(counter) = map.get(path) {
        counter.fetch_sub(1, Ordering::Relaxed) == 1
    } else {
        true
    }
}

/// A mutex to serialize downloads and avoid races.
static DOWNLOAD_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));

/// Download a pack/idx file if not already present, returning the local path.
fn ensure_downloaded_locked(filename: &str) -> PathBuf {
    let path = download_dir().join(filename);
    if path.exists() {
        return path;
    }
    let url = format!("{BASE_URL}/{filename}");
    tracing::info!("Downloading test pack file: {url}");
    let mut response = ureq::get(&url)
        .call()
        .unwrap_or_else(|e| panic!("failed to download {url}: {e}"));
    let mut bytes = Vec::new();
    response
        .body_mut()
        .as_reader()
        .read_to_end(&mut bytes)
        .unwrap_or_else(|e| panic!("failed to read response body for {url}: {e}"));
    std::fs::write(&path, &bytes)
        .unwrap_or_else(|e| panic!("failed to write {}: {e}", path.display()));
    tracing::info!("Downloaded {} ({} bytes)", filename, bytes.len());
    path
}

/// Guard that keeps the downloaded file referenced by active tests.
pub struct PackFileGuard {
    path: PathBuf,
}

impl Drop for PackFileGuard {
    fn drop(&mut self) {
        let _ = release_ref(&self.path);
    }
}

/// Download a pack file (and its companion .idx if the file is a .pack),
/// returning `(path, guard)`. Files are cached for the rest of the test run.
pub fn download_pack_file(filename: &str) -> (PathBuf, PackFileGuard) {
    let _lock = DOWNLOAD_LOCK.lock().unwrap_or_else(|e| e.into_inner());
    let path = ensure_downloaded_locked(filename);
    // Also download the companion file (.pack ↔ .idx).
    if filename.ends_with(".pack") {
        let idx = filename.replace(".pack", ".idx");
        let _ = ensure_downloaded_locked(&idx);
    } else if filename.ends_with(".idx") {
        let pack = filename.replace(".idx", ".pack");
        let _ = ensure_downloaded_locked(&pack);
    }
    acquire_ref(&path);
    let guard = PackFileGuard { path: path.clone() };
    (path, guard)
}