feat: script-meta-v2

This commit is contained in:
2025-01-18 12:41:12 +08:00
parent 709c4b1e72
commit 6b5f301086
4 changed files with 244 additions and 17 deletions

View File

@@ -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<String>,
}
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<bool>,
}
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<ScriptMeta> {
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<String> {
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::<String>();
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<ScriptMeta> {
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,
})
}