#[macro_use] extern crate rust_util; use argh::FromArgs; use rust_util::util_os::get_user_home; use std::os::unix::fs::PermissionsExt; use std::{env, fs}; use crate::install::install_script; use crate::list::list_scripts; use crate::util::{ build_script_command, get_run_script_bin_name, read_file_and_digest, run_script_command, }; #[cfg(feature = "switch-dart-lang")] mod help_dart; #[cfg(feature = "switch-go-lang")] mod help_go; #[cfg(feature = "switch-js-lang")] mod help_js; #[cfg(feature = "switch-rust-lang")] mod help_rs; mod install; mod list; mod util; #[cfg(feature = "switch-rust-lang")] const CMD_NAME: &str = "runrs"; #[cfg(feature = "switch-go-lang")] const CMD_NAME: &str = "rungo"; #[cfg(feature = "switch-js-lang")] const CMD_NAME: &str = "runjs"; #[cfg(feature = "switch-dart-lang")] const CMD_NAME: &str = "rundart"; #[derive(FromArgs, PartialEq, Debug)] /// Run script struct RunScriptArgs { /// help message #[argh(switch, short = 'h')] help_message: bool, /// script template #[argh(switch, short = 't')] template: bool, /// list scripts #[argh(switch, short = 'l')] list: bool, /// install script #[argh(switch, short = 'i')] install: bool, /// output #[argh(option, short = 'o')] output: Option, /// arguments #[argh(positional, greedy)] arguments: Vec, } fn main() { let rs_args: RunScriptArgs = argh::from_env(); // println!("{:#?}", rs_args); if env::args().len() == 1 { failure_and_exit!( "{} v{}, need arguments, `{} -h` or `{} --help-message` for help", CMD_NAME, env!("CARGO_PKG_VERSION"), CMD_NAME, CMD_NAME, ); } if rs_args.help_message { print_help(); return; } if rs_args.template { print_template(&rs_args.output); return; } if rs_args.list { list_scripts(rs_args.arguments.get(1)); return; } if rs_args.install { if rs_args.arguments.is_empty() { failure_and_exit!("No scripts assigned."); } for (i, script_name) in rs_args.arguments.iter().enumerate() { information!( "Installing script: {} [ {} / {} ]", script_name, (i + 1), rs_args.arguments.len() ); install_script(script_name); } return; } #[cfg(any( feature = "switch-go-lang", feature = "switch-js-lang", feature = "switch-dart-lang" ))] if true { failure_and_exit!("Only rust supports run by runrs."); } if rs_args.arguments.is_empty() { failure_and_exit!("Must assign a script file name"); } let script_file = &rs_args.arguments[0]; let (_, script_sha256) = read_file_and_digest(script_file); debugging!("File {} -> sha256: {}", script_file, script_sha256); let user_home = get_user_home().unwrap_or_else(|| failure_and_exit!("$HOME not found!")); let rust_script = get_run_script_bin_name(&user_home); let cache_script_bin_name = get_cache_script_bin_name(&user_home, &script_sha256); let mut run_script_cmd = build_script_command( rust_script, script_file, &script_sha256, &cache_script_bin_name, ); for arg in rs_args.arguments.iter().skip(1) { run_script_cmd.arg(arg); } run_script_command(script_file, &cache_script_bin_name, &mut run_script_cmd) } fn print_help() { #[cfg(feature = "switch-rust-lang")] help_rs::print_help(); #[cfg(feature = "switch-go-lang")] help_go::print_help(); #[cfg(feature = "switch-js-lang")] help_js::print_help(); #[cfg(feature = "switch-dart-lang")] help_dart::print_help(); } fn print_template(output: &Option) { #[cfg(feature = "switch-rust-lang")] let script = include_str!("script.template.rs"); #[cfg(feature = "switch-go-lang")] let script = include_str!("script.template.go"); #[cfg(feature = "switch-js-lang")] let script = include_str!("script.template.js"); #[cfg(feature = "switch-dart-lang")] let script = include_str!("script.template.dart"); match output { None => { println!("{}", script); } Some(output_file) => { if fs::metadata(output_file).is_ok() { failure!("Output script file exists: {}", output_file); } else { match fs::write(output_file, script) { Ok(_) => { success!("Write script file success: {}", output_file); let _ = fs::set_permissions(&output_file, PermissionsExt::from_mode(0o755)); } Err(e) => { failure!("Write script file: {}, failed: {}", output_file, e); } } } } } } fn get_cache_script_bin_name(user_home: &str, script_sha256: &str) -> String { #[cfg(target_os = "macos")] let cache_script_bin_name = format!( "{}/Library/Caches/rust-script/binaries/release/{}", user_home, script_sha256 ); // #[cfg(target_os = "linux")] #[cfg(not(target_os = "macos"))] let cache_script_bin_name = format!( "{}/.cache/rust-script/binaries/release/{}", user_home, script_sha256 ); cache_script_bin_name }