diff --git a/script-config.json b/script-config.json new file mode 100644 index 0000000..68d5b2f --- /dev/null +++ b/script-config.json @@ -0,0 +1,6 @@ +{ + "file_ext": "rs", + "simple_script_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/master/single-scripts/$NAME", + "project_script_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/$NAME/src/main.rs", + "skip_dirs": [] +} diff --git a/script-meta-v2.json b/script-meta-v2.json new file mode 100644 index 0000000..2fae76d --- /dev/null +++ b/script-meta-v2.json @@ -0,0 +1,87 @@ +{ + "bit-address.rs": { + "script_name": "bit-address.rs", + "script_length": 3877, + "script_sha256": "806980fef2db63d42024010bc7bc010664ec616662164fb6490ca9389502d869", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/bit-address-rs/src/main.rs" + }, + "commit-msg.rs": { + "script_name": "commit-msg.rs", + "script_length": 6618, + "script_sha256": "63d1569f1ae8b5b9c14e3be8a79841dbf67e954c16e1bb16f07c2b2f6660c88f", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/commit-msg-rs/src/main.rs" + }, + "current-time.rs": { + "script_name": "current-time.rs", + "script_length": 3301, + "script_sha256": "51536795cafedf593184a2690f08ee8fc2be9b5dccdd8a52fafa025d66c26e96", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/current-time-rs/src/main.rs" + }, + "decrypt.rs": { + "script_name": "decrypt.rs", + "script_length": 3087, + "script_sha256": "7f5bb37855da9b350fb1ca646fd75a3a71533a8f5f7913ac81036ad1b2082f3c", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/decrypt-rs/src/main.rs" + }, + "derparse.rs": { + "script_name": "derparse.rs", + "script_length": 7368, + "script_sha256": "423eb3c6ce57baf7bc8c9f452fdead2f3dc3d86f3724aa8bd7016ece8ce1853b", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/derparse-rs/src/main.rs" + }, + "helloworld.rs": { + "script_name": "helloworld.rs", + "script_length": 64, + "script_sha256": "b1cf245146e6684986b1f0788d2282fdb1c617eac0961a84bfbd65f386975993", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/master/single-scripts/helloworld.rs", + "single_script_file": true + }, + "makepassword.rs": { + "script_name": "makepassword.rs", + "script_length": 1966, + "script_sha256": "0ca721d3531a9cc94c95193e7148c0316551fd65d84de7f54bd4b6418ff37f01", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/makepassword-rs/src/main.rs" + }, + "myip.rs": { + "script_name": "myip.rs", + "script_length": 933, + "script_sha256": "9756186298cf6a65561760603e6369ee961e3271ea0cf86361b88c2250c3e690", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/myip-rs/src/main.rs" + }, + "osssendfile.rs": { + "script_name": "osssendfile.rs", + "script_length": 13853, + "script_sha256": "218eecef46329fb6d73986d3db1a07dd29fe99269f46290eda165e5f3d663ca9", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/osssendfile-rs/src/main.rs" + }, + "post.rs": { + "script_name": "post.rs", + "script_length": 10494, + "script_sha256": "fe3571fdcd170608575c610ba51fcaeee7aea0fe82ae4bc22032f61c7787d22f", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/post-rs/src/main.rs" + }, + "rpm-read.rs": { + "script_name": "rpm-read.rs", + "script_length": 637, + "script_sha256": "2338fb99c2803fc36ecdb09ec04eeb9aefb3524f8a68db4875562fdf3c8ba3f8", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/rpm-read-rs/src/main.rs" + }, + "script-sign.rs": { + "script_name": "script-sign.rs", + "script_length": 16506, + "script_sha256": "d8dc82553a5300ecee3364ed04596163295139f8b18e0d1a95b89ea6540ebfe5", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/script-sign-rs/src/main.rs" + }, + "sync.rs": { + "script_name": "sync.rs", + "script_length": 1818, + "script_sha256": "d947c179820a9d13284de9b8d0173f1738a06fbcacb40473a02aa94417c53454", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/sync-rs/src/main.rs" + }, + "xattr.rs": { + "script_name": "xattr.rs", + "script_length": 1822, + "script_sha256": "b49aadee8bdb76217ee3ce880b1ac8fbcc2af14a7c99053a7e847079ef5822b4", + "script_full_url": "https://git.hatter.ink/rust-scripts/scriptbase/raw/branch/main/xattr-rs/src/main.rs" + } +} \ No newline at end of file diff --git a/single-scripts/helloworld.rs b/single-scripts/helloworld.rs new file mode 100755 index 0000000..87094ab --- /dev/null +++ b/single-scripts/helloworld.rs @@ -0,0 +1,5 @@ +#!/usr/bin/env runrs + +fn main() { + println!("Hello World."); +} diff --git a/update-meta-rs/src/main.rs b/update-meta-rs/src/main.rs index 4b1d06e..c400720 100755 --- a/update-meta-rs/src/main.rs +++ b/update-meta-rs/src/main.rs @@ -8,26 +8,68 @@ //! rust_util = { version = "0.6" } //! ``` -use rust_util::{debugging, failure_and_exit, opt_result, opt_value_result, success, XResult}; -use serde::Serialize; +use rust_util::{ + debugging, failure_and_exit, iff, opt_result, opt_value_result, success, warning, XResult, +}; +use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fs; +use std::option::Option; use std::path::PathBuf; -const SCRIPT_META_FILE: &str = "script-meta.json"; +const SCRIPT_META_FILE: &str = "script-meta-v2.json"; +const SCRIPT_CONFIG_FILE: &str = "script-config.json"; +const SINGLE_SCRIPTS_DIR: &str = "single-scripts"; + +#[derive(Debug, Deserialize)] +struct ScriptConfig { + file_ext: String, + simple_script_url: String, + project_script_url: String, + skip_dirs: Vec, +} + +impl ScriptConfig { + fn skip_dir(&self, dir: &str) -> bool { + for skip_dir in &self.skip_dirs { + if skip_dir == dir { + return true; + } + } + dir == "update-meta-rs" || dir == SINGLE_SCRIPTS_DIR || dir.starts_with(".") + } +} #[derive(Serialize)] struct ScriptMeta { script_name: String, script_length: u64, script_sha256: String, + script_full_url: String, + #[serde(skip_serializing_if = "Option::is_none")] + single_script_file: Option, } fn main() -> XResult<()> { + if fs::metadata(SCRIPT_CONFIG_FILE).is_err() { + failure_and_exit!("Script config file {} not found.", SCRIPT_CONFIG_FILE); + } if fs::metadata(SCRIPT_META_FILE).is_err() { failure_and_exit!("Script meta file {} not found.", SCRIPT_META_FILE); } + let script_config_content = opt_result!( + fs::read_to_string(SCRIPT_CONFIG_FILE), + "Read {}, failed: {}", + SCRIPT_CONFIG_FILE + ); + let script_config: ScriptConfig = opt_result!( + serde_json::from_str(&script_config_content), + "Parse {}, failed: {}", + SCRIPT_CONFIG_FILE + ); + debugging!("Script config: {:#?}", script_config); + let mut script_meta_map = BTreeMap::new(); let current_read_dir = opt_result!(fs::read_dir("."), "Read dir '.' failed: {}"); @@ -40,19 +82,67 @@ fn main() -> XResult<()> { debugging!("Skip none dir: {}", script_dir); continue; } - if "update-meta-rs" == script_dir || script_dir.starts_with(".") { - debugging!("Skip update meta rs: {}", script_dir); + if script_config.skip_dir(&script_dir) { + debugging!("Skip update skip dirs: {}", script_dir); continue; } let abs_dir_entry = std::path::absolute(&dir_entry.path())?; - let main_rs = abs_dir_entry + let main_script = abs_dir_entry .join("src") - .join("main.rs"); + .join(format!("main.{}", script_config.file_ext)); - script_meta_map.insert( - script_dir.to_string(), - read_script_meta(script_dir, &main_rs)?, - ); + if let Some(script_file_name) = + translate_script_dir_to_script_name(script_dir, &script_config) + { + script_meta_map.insert( + script_file_name.clone(), + read_script_meta( + script_dir, + script_file_name.clone(), + &main_script, + false, + &script_config, + )?, + ); + } + } + + if let Ok(single_script_meta) = fs::metadata(SINGLE_SCRIPTS_DIR) { + if single_script_meta.is_dir() { + let single_scripts_read_dir = + opt_result!(fs::read_dir(SINGLE_SCRIPTS_DIR), "Read dir '.' failed: {}"); + for file in single_scripts_read_dir { + let file_entry = opt_result!(file, "Get dir failed: {}"); + let dir_file_type = opt_result!(file_entry.file_type(), "Get dir type failed: {}"); + let file_name_os_string = file_entry.file_name(); + let script_file = + opt_value_result!(file_name_os_string.to_str(), "Cannot get file name."); + if !dir_file_type.is_file() { + debugging!("Skip none file: {}", script_file); + continue; + } + let abs_file_entry = std::path::absolute(&file_entry.path())?; + let script_file_ext = format!(".{}", script_config.file_ext); + if !script_file.ends_with(&script_file_ext) { + continue; + } + let script_file_name = script_file.to_string(); + if script_meta_map.contains_key(&script_file_name) { + warning!("Script: {script_file_name} exists."); + continue; + } + script_meta_map.insert( + script_file_name.clone(), + read_script_meta( + "", + script_file_name.clone(), + &abs_file_entry, + true, + &script_config, + )?, + ); + } + } } let script_meta_json = serde_json::to_string_pretty(&script_meta_map)?; @@ -64,13 +154,52 @@ fn main() -> XResult<()> { Ok(()) } -fn read_script_meta(file_name: &str, main_rs: &PathBuf) -> XResult { - let main_rs_meta = opt_result!(main_rs.metadata(), "Read file: {:?} meta failed: {}", main_rs); - let main_rs_content = fs::read(main_rs)?; - let script_sha256 = sha256::digest(&main_rs_content); +// translate filename-ext to filename.ext +fn translate_script_dir_to_script_name( + script_dir: &str, + script_config: &ScriptConfig, +) -> Option { + let script_dir_ext = format!("-{}", script_config.file_ext); + if script_dir.ends_with(&script_dir_ext) { + let remove_ext_dir_name = script_dir + .chars() + .take(script_dir.len() - script_dir_ext.len()) + .collect::(); + Some(format!("{remove_ext_dir_name}.{}", script_config.file_ext)) + } else { + None + } +} + +fn read_script_meta( + script_dir: &str, + script_name: String, + script_path: &PathBuf, + is_simple_script: bool, + script_config: &ScriptConfig, +) -> XResult { + let script_meta = opt_result!( + script_path.metadata(), + "Read file: {:?} meta failed: {}", + script_path + ); + let script_path_content = fs::read(script_path)?; + let script_sha256 = sha256::digest(&script_path_content); + let script_full_url = if is_simple_script { + script_config + .simple_script_url + .replace("$NAME", &script_name) + } else { + script_config + .project_script_url + .replace("$NAME", script_dir) + }; + let single_script_file = iff!(is_simple_script, Some(true), None); Ok(ScriptMeta { - script_name: file_name.to_string(), - script_length: main_rs_meta.len(), + script_name: script_name.clone(), + script_length: script_meta.len(), script_sha256, + script_full_url, + single_script_file, }) }