fix(release): 保留空目录到 ZIP 产物
移除 count_files 和 dir_has_included_files 两个预检函数,不再在打包时 过滤空目录。所有遍历到的子目录(包括空目录和仅含 .gitkeep 的目录) 现在都会写入 ZIP 条目,确保项目目录结构完整保留。 新增三个测试覆盖:空子目录、仅 .gitkeep 目录、emod-package 匹配的 空目录。
This commit is contained in:
@@ -214,10 +214,6 @@ fn add_directory_to_zip(
|
||||
)));
|
||||
}
|
||||
|
||||
if count_files(src_dir, project_dir, ignore)? == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let options = SimpleFileOptions::default();
|
||||
let mut buffer = Vec::new();
|
||||
|
||||
@@ -243,9 +239,7 @@ fn add_directory_to_zip(
|
||||
f.read_to_end(&mut buffer)?;
|
||||
zip.write_all(&buffer)?;
|
||||
buffer.clear();
|
||||
} else if !relative_path.as_os_str().is_empty()
|
||||
&& count_files(path, project_dir, ignore)? > 0
|
||||
{
|
||||
} else if !relative_path.as_os_str().is_empty() {
|
||||
zip.add_directory(&path_str, options)?;
|
||||
}
|
||||
}
|
||||
@@ -329,7 +323,7 @@ fn add_with_package(
|
||||
if !is_dir {
|
||||
continue;
|
||||
}
|
||||
// 当前目录未命中且无被包含的子孙时,无需写出目录条目。
|
||||
// 当前目录未命中,不写出目录条目;WalkDir 仍会继续遍历子孙。
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -343,9 +337,7 @@ fn add_with_package(
|
||||
.map_err(|e| file::io_error("读取打包文件", path, e))?;
|
||||
zip.write_all(&buffer)?;
|
||||
buffer.clear();
|
||||
} else if !relative_path.as_os_str().is_empty()
|
||||
&& dir_has_included_files(path, project_dir, package, ignore)?
|
||||
{
|
||||
} else if !relative_path.as_os_str().is_empty() {
|
||||
zip.add_directory(&path_str, options)?;
|
||||
}
|
||||
}
|
||||
@@ -353,57 +345,6 @@ fn add_with_package(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dir_has_included_files(
|
||||
dir: &Path,
|
||||
project_dir: &Path,
|
||||
package: &EmodPackage,
|
||||
ignore: &EmodIgnore,
|
||||
) -> Result<bool> {
|
||||
for entry in walkdir::WalkDir::new(dir) {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if !path.is_file() {
|
||||
continue;
|
||||
}
|
||||
if path.display().to_string().ends_with(".gitkeep") {
|
||||
continue;
|
||||
}
|
||||
let relative_path = path
|
||||
.strip_prefix(project_dir)
|
||||
.map_err(|e| crate::error::CliError::InvalidData(e.to_string()))?;
|
||||
if ignore.is_ignored(relative_path, false) {
|
||||
continue;
|
||||
}
|
||||
if !package.matches(relative_path, false) {
|
||||
continue;
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn count_files(dir: &Path, project_dir: &Path, ignore: &EmodIgnore) -> Result<usize> {
|
||||
let mut count = 0;
|
||||
for entry in walkdir::WalkDir::new(dir) {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if !path.is_file() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let relative_path = path
|
||||
.strip_prefix(project_dir)
|
||||
.map_err(|e| crate::error::CliError::InvalidData(e.to_string()))?;
|
||||
|
||||
if !path.display().to_string().ends_with(".gitkeep")
|
||||
&& !ignore.is_ignored(relative_path, false)
|
||||
{
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
struct EmodIgnore {
|
||||
rules: Vec<IgnoreRule>,
|
||||
}
|
||||
@@ -803,6 +744,68 @@ mod tests {
|
||||
fs::remove_dir_all(project_dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn package_project_keeps_empty_subdirectory() {
|
||||
let project_dir = temp_project_dir();
|
||||
let release_info = release_info();
|
||||
|
||||
fs::create_dir_all(project_dir.join("behavior_pack_abcdefgh/empty_dir")).unwrap();
|
||||
fs::create_dir_all(project_dir.join("resource_pack_ijklmnop")).unwrap();
|
||||
|
||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||
let zip_path =
|
||||
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||
let entries = zip_entries(&zip_path);
|
||||
|
||||
assert!(entries.contains(&"behavior_pack_abcdefgh/empty_dir/".to_string()));
|
||||
|
||||
fs::remove_dir_all(project_dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn package_project_keeps_dir_with_only_gitkeep() {
|
||||
let project_dir = temp_project_dir();
|
||||
let release_info = release_info();
|
||||
|
||||
write_file(
|
||||
&project_dir.join("behavior_pack_abcdefgh/only_gitkeep/.gitkeep"),
|
||||
"",
|
||||
);
|
||||
fs::create_dir_all(project_dir.join("resource_pack_ijklmnop")).unwrap();
|
||||
|
||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||
let zip_path =
|
||||
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||
let entries = zip_entries(&zip_path);
|
||||
|
||||
assert!(entries.contains(&"behavior_pack_abcdefgh/only_gitkeep/".to_string()));
|
||||
assert!(!entries.contains(&"behavior_pack_abcdefgh/only_gitkeep/.gitkeep".to_string()));
|
||||
|
||||
fs::remove_dir_all(project_dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emod_package_keeps_matched_empty_subdirectory() {
|
||||
let project_dir = temp_project_dir();
|
||||
let release_info = release_info();
|
||||
|
||||
write_file(
|
||||
&project_dir.join(".emod-package"),
|
||||
"behavior_pack_abcdefgh/empty_dir/\n",
|
||||
);
|
||||
fs::create_dir_all(project_dir.join("behavior_pack_abcdefgh/empty_dir")).unwrap();
|
||||
fs::create_dir_all(project_dir.join("resource_pack_ijklmnop")).unwrap();
|
||||
|
||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||
let zip_path =
|
||||
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||
let entries = zip_entries(&zip_path);
|
||||
|
||||
assert!(entries.contains(&"behavior_pack_abcdefgh/empty_dir/".to_string()));
|
||||
|
||||
fs::remove_dir_all(project_dir).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn package_project_includes_world_pack_json_in_default_mode() {
|
||||
let project_dir = temp_project_dir();
|
||||
|
||||
Reference in New Issue
Block a user