diff options
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/main.rs | 136 | ||||
-rw-r--r-- | src/utils.rs | 53 |
3 files changed, 134 insertions, 56 deletions
@@ -8,4 +8,5 @@ edition = "2021" [dependencies] clap = { version = "3.0", features = ["derive"] } serde = { version = "1.0.140", features = ["derive"] } +colored = "2" serde_json = "1.0"
\ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 95de3b1..cde85c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,18 +16,24 @@ struct Cli { #[derive(Subcommand)] enum Commands { + /// Initialize Godot project for GLAM Init { }, - /// Install new addon + /// Install new GLAM package Install { - /// Addon project git - git_repo: String + /// Package project git + git_repo: String, + /// Verbose (output subshell commands) + #[clap(short, long, takes_value = false)] + verbose: bool }, + /// Update all GLAM packages Update { }, + /// Remove a GLAM package Remove { }, } @@ -37,10 +43,12 @@ struct GlamObject { packages: Vec<GlamPackage> } +// TODO: Add commit hash #[derive(Clone, Debug, Serialize, Deserialize)] struct GlamPackage { name : String, - git_repo : String + git_repo : String, + commit : String, } fn main() { @@ -51,9 +59,9 @@ fn main() { initialize(); }, - Commands::Install {git_repo: git_address} => { + Commands::Install {git_repo, verbose} => { check_initialization(); - install_addon(git_address); + install_addon(git_repo, *verbose); }, Commands::Update {} => { @@ -69,21 +77,25 @@ fn main() { } fn initialize() { - if !Path::new("./.gitignore").exists() { - match write("./.gitignore", content::create_gitignore_file()) { + let root = search_project_root(); + + let git_ignore = &format!("{}/.gitignore", &root); + if !Path::new(git_ignore).exists() { + match write(git_ignore, content::create_gitignore_file()) { Ok(_v) => (), Err(_e) => { - println!("There was a problem creating the .gitignore file!"); + utils::log_error("There was a problem creating the .gitignore file!"); exit(1); } } } - if !Path::new("./.gdignore").exists() { - match write("./.gdignore", content::create_gdignore_file()) { + let gd_ignore = &format!("{}/.gdignore", &root); + if !Path::new(gd_ignore).exists() { + match write(gd_ignore, content::create_gdignore_file()) { Ok(_v) => (), Err(_e) => { - println!("There was a problem creating the .gdignore file!"); + utils::log_error("There was a problem creating the .gdignore file!"); exit(1); } } @@ -91,26 +103,32 @@ fn initialize() { } fn check_initialization() { - if !Path::new("./.gitignore").exists() { - println!(".gitignore file does not exist!"); + let root = search_project_root(); + + let git_ignore = &format!("{}/.gitignore", &root); + if !Path::new(git_ignore).exists() { + utils::log_warning(".gitignore file does not exist!"); } - if !Path::new("./.gdignore").exists() { - println!(".gdignore file does not exist!"); + + let gd_ignore = &format!("{}/.gdignore", &root); + if !Path::new(gd_ignore).exists() { + utils::log_warning(".gdignore file does not exist!"); } } -fn install_addon(git_repo : &str) { - +fn install_addon(git_repo : &str, verbose : bool) { // Search for project root folder let root = search_project_root(); - println!("Found root project in: {}", root); + utils::log_check(&format!("Found root project in: {}", root)); // Create glam.d/ folder if it doesn't exist if !Path::new(&format!("{}/.glam.d/", root)).exists() { utils::run_shell_command( &format!("mkdir -p {}/.glam.d/", root), - None + &root, + false ); + utils::log_info("Created .glam.d/ folder"); } // Create .glam file if it doesn't exist @@ -118,60 +136,82 @@ fn install_addon(git_repo : &str) { fs::write(&format!("{}/.glam",root), content::create_glam_file()) .expect("Couldn't create .glam file!"); + utils::log_info("Created .glam file"); } // Find glam object or create one with default configuration let mut glam_object = read_glam_file(); let mut glam_packages = glam_object.packages; - let mut target_package : Option<GlamPackage> = None; - let name = utils::get_repo_name(git_repo); + let mut package_index = 0; + let mut found_package = false; +// let mut target_package : Option<GlamPackage> = None; + let name = utils::get_repo_name(git_repo); - for package in glam_packages.iter() { + for (i, package) in glam_packages.iter().enumerate() { if package.name == name { - target_package = Some(package.clone()); + package_index = i; + found_package = true; } } - match target_package { - None => { - let package = GlamPackage{ - git_repo : git_repo.to_string(), - name : name.to_string() - }; + if !found_package { + let package = GlamPackage{ + git_repo : git_repo.to_string(), + name : name.to_string(), + commit : "".to_string(), + }; - target_package = Some(package.clone()); - glam_packages.push(package); - } - - _ => {} + glam_packages.push(package); + package_index = glam_packages.len() - 1; } - let target_package = target_package.unwrap(); + let target_package = &mut glam_packages[package_index]; - // If glam addon folder doesn't exist, clone project + // If glam package folder doesn't exist, clone project if !Path::new(&format!("{}/.glam.d/{}", root, target_package.name)).exists() { utils::run_shell_command( - &format!("cd {}/.glam.d/ && git clone {} {}", root, target_package.git_repo, target_package.name), - None + &format!("cd .glam.d/ && git clone {} {} --progress", target_package.git_repo, target_package.name), + &root, + verbose ); - println!("Created addon folder on .glam.d!"); + utils::log_check("Created package folder on .glam.d"); + } else { + utils::log_info("Glam package folder already exists"); + } + + // Update package folder to commit hash + if target_package.commit == "" { + let res = utils::run_shell_command( + &format!("cd .glam.d/{} && git rev-parse HEAD", + target_package.name), + &root, + verbose).unwrap(); + target_package.commit = res.trim().to_string(); } else { - println!("Not Created!"); + utils::log_info("Git checkout to package commit"); + utils::run_shell_command( + &format!("cd .glam.d/{} && git checkout {}", + target_package.name, + target_package.commit), + &root, + verbose); } // If project addon folder doesn't exist, create it utils::run_shell_command( &format!("mkdir -p {}/addons/{}", root, name), - None + &root, + verbose ); // TODO: use source_folder to copy files from (default: /addons/) // TODO: use target_folder to copy files to (defautl: (root)/) // Copy addon repository content to target folder utils::run_shell_command( - &format!("cp -f -r {}/.glam.d/{}/addons/* -t {}/addons/",root, name, root), - None + &format!("cp -f -r .glam.d/{}/addons/* -t {}/addons/", name, root), + &root, + verbose ); // Write .glam file @@ -193,8 +233,7 @@ fn read_glam_file() -> GlamObject { // TODO: Use root folder fn write_glam_file(glam_object : &GlamObject) { - let json_string = serde_json::to_string(glam_object).unwrap(); - println!("{}", json_string); + let json_string = serde_json::to_string_pretty(glam_object).unwrap(); fs::write("./.glam", json_string).expect("Couldn't create .glam file!"); } @@ -211,7 +250,7 @@ fn search_project_root() -> String{ loop { let dir_path = dir.to_str().unwrap(); let proj_path = format!("{}/project.godot", dir_path); - println!("{}", proj_path); + let godot_project = Path::new(&proj_path); if godot_project.exists() { @@ -220,7 +259,8 @@ fn search_project_root() -> String{ else { let parent = dir.parent(); if parent.is_none() { - panic!("Godot project not found!"); + utils::log_error("Godot project not found!"); + exit(1); } dir = dir.parent().unwrap().to_path_buf(); } diff --git a/src/utils.rs b/src/utils.rs index 271cf6d..e925f9d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,26 @@ +use colored::Colorize; +use std::io::Write; + +pub fn log_warning(msg: &str) { + let msg = format!("⚠️ {}", msg).yellow(); + println!("{}", msg); +} + +pub fn log_error(msg: &str) { + let msg = format!("❌ {}", msg).red(); + println!("{}", msg); +} + +pub fn log_info(msg: &str) { + let msg = format!("ℹ️ {}", msg).blue(); + println!("{}", msg); +} + +pub fn log_check(msg: &str) { + let msg = format!("✅ {}", msg).green(); + println!("{}", msg); +} + pub fn get_repo_name(repo: &str) -> String { let mut chars = repo.chars().rev(); let length = repo.chars().count(); @@ -5,7 +28,6 @@ pub fn get_repo_name(repo: &str) -> String { let mut first_i = 0; let mut i = length; - println!("{}", i); while i > 0 { match chars.next() { @@ -25,20 +47,35 @@ pub fn get_repo_name(repo: &str) -> String { last_i = length; } - println!("{} {}", first_i, last_i); let name = &repo[first_i..last_i]; - println!("{}", name); // TODO: Return a Result (may be error) return name.to_string(); } -pub fn run_shell_command(command : &str, folder : Option<&str>) -> bool { - let status = std::process::Command:: +pub fn run_shell_command(command : &str, folder : &str, verbose : bool) -> Result<String, String> { + let output = std::process::Command:: new("sh") - .current_dir(folder.unwrap_or("./")) + .current_dir(folder) + .stdin(std::process::Stdio::inherit()) .arg("-c") .arg(command) - .status() + .output() .expect("Error running command."); - return status.success(); + + if verbose { + std::io::stdout().write_all(&output.stdout).unwrap(); + std::io::stderr().write_all(&output.stderr).unwrap(); + } + + match output.status.success() { + true => { + let stdout_str = String::from_utf8(output.stdout).unwrap(); + return Ok(stdout_str); + } + + false => { + let stderr_str = String::from_utf8(output.stderr).unwrap(); + return Err(stderr_str); + } + } } |