hyper-jump 0.11.0

A generalist all-in-one command-line version manager toolset for a more efficient development workflow.
use tracing::info;

use crate::adapters::archive::LocalArchive;
use crate::adapters::downloader::ReqwestDownloader;
use crate::adapters::fs::TokioFs;
use crate::adapters::github_release::GitHubReleaseProvider;
use crate::app::install;
use crate::app::resolve::resolve_requested_version;
use crate::domain::package::Package;
use crate::domain::package::PackageSpec;
use crate::ports::ProxyInstaller;
use crate::ports::UsedVersionStore;

#[derive(clap::Parser)]
pub struct Args {
    pub package: String,
    pub version: String,
}

pub async fn run(
    args: Args,
    ctx: &crate::Context,
    client: Option<&reqwest::Client>,
) -> miette::Result<()> {
    let spec = ctx.packages.resolve(&args.package).map_err(|e| miette::miette!(e))?;
    let paths = crate::adapters::path::FsPaths::new(ctx.dirs.root_dir.clone());
    let platform = crate::adapters::platform::StdPlatform;
    use_cmd(client, spec, args.version, &paths, &platform)
        .await
        .map_err(|err| miette::miette!(err))?;

    Ok(())
}

pub async fn use_cmd(
    client: Option<&reqwest::Client>,
    spec: std::sync::Arc<PackageSpec>,
    requested_version: String,
    paths: &crate::adapters::path::FsPaths,
    platform: &impl crate::ports::Platform,
) -> anyhow::Result<()> {
    let provider = GitHubReleaseProvider::new(client);
    let downloader = ReqwestDownloader::new(client);
    let archive = LocalArchive;
    let fs = TokioFs;
    let lock = crate::adapters::lock::FileLock::from_paths(paths).await?;
    let proxy = crate::adapters::proxy::ProxyFsCopier::new(
        paths.clone(),
        crate::adapters::env::StdEnv,
        crate::adapters::fs::TokioFs,
        crate::adapters::process::TokioProcess,
    );
    let used_store = crate::adapters::used_store::UsedFileStore::new(paths.clone());

    let parsed_version = resolve_requested_version(&requested_version, &spec, &provider).await?;
    let package = Package::with_parsed(spec.clone(), parsed_version.clone(), platform)?;
    let version = parsed_version;
    let is_version_used = match used_store.current(package.clone()).await? {
        Some(current) => current == version.tag_name,
        None => false,
    };

    proxy.ensure_proxy(&package.alias()).await?;

    if is_version_used {
        info!("{} is already in use.", version.tag_name);
        return Ok(());
    }

    install::install(
        spec,
        version.tag_name.clone(),
        &provider,
        &downloader,
        &archive,
        &fs,
        platform,
        &lock,
        &used_store,
        paths,
        &proxy,
    )
    .await?;

    used_store.set_current(package.clone(), &version.tag_name).await?;

    info!("You can now use {}!", version.tag_name);

    Ok(())
}