Skip to content

Commit

Permalink
Feat(*): Added Cache & Reinstall Arguments (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
WillKirkmanM committed May 3, 2023
2 parents 6aba77e + e056aa1 commit 8510eb0
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 68 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
name = "sandbox"
version = "0.1.1"
version = "0.2.1"
edition = "2021"
authors = ["WillKirkmanM <[email protected]>"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
clap = { version = "4.2.4", features = ["derive"] }
clap = { version = "4.2.7", features = ["derive"] }
colored = "2.0.0"
flate2 = "1.0.26"
indicatif = "0.17.3"
Expand Down
17 changes: 13 additions & 4 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@ pub struct SandboxArgs {
#[clap(short, long, default_value = "")]
pub new: String,

/// Create a New Environment
#[clap(short = 'U', long, default_value = "")]
pub uninstall: String,

/// Search for Environment
#[clap(short = 'S', long, default_value = "")]
pub search: String,

/// Search for Environment
#[clap(short = 'I', long, default_value = "")]
pub install: String,

/// Create a New Environment
#[clap(short = 'U', long, default_value = "")]
pub uninstall: String,

/// Reinstall an Environment
#[clap(short = 'R', long)]
pub reinstall: String,

/// Clear the Install Cache
#[clap(short = 'C', long)]
pub clearcache: bool,

}

41 changes: 41 additions & 0 deletions src/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::path::Path;

use tokio::fs;
use colored::Colorize;

use crate::{get_path, get_cache_path};

pub async fn ensure_installed() {
let cache_path = get_cache_path();

fs::create_dir_all(cache_path).await.unwrap();
}

pub async fn clear_cache() {
let cache_path = get_cache_path();

let cache_folder_is_empty = fs::read_dir(&cache_path).await.unwrap().next_entry().await.unwrap().is_none();

if cache_folder_is_empty {
println!("The Install Cache is {}!", "Empty".bright_green())
} else {
fs::remove_dir_all(&cache_path).await.unwrap();
fs::create_dir(&cache_path).await.unwrap();

println!("{} Cleared The Install Cache!", "Successfully".bright_green())
}
}

pub async fn in_cache(id: impl Into<String>) -> bool {
let id = id.into();

let cache_path = get_cache_path();

let environment_path = get_path(&id).await;
let tar_name = environment_path.split('/').last().unwrap();

let formatted_cache_path = format!("{}{}", cache_path, tar_name);
let tar_in_cache = Path::new(&formatted_cache_path).exists();

tar_in_cache
}
119 changes: 78 additions & 41 deletions src/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::path::Path;
use std::thread;
use std::time::Duration;
use std::fs;
use std::env;
use std::{cmp::min, fmt::Write};


Expand All @@ -15,66 +14,104 @@ use tar::Archive;
use indicatif::{ProgressBar, ProgressState, ProgressStyle};
use colored::Colorize;

use crate::get_beaches_path;
use crate::get_cache_path;
use crate::get_path;
use crate::cache::{self, in_cache};

pub async fn install(id: String) -> Result<(), Box<dyn Error>> {
let base_path = match env::consts::OS {
"windows" => {
let appdata = std::env::var("appdata").unwrap();
let beaches_path = format!("{}/sandbox/beaches/", appdata);
beaches_path
}
_ => "/usr/share/sandbox/beaches/".to_string()
};
pub async fn install(id: impl Into<String>) -> Result<(), Box<dyn Error>> {
let id = id.into();

let environment_path = get_path(id.clone()).await;
let base_path = get_beaches_path();
let environment_path = get_path(&id).await;

let download_url = format!("https://github.com/the-sandbox-project/sandbox-templates/raw/master/{}", environment_path);
let download_path = format!("{}{}", base_path, environment_path);

let client = Client::new();

let response = client.get(download_url).send().await?;

if response.status().is_success() {
let language_path = Path::new(&download_path).parent().unwrap().to_str().unwrap();
fs::create_dir_all(language_path)?;
let tar_name = environment_path.split('/').last().unwrap();

cache::ensure_installed().await;
let cache_path = get_cache_path();

let mut file = File::create(&download_path)?;
let formatted_cache_path = format!("{}{}", cache_path, tar_name);

let mut downloaded = 0;
let total_size = response.content_length().unwrap();
if in_cache(&id).await {
println!("{} found in {}! Installing from {}...", id.blue(), "Cache".bright_green(), "Cache".bright_green());

let pb = ProgressBar::new(total_size);
pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
.unwrap()
.with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap())
.progress_chars("#>-"));
let language_path = Path::new(&download_path).parent().unwrap().to_str().unwrap();

while downloaded < total_size {
let new = min(downloaded + 223211, total_size);
downloaded = new;
pb.set_position(new);
thread::sleep(Duration::from_millis(12));
}

pb.finish_with_message("downloaded");
let unzip_path = format!("{}/{}", language_path, id);

let content = response.bytes().await?;
fs::create_dir_all(&language_path)?;

io::copy(&mut content.as_ref(), &mut file)?;

let unzip_path = format!("{}/{}", language_path, id);
fs::copy(&formatted_cache_path, &download_path)?;

let tar_gz = File::open(&download_path)?;
let tar = GzDecoder::new(tar_gz);
let mut archive = Archive::new(tar);

archive.unpack(&unzip_path)?;

File::create(&formatted_cache_path)?;

fs::copy(&download_path, &formatted_cache_path)?;

fs::remove_file(&download_path)?;

println!("Installed {}! Test it out with: sandbox --new {}", id.bright_green(), id.bright_green())
}
Ok(())
println!("Installed {}! Test it out with: sandbox --new {}", id.bright_green(), id.bright_green());

Ok(())
} else {
let client = Client::new();

let response = client.get(download_url).send().await?;

if response.status().is_success() {
let language_path = Path::new(&download_path).parent().unwrap().to_str().unwrap();

fs::create_dir_all(language_path)?;

let mut file = File::create(&download_path)?;

let mut downloaded = 0;
let total_size = response.content_length().unwrap();

let pb = ProgressBar::new(total_size);
pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
.unwrap()
.with_key("eta", |state: &ProgressState, w: &mut dyn Write| write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap())
.progress_chars("#>-"));

while downloaded < total_size {
let new = min(downloaded + 223211, total_size);
downloaded = new;
pb.set_position(new);
thread::sleep(Duration::from_millis(12));
}

pb.finish_with_message("downloaded");

let content = response.bytes().await?;

io::copy(&mut content.as_ref(), &mut file)?;

let unzip_path = format!("{}/{}", language_path, id);

let tar_gz = File::open(&download_path)?;
let tar = GzDecoder::new(tar_gz);
let mut archive = Archive::new(tar);

archive.unpack(&unzip_path)?;

File::create(&formatted_cache_path)?;

fs::copy(&download_path, &formatted_cache_path)?;

fs::remove_file(&download_path)?;

println!("Installed {}! Test it out with: sandbox --new {}", id.bright_green(), id.bright_green())
}
Ok(())
}
}

2 changes: 1 addition & 1 deletion src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::get_path;
pub async fn open_environment(environment: String) {
let editor = get_editor();

let path = get_path(environment.clone()).await;
let path = get_path(&environment).await;
let environment_path = path.split("/").collect::<Vec<&str>>()[0].to_owned() + "/" + &environment;

let beaches_path = match env::consts::OS {
Expand Down
49 changes: 40 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ mod environment;
mod search;
mod install;
mod uninstall;
mod reinstall;
mod download;
mod cache;
mod new;

use std::error::Error;
Expand All @@ -16,7 +18,9 @@ use args::SandboxArgs;
use search::search;
use install::install_environment;
use uninstall::uninstall_environment;
use reinstall::reinstall_environment;
use new::create_new_environment;
use cache::clear_cache;

use clap::Parser;
use serde_yaml::{Value, Mapping};
Expand All @@ -40,6 +44,14 @@ pub async fn run() {
if !args.uninstall.is_empty() {
uninstall_environment(args.uninstall).await;
}

if !args.reinstall.is_empty() {
reinstall_environment(args.reinstall).await;
}

if args.clearcache {
clear_cache().await;
}
}

pub async fn get_templates_mapping() -> Result<Mapping, Box<dyn Error>> {
Expand Down Expand Up @@ -140,16 +152,9 @@ pub async fn id_is_valid(id: impl Into<String>) -> bool{
pub async fn in_system(id: impl Into<String>) -> bool {
let id = id.into();

let base_path = match env::consts::OS {
"windows" => {
let appdata = std::env::var("appdata").unwrap();
let beaches_path = format!("{}/sandbox/beaches/", appdata);
beaches_path
}
_ => "/usr/share/sandbox/beaches/".to_string(),
};
let base_path = get_beaches_path();

let path = get_path(id.clone()).await;
let path = get_path(&id).await;
let environment_path = path.split("/").collect::<Vec<&str>>()[0].to_owned() + "/" + &id;
let formatted_path = format!("{}{}", base_path, environment_path);

Expand All @@ -161,3 +166,29 @@ pub async fn in_system(id: impl Into<String>) -> bool {
false
}
}

pub fn get_beaches_path() -> String {
match env::consts::OS {
"windows" => {
let appdata = env::var("APPDATA").unwrap();
let beaches_path = format!("{}/sandbox/beaches/", appdata);
beaches_path
}
_ => "/usr/share/sandbox/beaches/".to_string(),
}
}

pub fn get_cache_path() -> String {
match env::consts::OS {
"windows" => {
let appdata = env::var("LOCALAPPDATA").unwrap();
let beaches_path = format!("{}/Temp/sandbox/", appdata);
beaches_path
}
_ => {
let home_path = env::var("HOME").unwrap();
let cache_path = format!("{}/.cache/sandbox/", home_path);
cache_path
}
}
}
22 changes: 22 additions & 0 deletions src/reinstall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::id_is_valid;
use crate::download::install;
use crate::uninstall::uninstall;

use colored::Colorize;

pub async fn reinstall_environment(id: impl Into<String>) {
let id = id.into();

if id_is_valid(&id).await {
reinstall(&id).await;
} else {
println!("The environment ({}) does {} exist! You can search for an environment with\nsandbox --search {}", id.bright_green(), "not".red(), id.bright_green());
}
}

pub async fn reinstall(id: impl Into<String>) {
let id = id.into();

uninstall(&id).await;
install(&id).await.unwrap();
}
14 changes: 3 additions & 11 deletions src/uninstall.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::env;
use std::io::{stdin, stdout, Write};

use crate::{get_path, id_is_valid, in_system};
use crate::{get_path, get_beaches_path, id_is_valid, in_system};

use colored::Colorize;
use tokio::fs;
Expand All @@ -28,16 +27,9 @@ pub async fn uninstall_environment(environment: impl Into<String>) {
pub async fn uninstall(environment: impl Into<String>) {
let environment = environment.into();

let base_path = match env::consts::OS {
"windows" => {
let appdata = std::env::var("appdata").unwrap();
let beaches_path = format!("{}/sandbox/beaches/", appdata);
beaches_path
}
_ => "/usr/share/sandbox/beaches/".to_string(),
};
let base_path = get_beaches_path();

let path = get_path(environment.clone()).await;
let path = get_path(&environment).await;
let environment_path = path.split("/").collect::<Vec<&str>>()[0].to_owned() + "/" + &environment;

let formatted_path = format!("{}{}", base_path, environment_path);
Expand Down

0 comments on commit 8510eb0

Please sign in to comment.