feat(游戏共创): 新增工程源包确定性打包器(M2b 客户端半,暂不接上传)
- 新模块 `src-tauri/src/project_bundle.rs`:`build_project_bundle(root, scope)` 产出 `(bytes, sha256, file_count, entry_paths)`,口径见 `docs/【技术方案】游戏共创与作品Fork-…` §3.5.2。 - 确定性:条目按路径排序、固定时间戳(ZIP 下限 1980-01-01)、固定权限位 0o644、固定 deflate, 只写文件条目不写目录条目;同内容必然得到同一 sha256(有测试钉住,含「改一字节即变」)。 - 路径安全:条目名一律项目根相对并过解压侧同一道门禁 `template_library::safe_archive_relative_path`; 符号链接 / Windows 重解析点、非普通条目一律失败关闭。ZIP 根 == 项目根(与模板包同一合同)。 - 排除规则:依赖与 VCS 任意层级(`node_modules`/`.git`/`.svn`)、项目根首层构建产物与 IDE (`dist`/`build`/`library`/`temp`/`local`/`.idea`/`.vscode`/`.godot`)、任意层级凭据 (`.env`/`.env.*`/`*.pem`/`*.key`/`*.p12`/`*.pfx`/`.npmrc`/`.netrc`)、AGC 自有目录 (`.agent`/`exports`/`memory`,理由逐条写在模块注释里)。 - 带上限常量:条目 ≤ 4096、单文件 ≤ 256 MiB、展开总量 ≤ 512 MiB;超限失败关闭并点名违规条目, 不静默截断(测试用小上限跑同一段逻辑,不另写一条检查路径)。 - 复用而非另起一套:`safe_archive_relative_path`(解压侧)、`project::relative_project_path`、 `image_inspect::metadata_is_windows_reparse_point`、`export.rs` 的排序 + 逐文件写 ZIP 写法; 摘要实现抽出 `project_bundle::sha256_hex`,`game_fork` 的取件校验改为复用它(少一份副本)。 - 打包范围:`WholeProject`(默认,M2b 用)与 `GameDirectory`(只收集 `game/`,条目命名不变)。 - 未接上传:上行路由族未定,模块整体带 `#![allow(dead_code)]` 并在注释里写明接线时删除。 - 测试 14 条:每类排除规则、确定性(两次/乱序/改字节)、条目路径不变量 + 解压器往返、 两个打包范围、空包与三类超限失败关闭、合同常量锚点;符号链接用例按平台 `#[cfg(unix)]`。
This commit is contained in:
@@ -36,19 +36,13 @@ pub(crate) fn verify_fork_source_bytes(
|
||||
bytes.len()
|
||||
));
|
||||
}
|
||||
let actual = sha256_hex(bytes);
|
||||
let actual = crate::project_bundle::sha256_hex(bytes);
|
||||
if actual != expected_sha256.trim().to_ascii_lowercase() {
|
||||
return Err("改编来源发行包完整性校验失败,已放弃落盘".to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sha256_hex(bytes: &[u8]) -> String {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(bytes);
|
||||
format!("{:x}", hasher.finalize())
|
||||
}
|
||||
|
||||
/// 参考副本相对项目的路径:`reference/<gameId>/`。
|
||||
///
|
||||
/// 作品 ID 来自平台响应,只接受路径安全取值;拼接复用归档条目门禁(拒绝 `..`、盘符与
|
||||
@@ -164,6 +158,7 @@ pub(crate) fn create_project_from_platform_fork_at(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::project_bundle::sha256_hex;
|
||||
use zip::write::SimpleFileOptions;
|
||||
|
||||
fn test_root(label: &str) -> PathBuf {
|
||||
|
||||
@@ -120,6 +120,7 @@ mod process_identity;
|
||||
mod process_session;
|
||||
mod process_session_bridge;
|
||||
mod project;
|
||||
mod project_bundle;
|
||||
mod project_snapshot;
|
||||
mod repository_context;
|
||||
mod resource_inspect;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user