diff --git a/Cargo.lock b/Cargo.lock index f1fe1ec..bff209c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -665,6 +665,7 @@ dependencies = [ "anyhow", "clap 3.2.16", "clap-nested", + "console", "dirs", "espflash", "flate2", diff --git a/Cargo.toml b/Cargo.toml index 0eafead..160a655 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ winapi = { version = "*", features = ["setupapi", "handleapi", "processthreadsap zip = "*" xz2 = "0.1.6" espflash = "1.6.0" +console = "0.15.1" [target.'cfg(windows)'.dependencies] winreg = "0.10.1" diff --git a/src/main.rs b/src/main.rs index 1516282..1633af0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ type Result = std::result::Result // General TODOs: // - Prettify prints (add emojis) -// - Avoid using shell commands +// - Avoid using shell commands // - Maybe split toolchain into toolchain(espidf, gcc, llvm...) and rust(rust checks, instalaltion and crates) // - Add subcommand test that downloads a projects and builds it // - Esp-idf version should be contained in an enum with the possible values (see chips in espflash for reference) @@ -95,13 +95,13 @@ pub struct UninstallOpts { } fn install(args: InstallOpts) -> Result<()> { - println!("{:?}", args); + // println!("{:?}", args); let arch = guess_host_triple::guess_host_triple().unwrap(); - println!("{}", arch); + // println!("{}", arch); let targets: Vec = parse_targets(&args.build_target)?; - println!("targets: {:?}", targets); + // println!("targets: {:?}", targets); let llvm_version = parse_llvm_version(&args.llvm_version).unwrap(); - println!("llvm_version: {:?}", llvm_version); + // println!("llvm_version: {:?}", llvm_version); let artifact_file_extension = get_artifact_file_extension(arch).to_string(); let llvm_arch = get_llvm_arch(arch).to_string(); @@ -135,21 +135,21 @@ fn install(args: InstallOpts) -> Result<()> { arch ); let mut exports: Vec = Vec::new(); - + check_rust_installation(&args.nightly_version); if args.toolchain_destination.exists() { println!( - "Previous installation of Rust Toolchain exist in: {}", + "{} Previous installation of Rust Toolchain exist in: {}.\n Please, remove the directory before new installation.", + WARN, args.toolchain_destination.display() ); - println!("Please, remove the directory before new installation."); return Ok(()); } else { // install_rust_xtensa_toolchain // Some platfroms like Windows are available in single bundle rust + src, because install // script in dist is not available for the plaform. It's sufficient to extract the toolchain - println!("Installing Xtensa Rust toolchain"); + println!("{} Installing Xtensa Rust toolchain", WRENCH); if get_rust_installer(arch).to_string().is_empty() { // TODO: Check idf_env and adjust // match prepare_package_strip_prefix(&rust_dist_url, @@ -166,19 +166,14 @@ fn install(args: InstallOpts) -> Result<()> { &format!("rust-nightly-{}", arch), ) { Ok(_) => { - println!("Package rust ready"); + println!("{} Package rust ready", SPARKLE); } Err(_e) => { - println!("Unable to prepare rust"); + println!("{} Unable to prepare rust", ERROR); } } - + println!("{} Installing rust", WRENCH); let mut arguments: Vec = [].to_vec(); - println!( - "{}/install.sh --destdir={} --prefix='' --without=rust-docs", - get_tool_path("rust"), - args.toolchain_destination.display() - ); arguments.push("-c".to_string()); arguments.push(format!( "{}/install.sh --destdir={} --prefix='' --without=rust-docs", @@ -188,10 +183,10 @@ fn install(args: InstallOpts) -> Result<()> { match run_command("/bin/bash".to_string(), arguments.clone(), "".to_string()) { Ok(_) => { - println!("rust/install.sh command succeeded"); + println!("{} rust/install.sh command succeeded", SPARKLE); } Err(_e) => { - println!("rust/install.sh command failed"); + println!("{} rust/install.sh command failed", ERROR); } } @@ -201,19 +196,15 @@ fn install(args: InstallOpts) -> Result<()> { "rust-src-nightly", ) { Ok(_) => { - println!("Package rust-src ready"); + println!("{} Package rust-src ready", SPARKLE); } Err(_e) => { - println!("Unable to prepare rust-src"); + println!("{} Unable to prepare rust-src", ERROR); } } + println!("{} Installing rust-src", WRENCH); let mut arguments: Vec = [].to_vec(); - println!( - "{}/install.sh --destdir={} --prefix='' --without=rust-docs", - get_tool_path("rust-src"), - args.toolchain_destination.display() - ); arguments.push("-c".to_string()); arguments.push(format!( "{}/install.sh --destdir={} --prefix='' --without=rust-docs", @@ -222,10 +213,10 @@ fn install(args: InstallOpts) -> Result<()> { )); match run_command("/bin/bash".to_string(), arguments, "".to_string()) { Ok(_) => { - println!("rust-src/install.sh Command succeeded"); + println!("{} rust-src/install.sh Command succeeded", SPARKLE); } Err(_e) => { - println!("rust-src/install.sh Command failed"); + println!("{} rust-src/install.sh Command failed", ERROR); } } } @@ -235,12 +226,11 @@ fn install(args: InstallOpts) -> Result<()> { // TODO: move to function if Path::new(idf_tool_xtensa_elf_clang.as_str()).exists() { println!( - "Previous installation of LLVM exist in: {}", + "{} Previous installation of LLVM exist in: {}.\n Please, remove the directory before new installation.", + WARN, idf_tool_xtensa_elf_clang ); - println!("Please, remove the directory before new installation."); } else { - println!("Downloading xtensa-esp32-elf-clang"); match prepare_package_strip_prefix( &llvm_url, get_tool_path(&format!( @@ -250,10 +240,10 @@ fn install(args: InstallOpts) -> Result<()> { "", ) { Ok(_) => { - println!("Package xtensa-esp32-elf-clang ready"); + println!("{} Package xtensa-esp32-elf-clang ready", SPARKLE); } Err(_e) => { - println!("Unable to prepare xtensa-esp32-elf-clang"); + println!("{} Unable to prepare xtensa-esp32-elf-clang", ERROR); } } } @@ -262,7 +252,7 @@ fn install(args: InstallOpts) -> Result<()> { exports.push(format!("export LIBCLANG_PATH=\"{}\"", &libclang_path)); if targets.contains(&Chip::Esp32c3) { - println!("Installing riscv target"); + println!("{} Installing riscv target", WRENCH); install_riscv_target(&args.nightly_version); } @@ -271,21 +261,24 @@ fn install(args: InstallOpts) -> Result<()> { let mut espidf_targets: String = String::new(); for target in targets { if espidf_targets.is_empty() { - espidf_targets = espidf_targets + &target.to_string().to_lowercase().replace("-",""); + espidf_targets = + espidf_targets + &target.to_string().to_lowercase().replace("-", ""); } else { - espidf_targets = espidf_targets + "," + &target.to_string().to_lowercase().replace("-",""); + espidf_targets = + espidf_targets + "," + &target.to_string().to_lowercase().replace("-", ""); } - } install_espidf(&espidf_targets, &espidf_version)?; exports.push(format!( "export IDF_TOOLS_PATH=\"{}\"", get_espressif_base_path() )); - exports.push(format!("source {}/export.sh", get_espidf_path(&espidf_version))); + exports.push(format!( + "source {}/export.sh", + get_espidf_path(&espidf_version) + )); // TODO: Install ldproxy - } else { println!("No esp-idf version provided. Installing gcc for targets"); exports.extend(install_gcc_targets(targets)?.iter().cloned()); @@ -318,7 +311,6 @@ fn install(args: InstallOpts) -> Result<()> { println!("{}", e); } - Ok(()) } diff --git a/src/toolchain.rs b/src/toolchain.rs index ba2cb2d..a5180c5 100644 --- a/src/toolchain.rs +++ b/src/toolchain.rs @@ -10,17 +10,17 @@ pub fn check_rust_installation(nightly_version: &str) { .output() { Ok(child_output) => { - println!("rustup found."); + println!("{} rustup found", INFO); let result = String::from_utf8_lossy(&child_output.stdout); if !result.contains(nightly_version) { println!("nightly toolchain not found"); install_rust_nightly(nightly_version); } else { - println!("nightly toolchain found."); + println!("{} {} toolchain found", INFO, nightly_version); } } Err(e) => { - println!("Error: {}", e); + println!("{}Error: {}", ERROR, e); install_rustup(); } } @@ -39,12 +39,15 @@ pub fn install_riscv_target(version: &str) { Ok(child_output) => { let result = String::from_utf8_lossy(&child_output.stdout); println!( - "Rust-src for RiscV target installed suscesfully: {}", - result + "{} Rust-src for RiscV target installed suscesfully: {}", + SPARKLE, result ); } Err(e) => { - println!("Rust-src for RiscV target installation failed: {}", e); + println!( + "{} Rust-src for RiscV target installation failed: {}", + ERROR, e + ); } } @@ -59,10 +62,10 @@ pub fn install_riscv_target(version: &str) { { Ok(child_output) => { let result = String::from_utf8_lossy(&child_output.stdout); - println!("RiscV target installed suscesfully: {}", result); + println!("{} RiscV target installed suscesfully: {}", SPARKLE, result); } Err(e) => { - println!("RiscV target installation failed: {}", e); + println!("{} RiscV target installation failed: {}", ERROR, e); } } } @@ -85,16 +88,16 @@ pub fn install_rustup() { { Ok(child_output) => { let result = String::from_utf8_lossy(&child_output.stdout); - println!("{}", result); + println!("{} {}", SPARKLE, result); } Err(e) => { - println!("Error: {}", e); + println!("{} Error: {}", ERROR, e); } } } pub fn install_rust_nightly(version: &str) { - println!("installing nightly toolchain"); + println!("{} Installing {} toolchain", WRENCH, version); match std::process::Command::new("rustup") .arg("toolchain") .arg("install") @@ -106,10 +109,10 @@ pub fn install_rust_nightly(version: &str) { { Ok(child_output) => { let result = String::from_utf8_lossy(&child_output.stdout); - println!("Result: {}", result); + println!("{} Result: {}", SPARKLE, result); } Err(e) => { - println!("Error: {}", e); + println!("{} Error: {}", ERROR, e); } } } @@ -147,7 +150,7 @@ pub fn install_gcc_targets(targets: Vec) -> Result, String> { )); } _ => { - println!("Unknown target") + println!("{} Unknown target", ERROR) } } } @@ -177,9 +180,8 @@ pub fn install_gcc(gcc_target: &str) { } pub fn install_espidf(targets: &str, version: &str) -> Result<(), String> { - let espidf_path = get_espidf_path(version); - println!("ESP-IDF Path: {}", espidf_path); + println!("{} ESP-IDF Path: {}", INFO, espidf_path); #[cfg(windows)] match prepare_package( @@ -236,29 +238,29 @@ pub fn install_espidf(targets: &str, version: &str) -> Result<(), String> { arguments.push("--recursive".to_string()); arguments.push("https://github.com/espressif/esp-idf.git".to_string()); arguments.push(espidf_path.clone()); - println!("Cloning: {} {:?}", git_path, arguments); + println!("{} Dowloading esp-idf {}", DOWNLOAD, version); match run_command(git_path, arguments, "".to_string()) { Ok(_) => { - println!("Cloned esp-idf suscessfuly"); + println!("{} Cloned esp-idf suscessfuly", SPARKLE); } Err(_e) => { - println!("Cloned esp-idf failed"); + println!("{} Cloned esp-idf failed", ERROR); } } } println!( - "Installing esp-idf for {} with {}/install.sh", - targets, espidf_path + "{} Installing esp-idf for {} with {}/install.sh", + WRENCH, targets, espidf_path ); let install_script_path = format!("{}/install.sh", espidf_path); let mut arguments: Vec = [].to_vec(); arguments.push(targets.to_string()); match run_command(install_script_path, arguments, "".to_string()) { Ok(_) => { - println!("ESP-IDF installation succeeded"); + println!("{} ESP-IDF installation succeeded", SPARKLE); } Err(_e) => { - println!("ESP-IDF installation failed"); + println!("{} ESP-IDF installation failed", ERROR); } } // match std::process::Command::new(install_script_path) @@ -283,10 +285,10 @@ pub fn install_espidf(targets: &str, version: &str) -> Result<(), String> { arguments.push("cmake".to_string()); match run_command(python_path, arguments, "".to_string()) { Ok(_) => { - println!("CMake installation succeeded"); + println!("{} CMake installation succeeded", SPARKLE); } Err(_e) => { - println!("CMake installation failed"); + println!("{} CMake installation failed", ERROR); } } diff --git a/src/utils.rs b/src/utils.rs index cad5820..4ce6855 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,4 @@ +use console::Emoji; use dirs::home_dir; use espflash::Chip; use flate2::bufread::GzDecoder; @@ -11,8 +12,16 @@ use tar::Archive; use tokio::runtime::Handle; use xz2::read::XzDecoder; +pub static ERROR: Emoji<'_, '_> = Emoji("⛔ ", ""); +pub static SPARKLE: Emoji<'_, '_> = Emoji("✨ ", ""); +pub static WARN: Emoji<'_, '_> = Emoji("⚠️ ", ""); +pub static WRENCH: Emoji<'_, '_> = Emoji("🔧 ", ""); +pub static DOWNLOAD: Emoji<'_, '_> = Emoji("📥 ", ""); +pub static INFO: Emoji<'_, '_> = Emoji("💡 ", ""); +// pub static DIAMOND: Emoji<'_, '_> = Emoji("🔸 ", ""); + pub fn parse_targets(build_target: &str) -> Result, String> { - println!("Parsing targets: {}", build_target); + // println!("Parsing targets: {}", build_target); let mut chips: Vec = Vec::new(); if build_target.contains("all") { chips.push(Chip::Esp32); @@ -109,12 +118,18 @@ pub fn get_tool_path(tool_name: &str) -> String { } pub fn get_espidf_path(version: &str) -> String { - let parsed_version: String = version.chars() - .map(|x| match x { - '/' => '-', - _ => x - }).collect(); - format!("{}frameworks/esp-idf-{}", get_espressif_base_path(), parsed_version) + let parsed_version: String = version + .chars() + .map(|x| match x { + '/' => '-', + _ => x, + }) + .collect(); + format!( + "{}frameworks/esp-idf-{}", + get_espressif_base_path(), + parsed_version + ) } pub fn prepare_package_strip_prefix( @@ -123,26 +138,23 @@ pub fn prepare_package_strip_prefix( strip_prefix: &str, ) -> Result<(), String> { println!( - "prepare_package_strip_prefix: - -pacakge_url: {} - -output dir: {} - -strip_prefix: {}", - &package_url, &output_directory, &strip_prefix + "{} Dowloading and uncompressing {} to {}", + DOWNLOAD, &package_url, &output_directory ); if Path::new(&output_directory).exists() { - println!("Using cached directory: {}", output_directory); + println!("{} Using cached directory: {}", WARN, output_directory); return Ok(()); } let tools_path = get_tool_path(""); if !Path::new(&tools_path).exists() { - println!("Creating tools directory: {}", tools_path); + println!("{} Creating tools directory: {}", WRENCH, tools_path); match fs::create_dir_all(&tools_path) { Ok(_) => { - println!("tools_path created"); + println!("{} Directory tools_path created", SPARKLE); } Err(_e) => { - println!("tools_path creating failed"); + println!("{} Directory tools_path creation failed", ERROR); } } } @@ -159,7 +171,10 @@ pub fn prepare_package_strip_prefix( } if !strip_prefix.is_empty() { let extracted_folder = format!("{}{}", &tools_path, strip_prefix); - println!("Renaming: {} to {}", &extracted_folder, &output_directory); + println!( + "{} Renaming: {} to {}", + INFO, &extracted_folder, &output_directory + ); fs::rename(extracted_folder, output_directory).unwrap(); } Ok(()) @@ -226,12 +241,12 @@ pub fn prepare_single_binary( let binary_path = format!("{}/{}", tool_path, binary_name); if Path::new(&binary_path).exists() { - println!("Using cached tool: {}", binary_path); + println!("{} Using cached tool: {}", WARN, binary_path); return binary_path; } if !Path::new(&tool_path).exists() { - println!("Creating tool directory: {}", tool_path); + println!("{} Creating tool directory: {}", WRENCH, tool_path); match fs::create_dir_all(&tool_path) { Ok(_) => { println!("Ok"); @@ -244,10 +259,10 @@ pub fn prepare_single_binary( match download_package(package_url.to_string(), binary_path.to_string()) { Ok(_) => { - println!("Ok"); + println!("{} Succeded", SPARKLE); } Err(_e) => { - println!("Failed"); + println!("{} Failed", ERROR); } } binary_path @@ -277,10 +292,10 @@ pub fn download_package(package_url: String, package_archive: String) -> Result< async fn download_file(url: String, output: String) -> Result<(), String> { if Path::new(&output).exists() { - println!("Using cached archive: {}", output); + println!("{} Using cached archive: {}", WRENCH, output); return Ok(()); } - println!("Downloading {} to {}", url, output); + println!("{} Downloading {} to {}", DOWNLOAD, url, output); fetch_url(url, output).await } @@ -294,7 +309,7 @@ async fn fetch_url(url: String, output: String) -> Result<(), String> { return Ok(()); } _ => { - println!("Download of {} failed", url); + println!("{} Download of {} failed", ERROR, url); // Exit code is 0, there is temporal issue with Windows Installer which does not recover from error exit code #[cfg(windows)] std::process::exit(0);