Initial clean project import
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = path.join(__dirname, '..');
|
||||
const buildDir = path.join(root, 'dist-release-final');
|
||||
const bundleDir = path.join(buildDir, 'resource-bundles');
|
||||
const releaseDir = path.join(buildDir, 'release-assets');
|
||||
const legacyPrefixes = ['尚创IP智能体V8'];
|
||||
const currentPrefix = 'SC-IP-Agent';
|
||||
const manifestPath = path.join(buildDir, 'resource-manifest.json');
|
||||
const isOemFullOfflineBuild = process.env.OEM_BATCH_BUILD === '1';
|
||||
|
||||
const readJson = (file, fallback) => {
|
||||
if (!fs.existsSync(file)) return fallback;
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
};
|
||||
|
||||
fs.mkdirSync(releaseDir, { recursive: true });
|
||||
|
||||
const waitForFile = (filePath, maxWait = 10000) => {
|
||||
const startTime = Date.now();
|
||||
while (Date.now() - startTime < maxWait) {
|
||||
try {
|
||||
const fd = fs.openSync(filePath, 'r+');
|
||||
fs.closeSync(fd);
|
||||
return true;
|
||||
} catch {
|
||||
if (Date.now() - startTime < maxWait) {
|
||||
const sleepMs = 200;
|
||||
const sleepUntil = Date.now() + sleepMs;
|
||||
while (Date.now() < sleepUntil) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.warn(`[assemble] Warning: ${filePath} still locked after ${maxWait}ms, attempting copy anyway...`);
|
||||
return false;
|
||||
};
|
||||
|
||||
const copyIfNeeded = (sourcePath, destPath) => {
|
||||
if (fs.existsSync(destPath)) {
|
||||
const srcBuffer = fs.readFileSync(sourcePath);
|
||||
const destBuffer = fs.readFileSync(destPath);
|
||||
if (srcBuffer.length === destBuffer.length && srcBuffer.equals(destBuffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
waitForFile(sourcePath);
|
||||
fs.copyFileSync(sourcePath, destPath);
|
||||
return true;
|
||||
};
|
||||
|
||||
const compatAliasesFor = (name) => {
|
||||
for (const legacyPrefix of legacyPrefixes) {
|
||||
const prefix = `${legacyPrefix}-`;
|
||||
if (name.startsWith(prefix)) {
|
||||
return [`${currentPrefix}-${name.slice(prefix.length)}`];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const releaseExtensions = ['.exe', '.blockmap', '.yml', '.7z'];
|
||||
const hasRootInstaller = fs.readdirSync(buildDir)
|
||||
.some(name => {
|
||||
const full = path.join(buildDir, name);
|
||||
return fs.statSync(full).isFile()
|
||||
&& /setup.*\.exe$/i.test(name)
|
||||
&& !name.startsWith('__uninstaller')
|
||||
&& fs.statSync(full).size > 1024 * 1024;
|
||||
});
|
||||
const hasNsisWebOutput = !hasRootInstaller && fs.existsSync(path.join(buildDir, 'nsis-web'));
|
||||
const copyReleaseFiles = (dir) => {
|
||||
if (!fs.existsSync(dir)) return;
|
||||
if (path.resolve(dir) === path.resolve(releaseDir)) return;
|
||||
for (const name of fs.readdirSync(dir)) {
|
||||
const full = path.join(dir, name);
|
||||
const stat = fs.statSync(full);
|
||||
if (stat.isDirectory()) {
|
||||
if (path.resolve(dir) === path.resolve(buildDir) && name === 'nsis-web') {
|
||||
copyReleaseFiles(full);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!stat.isFile()) continue;
|
||||
if (!releaseExtensions.some(ext => name.endsWith(ext))) continue;
|
||||
if (hasNsisWebOutput && path.resolve(dir) === path.resolve(buildDir)) continue;
|
||||
const dest = path.join(releaseDir, name);
|
||||
try {
|
||||
copyIfNeeded(full, dest);
|
||||
} catch (err) {
|
||||
if (err.code === 'EBUSY') {
|
||||
console.warn(`[assemble] ${name} is locked, skipping (likely being scanned by antivirus)`);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
copyReleaseFiles(buildDir);
|
||||
|
||||
for (const name of fs.readdirSync(releaseDir)) {
|
||||
const full = path.join(releaseDir, name);
|
||||
if (!fs.statSync(full).isFile()) continue;
|
||||
for (const alias of compatAliasesFor(name)) {
|
||||
const aliasPath = path.join(releaseDir, alias);
|
||||
if (aliasPath === full || fs.existsSync(aliasPath)) continue;
|
||||
fs.copyFileSync(full, aliasPath);
|
||||
console.log(`[assemble] Created compatibility alias: ${alias}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isOemFullOfflineBuild && fs.existsSync(manifestPath)) {
|
||||
fs.copyFileSync(manifestPath, path.join(releaseDir, 'resource-manifest.json'));
|
||||
}
|
||||
|
||||
if (!isOemFullOfflineBuild && fs.existsSync(bundleDir)) {
|
||||
const manifest = readJson(manifestPath, { bundles: {} });
|
||||
const currentBundleArchives = new Set(
|
||||
Object.values(manifest.bundles || {})
|
||||
.map(bundle => bundle && bundle.archive)
|
||||
.filter(Boolean)
|
||||
);
|
||||
|
||||
for (const name of fs.readdirSync(bundleDir)) {
|
||||
const full = path.join(bundleDir, name);
|
||||
const shouldCopy = name.endsWith('.json') || currentBundleArchives.has(name);
|
||||
if (fs.statSync(full).isFile() && shouldCopy) {
|
||||
fs.copyFileSync(full, path.join(releaseDir, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isOemFullOfflineBuild) {
|
||||
for (const name of fs.readdirSync(releaseDir)) {
|
||||
if (name.endsWith('.zip') || name === 'resource-manifest.json' || name === 'changed-bundles.json') {
|
||||
fs.rmSync(path.join(releaseDir, name), { force: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[release-assemble] output:', releaseDir);
|
||||
Reference in New Issue
Block a user