From e2d609961abc5e309da4f40b1ae57de6616bd0e3 Mon Sep 17 00:00:00 2001 From: ion098 <146852218+ion098@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:29:44 +0000 Subject: [PATCH 1/9] feat: :sparkles: Use cached template if it is up-to-date --- Cargo.toml | 2 +- src/commands/new.rs | 115 ++++++++++++++++++++-------- src/commands/vexide-template.tar.gz | Bin 8693 -> 8933 bytes src/errors.rs | 5 ++ src/main.rs | 20 +++-- 5 files changed, 104 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9809e41..6555681 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ chrono = "0.4.38" directories = "5.0.1" [features] -default = ["clap", "fetch-template"] +default = ["clap"] clap = ["dep:clap"] field-control = ["dep:ratatui", "dep:crossterm", "dep:tui-term"] diff --git a/src/commands/new.rs b/src/commands/new.rs index a668842..3aefe90 100644 --- a/src/commands/new.rs +++ b/src/commands/new.rs @@ -1,6 +1,7 @@ use cargo_metadata::camino::Utf8PathBuf; use directories::ProjectDirs; -use log::info; +use log::{debug, info, warn}; +use serde_json::Value; use crate::errors::CliError; use std::{ @@ -8,29 +9,69 @@ use std::{ path::{Path, PathBuf}, }; +#[derive(Debug, Clone)] +struct Template { + pub data: Vec, + pub sha: Option, +} + #[cfg(feature = "fetch-template")] -async fn fetch_template() -> reqwest::Result> { +async fn get_current_sha() -> Result { + let response = + reqwest::get("https://api.github.com/repos/vexide/vexide-template/commits/main?per-page=1") + .await; + let response = match response { + Ok(response) => response, + Err(err) => return Err(CliError::BadResponse(err)), + }; + let response_text = response.text().await.ok().unwrap_or("{}".to_string()); + match &serde_json::from_str::(&response_text).unwrap_or_default()["sha"] { + Value::String(str) => Ok(str.clone()), + _ => unreachable!("Internal error: GitHub API broken"), + } +} + +#[cfg(feature = "fetch-template")] +async fn fetch_template() -> Result { info!("Fetching template..."); let response = reqwest::get("https://github.com/vexide/vexide-template/archive/refs/heads/main.tar.gz") - .await?; + .await; + let response = match response { + Ok(response) => response, + Err(err) => return Err(CliError::BadResponse(err)), + }; let bytes = response.bytes().await?; + info!("Successfully fetched template."); - Ok(bytes.to_vec()) + let template = Template { + data: bytes.to_vec(), + sha: get_current_sha().await.ok(), + }; + Ok(template) } #[cfg(feature = "fetch-template")] -fn cached_template_path() -> Option { - ProjectDirs::from("", "vexide", "cargo-v5").and_then(|dirs| { - dirs.cache_dir() - .canonicalize() - .ok() - .map(|path| path.with_file_name("vexide-template.tar.gz")) - }) +fn cached_template() -> Option