From 3b4f9b2e107134054a5a2090523ad66bacaea7c5 Mon Sep 17 00:00:00 2001 From: suzmii Date: Mon, 28 Sep 2026 10:20:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E7=B3=BB=E7=BB=9F=E6=80=A7=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1=E4=BF=AE=E5=A4=8D=20M3=EF=BC=9A=E6=8C=87=E7=BA=B9?= =?UTF-8?q?=E5=8F=8D=E5=88=A4=E6=96=AD=E3=80=81=E5=AE=88=E5=8D=AB=E6=AD=BB?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E3=80=81fail-open=20=E4=B8=8E=E5=8D=AB?= =?UTF-8?q?=E7=94=9F=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - P1-1:pluginSourceFingerprint 的判断取反(prepared 内容与交付态真正进入指纹);pluginTreeMatches 的「当前目标/feature 下不该存在却存在 → 重建」从死代码修活 - P1-7:package_layout 的 `sha256_file(x).ok() != ...` 改为 map_err 传播,两侧读失败不再被判为「相等」 - P3-2:copyNativePayloads 的 'plugins' 字面量改由声明 sourceDirectory 派生 - P3-5:payload 交付内容一致时跳过写入(命中缓存保持零写入、时间戳稳定) - P3-7:门禁提示里的脚本名改为 agc:bundled-resources:sync - P3-8:删除已无写入方的 resources/cocos-editor-bridge 占位目录 - P2-4:root 包装脚本补结尾 `--`,文档里的 prepare 命令可直接复制执行 - 验证:工具用例全绿、声明门禁通过 --- .../scripts/check-package-layout.mjs | 4 +-- .../scripts/prepare-bundled-resources.mjs | 33 ++++++++++++------- .../src-tauri/build_support/package_layout.rs | 18 ++++++++-- .../resources/cocos-editor-bridge/.gitignore | 1 - .../resources/cocos-editor-bridge/.gitkeep | 0 package.json | 4 +-- 6 files changed, 41 insertions(+), 19 deletions(-) delete mode 100644 apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitignore delete mode 100644 apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitkeep diff --git a/apps/ai-game-creator-shell/scripts/check-package-layout.mjs b/apps/ai-game-creator-shell/scripts/check-package-layout.mjs index 90dd0ce92..b90209878 100755 --- a/apps/ai-game-creator-shell/scripts/check-package-layout.mjs +++ b/apps/ai-game-creator-shell/scripts/check-package-layout.mjs @@ -453,7 +453,7 @@ function renderGenerated(declaration) { return `// @generated by apps/ai-game-creator-shell/scripts/check-package-layout.mjs // 来源:build_support/package-layout.json。不要手工编辑本文件。 // 修改随包资源布局请编辑声明文件,然后运行 -// npm run agc:package-layout:sync(在仓库根目录) +// npm run agc:bundled-resources:sync(在仓库根目录) // 门禁会校验两者一致(npm run agc:typecheck 链内含 check-package-layout.mjs)。 pub const DECLARATION_SCHEMA: &str = ${rustString(EXPECTED_SCHEMA)}; @@ -615,7 +615,7 @@ function main() { `随包资源声明与 Rust 常量不一致:`, ` 声明:${path.relative(process.cwd(), DECLARATION_PATH)}`, ` 生成:${path.relative(process.cwd(), GENERATED_PATH)}`, - '请运行:npm run agc:package-layout:sync', + '请运行:npm run agc:bundled-resources:sync', ].join('\n'), ); process.exit(1); diff --git a/apps/ai-game-creator-shell/scripts/prepare-bundled-resources.mjs b/apps/ai-game-creator-shell/scripts/prepare-bundled-resources.mjs index 9ec3828ac..674e668e4 100755 --- a/apps/ai-game-creator-shell/scripts/prepare-bundled-resources.mjs +++ b/apps/ai-game-creator-shell/scripts/prepare-bundled-resources.mjs @@ -660,8 +660,8 @@ function pluginSourceFingerprint(declaration, plugins, target, features) { for (const plugin of plugins) { for (const subdirectory of declaration.plugins.subdirectories) { if ( - subdirectoryAppliesToPlugin(subdirectory, plugin.name) || - subdirectoryEnabled(subdirectory, target, features) + !subdirectoryAppliesToPlugin(subdirectory, plugin.name) || + !subdirectoryEnabled(subdirectory, target, features) ) { continue; } @@ -747,10 +747,7 @@ function pluginTreeMatches( return false; } for (const subdirectory of declaration.plugins.subdirectories) { - if ( - !subdirectoryAppliesToPlugin(subdirectory, plugin.name) || - !subdirectoryEnabled(subdirectory, target, features) - ) { + if (!subdirectoryAppliesToPlugin(subdirectory, plugin.name)) { continue; } const stagedDirectory = path.join(pluginDestination, subdirectory.path); @@ -763,10 +760,7 @@ function pluginTreeMatches( } const sourceRoot = path.join(plugin.root, subdirectory.path); if (subdirectory.origin !== 'source') { - if ( - existsSync(sourceRoot) && - !existsSync(path.join(pluginDestination, subdirectory.path)) - ) { + if (existsSync(sourceRoot) && !existsSync(stagedDirectory)) { return false; } continue; @@ -1053,6 +1047,21 @@ function copyPreparedPayloads({ } } +/// 内容一致时不重写(保住时间戳与「命中缓存零写入」口径)。 +function copyFilePreservingModeIfChanged(source, destination) { + if (existsSync(destination)) { + const sourceInfo = statSync(source); + const destinationInfo = statSync(destination); + if ( + sourceInfo.size === destinationInfo.size && + Buffer.compare(readFileSync(source), readFileSync(destination)) === 0 + ) { + return; + } + } + copyFilePreservingMode(source, destination); +} + /// Cocos bridge 的 dll 既要进插件工作区(唯一真源),也要进随包目录。 function copyNativePayloads({ declaration, @@ -1100,7 +1109,7 @@ function copyNativePayloads({ } const destinationName = payload.destinationFileName ?? payload.sourceFileName; - copyFilePreservingMode( + copyFilePreservingModeIfChanged( source, path.join( repoRoot, @@ -1110,7 +1119,7 @@ function copyNativePayloads({ destinationName, ), ); - copyFilePreservingMode( + copyFilePreservingModeIfChanged( source, path.join( staging, diff --git a/apps/ai-game-creator-shell/src-tauri/build_support/package_layout.rs b/apps/ai-game-creator-shell/src-tauri/build_support/package_layout.rs index 8c8732039..f7de69dcd 100644 --- a/apps/ai-game-creator-shell/src-tauri/build_support/package_layout.rs +++ b/apps/ai-game-creator-shell/src-tauri/build_support/package_layout.rs @@ -280,7 +280,15 @@ pub fn validate_staged_plugins( if !staged_manifest.is_file() { return Err(format!("随包插件缺少清单:{}", staged_manifest.display())); } - if sha256_file(&source_manifest).ok() != sha256_file(&staged_manifest).ok() { + let source_manifest_digest = sha256_file(&source_manifest) + .map_err(|error| format!("读取插件清单失败 {}:{error}", source_manifest.display()))?; + let staged_manifest_digest = sha256_file(&staged_manifest).map_err(|error| { + format!( + "读取随包插件清单失败 {}:{error}", + staged_manifest.display() + ) + })?; + if source_manifest_digest != staged_manifest_digest { return Err(format!( "随包插件清单与源码不一致:{}", staged_manifest.display() @@ -319,7 +327,13 @@ pub fn validate_staged_plugins( if !staged_file.is_file() { return Err(format!("随包插件缺少文件:{}", staged_file.display())); } - if sha256_file(&source_file).ok() != sha256_file(&staged_file).ok() { + let source_digest = sha256_file(&source_file).map_err(|error| { + format!("读取插件文件失败 {}:{error}", source_file.display()) + })?; + let staged_digest = sha256_file(&staged_file).map_err(|error| { + format!("读取随包插件文件失败 {}:{error}", staged_file.display()) + })?; + if source_digest != staged_digest { return Err(format!( "随包插件文件与源码不一致:{}", staged_file.display() diff --git a/apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitignore b/apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitignore deleted file mode 100644 index 6a7461313..000000000 --- a/apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.dll diff --git a/apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitkeep b/apps/ai-game-creator-shell/src-tauri/resources/cocos-editor-bridge/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/package.json b/package.json index 2c852e22f..250192b8f 100644 --- a/package.json +++ b/package.json @@ -170,8 +170,8 @@ "agc:skill-pack:sync": "npm --prefix apps/ai-game-creator-shell run skill-pack:sync", "agc:bundled-resources:check": "npm --prefix apps/ai-game-creator-shell run bundled-resources:check", "agc:bundled-resources:sync": "npm --prefix apps/ai-game-creator-shell run bundled-resources:sync", - "agc:bundled-resources:prepare": "npm --prefix apps/ai-game-creator-shell run bundled-resources:prepare", - "agc:bundled-resources:test": "npm --prefix apps/ai-game-creator-shell run bundled-resources:test", + "agc:bundled-resources:prepare": "npm --prefix apps/ai-game-creator-shell run bundled-resources:prepare --", + "agc:bundled-resources:test": "npm --prefix apps/ai-game-creator-shell run bundled-resources:test --", "agc:plugins:test": "node --test plugins/agc-cocos-editor/src/entry.test.mjs plugins/agc-unity-editor/src/entry.test.mjs plugins/agc-godot-editor/src/entry.test.mjs", "agc:plugins:native-test": "cargo test --manifest-path plugins/agc-cocos-editor/native/cocos-editor-bridge/Cargo.toml && cargo test --locked --manifest-path plugins/agc-unity-editor/native/unity-editor-bridge/Cargo.toml && cargo test --locked --manifest-path plugins/agc-godot-editor/native/godot-editor-bridge/Cargo.toml", "agc:plugins:check": "npm run agc:plugins:test && npm run agc:plugins:native-test",