Fix recusive path not works when custom path is provided

This commit is contained in:
2025-07-31 17:20:30 +08:00
parent b878ad0e7a
commit 334acbb633
2 changed files with 118 additions and 18 deletions

View File

@@ -346,7 +346,7 @@ pub fn export_script(
arg: &args::Arg, arg: &args::Arg,
config: &types::ExtraConfig, config: &types::ExtraConfig,
output: &Option<String>, output: &Option<String>,
is_dir: bool, root_dir: Option<&std::path::Path>,
) -> anyhow::Result<types::ScriptResult> { ) -> anyhow::Result<types::ScriptResult> {
eprintln!("Exporting {}", filename); eprintln!("Exporting {}", filename);
let script = parse_script(filename, arg, config)?.0; let script = parse_script(filename, arg, config)?.0;
@@ -355,7 +355,11 @@ pub fn export_script(
Some(output) => { Some(output) => {
let mut pb = std::path::PathBuf::from(output); let mut pb = std::path::PathBuf::from(output);
let filename = std::path::PathBuf::from(filename); let filename = std::path::PathBuf::from(filename);
if is_dir { if let Some(root_dir) = root_dir {
let rpath = utils::files::relative_path(root_dir, &filename);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = filename.file_name() { if let Some(fname) = filename.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -679,9 +683,13 @@ pub fn export_script(
let out_type = arg.image_type.unwrap_or(types::ImageOutputType::Png); let out_type = arg.image_type.unwrap_or(types::ImageOutputType::Png);
let f = match output.as_ref() { let f = match output.as_ref() {
Some(output) => { Some(output) => {
if is_dir { if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(output); let mut pb = std::path::PathBuf::from(output);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if !arg.image_output_flat { if !arg.image_output_flat {
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
@@ -750,9 +758,13 @@ pub fn export_script(
} else { } else {
match output.as_ref() { match output.as_ref() {
Some(output) => { Some(output) => {
if is_dir { if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(output); let mut pb = std::path::PathBuf::from(output);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -769,6 +781,7 @@ pub fn export_script(
} }
} }
}; };
utils::files::make_sure_dir_exists(&f)?;
utils::img::encode_img(img_data, out_type, &f, config)?; utils::img::encode_img(img_data, out_type, &f, config)?;
return Ok(types::ScriptResult::Ok); return Ok(types::ScriptResult::Ok);
} }
@@ -798,9 +811,13 @@ pub fn export_script(
} else { } else {
match output.as_ref() { match output.as_ref() {
Some(output) => { Some(output) => {
if is_dir { if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(output); let mut pb = std::path::PathBuf::from(output);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -817,6 +834,7 @@ pub fn export_script(
} }
} }
}; };
utils::files::make_sure_dir_exists(&f)?;
match of { match of {
types::OutputScriptType::Json => { types::OutputScriptType::Json => {
let enc = get_output_encoding(arg); let enc = get_output_encoding(arg);
@@ -845,7 +863,7 @@ pub fn import_script(
arg: &args::Arg, arg: &args::Arg,
config: &types::ExtraConfig, config: &types::ExtraConfig,
imp_cfg: &args::ImportArgs, imp_cfg: &args::ImportArgs,
is_dir: bool, root_dir: Option<&std::path::Path>,
name_csv: Option<&std::collections::HashMap<String, String>>, name_csv: Option<&std::collections::HashMap<String, String>>,
repl: Option<&types::ReplacementTable>, repl: Option<&types::ReplacementTable>,
) -> anyhow::Result<types::ScriptResult> { ) -> anyhow::Result<types::ScriptResult> {
@@ -855,7 +873,11 @@ pub fn import_script(
let odir = { let odir = {
let mut pb = std::path::PathBuf::from(&imp_cfg.output); let mut pb = std::path::PathBuf::from(&imp_cfg.output);
let filename = std::path::PathBuf::from(filename); let filename = std::path::PathBuf::from(filename);
if is_dir { if let Some(root_dir) = root_dir {
let rpath = utils::files::relative_path(root_dir, &filename);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = filename.file_name() { if let Some(fname) = filename.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -868,9 +890,13 @@ pub fn import_script(
}; };
let files: Vec<_> = script.iter_archive_filename()?.collect(); let files: Vec<_> = script.iter_archive_filename()?.collect();
let files = files.into_iter().filter_map(|f| f.ok()).collect::<Vec<_>>(); let files = files.into_iter().filter_map(|f| f.ok()).collect::<Vec<_>>();
let patched_f = if is_dir { let patched_f = if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(&imp_cfg.patched); let mut pb = std::path::PathBuf::from(&imp_cfg.patched);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -882,6 +908,7 @@ pub fn import_script(
let files: Vec<_> = files.iter().map(|s| s.as_str()).collect(); let files: Vec<_> = files.iter().map(|s| s.as_str()).collect();
let pencoding = get_patched_encoding(imp_cfg, builder); let pencoding = get_patched_encoding(imp_cfg, builder);
let enc = get_patched_archive_encoding(imp_cfg, builder, pencoding); let enc = get_patched_archive_encoding(imp_cfg, builder, pencoding);
utils::files::make_sure_dir_exists(&patched_f)?;
let mut arch = builder.create_archive(&patched_f, &files, enc, config)?; let mut arch = builder.create_archive(&patched_f, &files, enc, config)?;
for (index, filename) in script.iter_archive_filename()?.enumerate() { for (index, filename) in script.iter_archive_filename()?.enumerate() {
let filename = match filename { let filename = match filename {
@@ -1126,9 +1153,13 @@ pub fn import_script(
#[cfg(feature = "image")] #[cfg(feature = "image")]
if script.is_image() { if script.is_image() {
let out_type = arg.image_type.unwrap_or(types::ImageOutputType::Png); let out_type = arg.image_type.unwrap_or(types::ImageOutputType::Png);
let out_f = if is_dir { let out_f = if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(&imp_cfg.output); let mut pb = std::path::PathBuf::from(&imp_cfg.output);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -1138,9 +1169,13 @@ pub fn import_script(
imp_cfg.output.clone() imp_cfg.output.clone()
}; };
let data = utils::img::decode_img(out_type, &out_f)?; let data = utils::img::decode_img(out_type, &out_f)?;
let patched_f = if is_dir { let patched_f = if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(&imp_cfg.patched); let mut pb = std::path::PathBuf::from(&imp_cfg.patched);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -1149,6 +1184,7 @@ pub fn import_script(
} else { } else {
imp_cfg.patched.clone() imp_cfg.patched.clone()
}; };
utils::files::make_sure_dir_exists(&patched_f)?;
script.import_image_filename(data, &patched_f)?; script.import_image_filename(data, &patched_f)?;
return Ok(types::ScriptResult::Ok); return Ok(types::ScriptResult::Ok);
} }
@@ -1159,9 +1195,13 @@ pub fn import_script(
if !script.is_output_supported(of) { if !script.is_output_supported(of) {
of = script.default_output_script_type(); of = script.default_output_script_type();
} }
let out_f = if is_dir { let out_f = if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(&imp_cfg.output); let mut pb = std::path::PathBuf::from(&imp_cfg.output);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -1197,9 +1237,13 @@ pub fn import_script(
return Ok(types::ScriptResult::Ignored); return Ok(types::ScriptResult::Ignored);
} }
let encoding = get_patched_encoding(imp_cfg, builder); let encoding = get_patched_encoding(imp_cfg, builder);
let patched_f = if is_dir { let patched_f = if let Some(root_dir) = root_dir {
let f = std::path::PathBuf::from(filename); let f = std::path::PathBuf::from(filename);
let mut pb = std::path::PathBuf::from(&imp_cfg.patched); let mut pb = std::path::PathBuf::from(&imp_cfg.patched);
let rpath = utils::files::relative_path(root_dir, &f);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = f.file_name() { if let Some(fname) = f.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -1208,6 +1252,7 @@ pub fn import_script(
} else { } else {
imp_cfg.patched.clone() imp_cfg.patched.clone()
}; };
utils::files::make_sure_dir_exists(&patched_f)?;
if of.is_custom() { if of.is_custom() {
let enc = get_output_encoding(arg); let enc = get_output_encoding(arg);
script.custom_import_filename(&out_f, &patched_f, encoding, enc)?; script.custom_import_filename(&out_f, &patched_f, encoding, enc)?;
@@ -1324,7 +1369,7 @@ pub fn unpack_archive(
arg: &args::Arg, arg: &args::Arg,
config: &types::ExtraConfig, config: &types::ExtraConfig,
output: &Option<String>, output: &Option<String>,
is_dir: bool, root_dir: Option<&std::path::Path>,
) -> anyhow::Result<types::ScriptResult> { ) -> anyhow::Result<types::ScriptResult> {
eprintln!("Unpacking {}", filename); eprintln!("Unpacking {}", filename);
let script = parse_script(filename, arg, config)?.0; let script = parse_script(filename, arg, config)?.0;
@@ -1335,7 +1380,11 @@ pub fn unpack_archive(
Some(output) => { Some(output) => {
let mut pb = std::path::PathBuf::from(output); let mut pb = std::path::PathBuf::from(output);
let filename = std::path::PathBuf::from(filename); let filename = std::path::PathBuf::from(filename);
if is_dir { if let Some(root_dir) = root_dir {
let rpath = utils::files::relative_path(root_dir, &filename);
if let Some(parent) = rpath.parent() {
pb.push(parent);
}
if let Some(fname) = filename.file_name() { if let Some(fname) = filename.file_name() {
pb.push(fname); pb.push(fname);
} }
@@ -1584,8 +1633,13 @@ fn main() {
None => {} None => {}
} }
} }
let root_dir = if is_dir {
Some(std::path::Path::new(input))
} else {
None
};
for script in scripts.iter() { for script in scripts.iter() {
let re = export_script(&script, &arg, &cfg, output, is_dir); let re = export_script(&script, &arg, &cfg, output, root_dir);
match re { match re {
Ok(s) => { Ok(s) => {
COUNTER.inc(s); COUNTER.inc(s);
@@ -1630,13 +1684,18 @@ fn main() {
std::fs::create_dir_all(pb).unwrap(); std::fs::create_dir_all(pb).unwrap();
} }
} }
let root_dir = if is_dir {
Some(std::path::Path::new(&args.input))
} else {
None
};
for script in scripts.iter() { for script in scripts.iter() {
let re = import_script( let re = import_script(
&script, &script,
&arg, &arg,
&cfg, &cfg,
args, args,
is_dir, root_dir,
name_csv.as_ref(), name_csv.as_ref(),
repl.as_ref(), repl.as_ref(),
); );
@@ -1679,8 +1738,13 @@ fn main() {
None => {} None => {}
} }
} }
let root_dir = if is_dir {
Some(std::path::Path::new(input))
} else {
None
};
for script in scripts.iter() { for script in scripts.iter() {
let re = unpack_archive(&script, &arg, &cfg, output, is_dir); let re = unpack_archive(&script, &arg, &cfg, output, root_dir);
match re { match re {
Ok(s) => { Ok(s) => {
COUNTER.inc(s); COUNTER.inc(s);

View File

@@ -2,7 +2,43 @@ use crate::scripts::{ALL_EXTS, ARCHIVE_EXTS};
use std::fs; use std::fs;
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::Path; use std::path::{Path, PathBuf};
pub fn relative_path<P: AsRef<Path>, T: AsRef<Path>>(root: P, target: T) -> PathBuf {
let root = root
.as_ref()
.canonicalize()
.unwrap_or_else(|_| root.as_ref().to_path_buf());
let target = target
.as_ref()
.canonicalize()
.unwrap_or_else(|_| target.as_ref().to_path_buf());
let mut root_components: Vec<_> = root.components().collect();
let mut target_components: Vec<_> = target.components().collect();
// Remove common prefix
while !root_components.is_empty()
&& !target_components.is_empty()
&& root_components[0] == target_components[0]
{
root_components.remove(0);
target_components.remove(0);
}
// Add ".." for each remaining root component
let mut result = PathBuf::new();
for _ in root_components {
result.push("..");
}
// Add remaining target components
for component in target_components {
result.push(component);
}
result
}
pub fn find_files(path: &str, recursive: bool, no_ext_filter: bool) -> io::Result<Vec<String>> { pub fn find_files(path: &str, recursive: bool, no_ext_filter: bool) -> io::Result<Vec<String>> {
let mut result = Vec::new(); let mut result = Vec::new();