feat(release): 支持自定义打包产物目录
release 现在会在设置 EMOD_ARTIFACTS_DIR 时将 ZIP 输出到按项目名隔离的 artifacts 子目录,未设置时保持写入项目目录。 新增单元测试覆盖默认输出和环境变量输出两条路径,避免发布产物污染源项目或路径回退失效。
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
|
env,
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@@ -14,6 +15,8 @@ use crate::error::{CliError, Result};
|
|||||||
use crate::utils::file;
|
use crate::utils::file;
|
||||||
use crate::{entity, entity::project::ReleaseInfo};
|
use crate::{entity, entity::project::ReleaseInfo};
|
||||||
|
|
||||||
|
const ARTIFACTS_DIR_ENV: &str = "EMOD_ARTIFACTS_DIR";
|
||||||
|
|
||||||
pub fn execute(args: &ReleaseArgs) {
|
pub fn execute(args: &ReleaseArgs) {
|
||||||
if let Err(e) = run_release(args) {
|
if let Err(e) = run_release(args) {
|
||||||
eprintln!("❌ 组件打包失败: {}", e);
|
eprintln!("❌ 组件打包失败: {}", e);
|
||||||
@@ -34,11 +37,7 @@ fn run_release(args: &ReleaseArgs) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release(
|
fn release(args: &ReleaseArgs, project_dir: &PathBuf, release_info: &ReleaseInfo) -> Result<()> {
|
||||||
args: &ReleaseArgs,
|
|
||||||
project_dir: &PathBuf,
|
|
||||||
release_info: &ReleaseInfo,
|
|
||||||
) -> Result<()> {
|
|
||||||
let new_version = calculate_version(&args.ver, args.pin, &release_info.behavior_version)?;
|
let new_version = calculate_version(&args.ver, args.pin, &release_info.behavior_version)?;
|
||||||
let version_value = Value::Array(new_version.iter().map(|v| Value::from(*v)).collect());
|
let version_value = Value::Array(new_version.iter().map(|v| Value::from(*v)).collect());
|
||||||
|
|
||||||
@@ -50,16 +49,12 @@ fn release(
|
|||||||
|
|
||||||
let version_str = format!("{}.{}.{}", new_version[0], new_version[1], new_version[2]);
|
let version_str = format!("{}.{}.{}", new_version[0], new_version[1], new_version[2]);
|
||||||
let output_path = package_project(&project_dir, &pack_dirs, &version_str)?;
|
let output_path = package_project(&project_dir, &pack_dirs, &version_str)?;
|
||||||
|
let display_path = output_path.display().to_string().replace("\\", "/");
|
||||||
println!("📦 打包完成: {}", output_path.replace("\\", "/"));
|
println!("📦 打包完成: {}", display_path);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_version(
|
fn calculate_version(version: &Option<String>, pin: bool, current: &[u32]) -> Result<Vec<u32>> {
|
||||||
version: &Option<String>,
|
|
||||||
pin: bool,
|
|
||||||
current: &[u32],
|
|
||||||
) -> Result<Vec<u32>> {
|
|
||||||
if let Some(ver_str) = version {
|
if let Some(ver_str) = version {
|
||||||
ver_str
|
ver_str
|
||||||
.split(".")
|
.split(".")
|
||||||
@@ -116,11 +111,7 @@ fn ensure_pack_ready(label: &str, pack_dir: &Path, identifier: &str) -> Result<(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_versions(
|
fn update_versions(project_dir: &PathBuf, version: &Value, pack_dirs: &PackDirs) -> Result<()> {
|
||||||
project_dir: &PathBuf,
|
|
||||||
version: &Value,
|
|
||||||
pack_dirs: &PackDirs,
|
|
||||||
) -> Result<()> {
|
|
||||||
update_pack_json(&project_dir, &version)?;
|
update_pack_json(&project_dir, &version)?;
|
||||||
update_manifest_json(&version, pack_dirs)?;
|
update_manifest_json(&version, pack_dirs)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -155,11 +146,7 @@ fn update_manifest_json(version: &Value, pack_dirs: &PackDirs) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn package_project(
|
fn package_project(project_dir: &PathBuf, pack_dirs: &PackDirs, version: &str) -> Result<PathBuf> {
|
||||||
project_dir: &PathBuf,
|
|
||||||
pack_dirs: &PackDirs,
|
|
||||||
version: &str,
|
|
||||||
) -> Result<String> {
|
|
||||||
let canonical_project_dir = project_dir
|
let canonical_project_dir = project_dir
|
||||||
.canonicalize()
|
.canonicalize()
|
||||||
.map_err(|e| file::io_error("解析项目目录", project_dir, e))?;
|
.map_err(|e| file::io_error("解析项目目录", project_dir, e))?;
|
||||||
@@ -178,15 +165,25 @@ fn package_project(
|
|||||||
canonical_project_dir.display()
|
canonical_project_dir.display()
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let output_path = format!(
|
|
||||||
"{}/{}_release_{}.zip",
|
let output_dir =
|
||||||
project_dir.display(),
|
match env::var_os(ARTIFACTS_DIR_ENV).filter(|value| !value.as_os_str().is_empty()) {
|
||||||
project_name,
|
Some(artifacts_dir) => {
|
||||||
version
|
let output_dir = PathBuf::from(artifacts_dir).join(project_name);
|
||||||
|
fs::create_dir_all(&output_dir)
|
||||||
|
.map_err(|e| file::io_error("创建打包输出目录", &output_dir, e))?;
|
||||||
|
println!(
|
||||||
|
"📦 使用 {} 指定的打包输出目录: {}",
|
||||||
|
ARTIFACTS_DIR_ENV,
|
||||||
|
output_dir.display().to_string().replace("\\", "/")
|
||||||
);
|
);
|
||||||
let output_pathbuf = PathBuf::from(&output_path);
|
output_dir
|
||||||
|
}
|
||||||
|
None => project_dir.clone(),
|
||||||
|
};
|
||||||
|
let output_path = output_dir.join(format!("{project_name}_release_{version}.zip"));
|
||||||
let file = fs::File::create(&output_path)
|
let file = fs::File::create(&output_path)
|
||||||
.map_err(|e| file::io_error("创建打包文件", &output_pathbuf, e))?;
|
.map_err(|e| file::io_error("创建打包文件", &output_path, e))?;
|
||||||
let mut zip = zip::ZipWriter::new(file);
|
let mut zip = zip::ZipWriter::new(file);
|
||||||
|
|
||||||
let ignore = EmodIgnore::load(project_dir)?;
|
let ignore = EmodIgnore::load(project_dir)?;
|
||||||
@@ -276,8 +273,7 @@ fn add_world_pack_files(
|
|||||||
}
|
}
|
||||||
|
|
||||||
zip.start_file(name, options)?;
|
zip.start_file(name, options)?;
|
||||||
let mut f =
|
let mut f = File::open(&path).map_err(|e| file::io_error("打开打包文件", &path, e))?;
|
||||||
File::open(&path).map_err(|e| file::io_error("打开打包文件", &path, e))?;
|
|
||||||
f.read_to_end(&mut buffer)
|
f.read_to_end(&mut buffer)
|
||||||
.map_err(|e| file::io_error("读取打包文件", &path, e))?;
|
.map_err(|e| file::io_error("读取打包文件", &path, e))?;
|
||||||
zip.write_all(&buffer)?;
|
zip.write_all(&buffer)?;
|
||||||
@@ -342,8 +338,7 @@ fn add_with_package(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
zip.start_file(&path_str, options)?;
|
zip.start_file(&path_str, options)?;
|
||||||
let mut f =
|
let mut f = File::open(path).map_err(|e| file::io_error("打开打包文件", path, e))?;
|
||||||
File::open(path).map_err(|e| file::io_error("打开打包文件", path, e))?;
|
|
||||||
f.read_to_end(&mut buffer)
|
f.read_to_end(&mut buffer)
|
||||||
.map_err(|e| file::io_error("读取打包文件", path, e))?;
|
.map_err(|e| file::io_error("读取打包文件", path, e))?;
|
||||||
zip.write_all(&buffer)?;
|
zip.write_all(&buffer)?;
|
||||||
@@ -554,10 +549,7 @@ fn normalize_path(path: &Path) -> String {
|
|||||||
/// review tooling rejects as "中文或特殊符号". Always normalize to '/'.
|
/// review tooling rejects as "中文或特殊符号". Always normalize to '/'.
|
||||||
fn zip_entry_path(relative_path: &Path) -> Result<String> {
|
fn zip_entry_path(relative_path: &Path) -> Result<String> {
|
||||||
let s = relative_path.to_str().ok_or_else(|| {
|
let s = relative_path.to_str().ok_or_else(|| {
|
||||||
crate::error::CliError::InvalidData(format!(
|
crate::error::CliError::InvalidData(format!("{:?} 不是有效的 UTF-8 路径", relative_path))
|
||||||
"{:?} 不是有效的 UTF-8 路径",
|
|
||||||
relative_path
|
|
||||||
))
|
|
||||||
})?;
|
})?;
|
||||||
Ok(s.replace('\\', "/"))
|
Ok(s.replace('\\', "/"))
|
||||||
}
|
}
|
||||||
@@ -614,9 +606,12 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
|
sync::Mutex,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ARTIFACTS_ENV_LOCK: Mutex<()> = Mutex::new(());
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn preflight_pack_dirs_reports_missing_behavior_pack() {
|
fn preflight_pack_dirs_reports_missing_behavior_pack() {
|
||||||
let project_dir = temp_project_dir();
|
let project_dir = temp_project_dir();
|
||||||
@@ -675,6 +670,66 @@ mod tests {
|
|||||||
assert_eq!(v, vec![1, 2, 3]);
|
assert_eq!(v, vec![1, 2, 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn package_writes_to_project_dir_when_env_unset() {
|
||||||
|
let project_dir = temp_project_dir();
|
||||||
|
let release_info = release_info();
|
||||||
|
|
||||||
|
write_file(
|
||||||
|
&project_dir.join("behavior_pack_abcdefgh/scripts/main.py"),
|
||||||
|
"main",
|
||||||
|
);
|
||||||
|
write_file(
|
||||||
|
&project_dir.join("resource_pack_ijklmnop/textures/icon.png"),
|
||||||
|
"icon",
|
||||||
|
);
|
||||||
|
|
||||||
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.2.3").unwrap();
|
||||||
|
let project_name = project_dir.file_name().unwrap().to_string_lossy();
|
||||||
|
let expected_path = project_dir.join(format!("{project_name}_release_1.2.3.zip"));
|
||||||
|
|
||||||
|
assert_eq!(zip_path, expected_path);
|
||||||
|
assert!(zip_path.is_file());
|
||||||
|
|
||||||
|
fs::remove_dir_all(project_dir).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn package_writes_to_artifacts_subdir_when_env_set() {
|
||||||
|
let project_dir = temp_project_dir();
|
||||||
|
let artifacts_dir = temp_project_dir();
|
||||||
|
let release_info = release_info();
|
||||||
|
|
||||||
|
write_file(
|
||||||
|
&project_dir.join("behavior_pack_abcdefgh/scripts/main.py"),
|
||||||
|
"main",
|
||||||
|
);
|
||||||
|
write_file(
|
||||||
|
&project_dir.join("resource_pack_ijklmnop/textures/icon.png"),
|
||||||
|
"icon",
|
||||||
|
);
|
||||||
|
|
||||||
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env(&project_dir, &pack_dirs, "1.0.0", &artifacts_dir)
|
||||||
|
.unwrap();
|
||||||
|
let project_name = project_dir.file_name().unwrap().to_string_lossy();
|
||||||
|
let expected_path = artifacts_dir
|
||||||
|
.join(project_name.as_ref())
|
||||||
|
.join(format!("{project_name}_release_1.0.0.zip"));
|
||||||
|
let project_dir_zip = project_dir.join(format!("{project_name}_release_1.0.0.zip"));
|
||||||
|
|
||||||
|
assert_eq!(zip_path, expected_path);
|
||||||
|
assert!(zip_path.is_file());
|
||||||
|
assert!(expected_path.parent().unwrap().is_dir());
|
||||||
|
assert!(!project_dir_zip.exists());
|
||||||
|
|
||||||
|
fs::remove_dir_all(project_dir).unwrap();
|
||||||
|
fs::remove_dir_all(artifacts_dir).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn package_project_skips_files_listed_in_emod_ignore() {
|
fn package_project_skips_files_listed_in_emod_ignore() {
|
||||||
let project_dir = temp_project_dir();
|
let project_dir = temp_project_dir();
|
||||||
@@ -702,7 +757,8 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
assert!(entries.contains(&"behavior_pack_abcdefgh/scripts/main.py".to_string()));
|
assert!(entries.contains(&"behavior_pack_abcdefgh/scripts/main.py".to_string()));
|
||||||
@@ -736,7 +792,8 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
assert!(entries.contains(&"behavior_pack_abcdefgh/live/main.py".to_string()));
|
assert!(entries.contains(&"behavior_pack_abcdefgh/live/main.py".to_string()));
|
||||||
@@ -763,7 +820,8 @@ mod tests {
|
|||||||
write_file(&project_dir.join("world_resource_packs.json"), "[]");
|
write_file(&project_dir.join("world_resource_packs.json"), "[]");
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
assert!(entries.contains(&"world_behavior_packs.json".to_string()));
|
assert!(entries.contains(&"world_behavior_packs.json".to_string()));
|
||||||
@@ -796,7 +854,8 @@ mod tests {
|
|||||||
write_file(&project_dir.join("misc/notes.md"), "notes");
|
write_file(&project_dir.join("misc/notes.md"), "notes");
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
assert!(entries.contains(&"behavior_pack_abcdefgh/scripts/main.py".to_string()));
|
assert!(entries.contains(&"behavior_pack_abcdefgh/scripts/main.py".to_string()));
|
||||||
@@ -831,7 +890,8 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
assert!(entries.contains(&"behavior_pack_abcdefgh/scripts/main.py".to_string()));
|
assert!(entries.contains(&"behavior_pack_abcdefgh/scripts/main.py".to_string()));
|
||||||
@@ -846,7 +906,10 @@ mod tests {
|
|||||||
let release_info = release_info();
|
let release_info = release_info();
|
||||||
|
|
||||||
write_file(&project_dir.join(".emod-package"), "**/*.json\n");
|
write_file(&project_dir.join(".emod-package"), "**/*.json\n");
|
||||||
write_file(&project_dir.join("behavior_pack_abcdefgh/manifest.json"), "{}");
|
write_file(
|
||||||
|
&project_dir.join("behavior_pack_abcdefgh/manifest.json"),
|
||||||
|
"{}",
|
||||||
|
);
|
||||||
write_file(
|
write_file(
|
||||||
&project_dir.join("behavior_pack_abcdefgh/scripts/main.py"),
|
&project_dir.join("behavior_pack_abcdefgh/scripts/main.py"),
|
||||||
"main",
|
"main",
|
||||||
@@ -854,7 +917,8 @@ mod tests {
|
|||||||
write_file(&project_dir.join("world_behavior_packs.json"), "[]");
|
write_file(&project_dir.join("world_behavior_packs.json"), "[]");
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
assert!(entries.contains(&"behavior_pack_abcdefgh/manifest.json".to_string()));
|
assert!(entries.contains(&"behavior_pack_abcdefgh/manifest.json".to_string()));
|
||||||
@@ -885,7 +949,8 @@ mod tests {
|
|||||||
write_file(&project_dir.join("world_resource_packs.json"), "[]");
|
write_file(&project_dir.join("world_resource_packs.json"), "[]");
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
for entry in &entries {
|
for entry in &entries {
|
||||||
@@ -904,7 +969,10 @@ mod tests {
|
|||||||
let project_dir = temp_project_dir();
|
let project_dir = temp_project_dir();
|
||||||
let release_info = release_info();
|
let release_info = release_info();
|
||||||
|
|
||||||
write_file(&project_dir.join(".emod-package"), "behavior_pack_abcdefgh/\n");
|
write_file(
|
||||||
|
&project_dir.join(".emod-package"),
|
||||||
|
"behavior_pack_abcdefgh/\n",
|
||||||
|
);
|
||||||
write_file(
|
write_file(
|
||||||
&project_dir.join("behavior_pack_abcdefgh/BoxData/data.json"),
|
&project_dir.join("behavior_pack_abcdefgh/BoxData/data.json"),
|
||||||
"{}",
|
"{}",
|
||||||
@@ -915,7 +983,8 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
let pack_dirs = pack_dirs(&project_dir, &release_info);
|
||||||
let zip_path = package_project(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
let zip_path =
|
||||||
|
package_project_with_artifacts_env_unset(&project_dir, &pack_dirs, "1.0.0").unwrap();
|
||||||
let entries = zip_entries(&zip_path);
|
let entries = zip_entries(&zip_path);
|
||||||
|
|
||||||
for entry in &entries {
|
for entry in &entries {
|
||||||
@@ -964,7 +1033,48 @@ mod tests {
|
|||||||
fs::write(path, content).unwrap();
|
fs::write(path, content).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zip_entries(path: &str) -> Vec<String> {
|
fn package_project_with_artifacts_env_unset(
|
||||||
|
project_dir: &PathBuf,
|
||||||
|
pack_dirs: &PackDirs,
|
||||||
|
version: &str,
|
||||||
|
) -> Result<PathBuf> {
|
||||||
|
let _guard = ARTIFACTS_ENV_LOCK.lock().unwrap();
|
||||||
|
remove_artifacts_dir_env();
|
||||||
|
let result = package_project(project_dir, pack_dirs, version);
|
||||||
|
remove_artifacts_dir_env();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn package_project_with_artifacts_env(
|
||||||
|
project_dir: &PathBuf,
|
||||||
|
pack_dirs: &PackDirs,
|
||||||
|
version: &str,
|
||||||
|
artifacts_dir: &Path,
|
||||||
|
) -> Result<PathBuf> {
|
||||||
|
let _guard = ARTIFACTS_ENV_LOCK.lock().unwrap();
|
||||||
|
set_artifacts_dir_env(artifacts_dir);
|
||||||
|
let result = package_project(project_dir, pack_dirs, version);
|
||||||
|
remove_artifacts_dir_env();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_artifacts_dir_env(path: &Path) {
|
||||||
|
// SAFETY: tests serialize every EMOD_ARTIFACTS_DIR mutation and every
|
||||||
|
// package_project call through ARTIFACTS_ENV_LOCK.
|
||||||
|
unsafe {
|
||||||
|
env::set_var(ARTIFACTS_DIR_ENV, path.as_os_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_artifacts_dir_env() {
|
||||||
|
// SAFETY: tests serialize every EMOD_ARTIFACTS_DIR mutation and every
|
||||||
|
// package_project call through ARTIFACTS_ENV_LOCK.
|
||||||
|
unsafe {
|
||||||
|
env::remove_var(ARTIFACTS_DIR_ENV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zip_entries(path: &Path) -> Vec<String> {
|
||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
let mut archive = zip::ZipArchive::new(file).unwrap();
|
let mut archive = zip::ZipArchive::new(file).unwrap();
|
||||||
(0..archive.len())
|
(0..archive.len())
|
||||||
|
|||||||
Reference in New Issue
Block a user