mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-03 10:00:22 +08:00
fix(electron): properly dereference symlinks by copying actual content (#610)
cpSync with dereference:true does NOT convert symlinks to files. This implements a custom copyDereferenced function that: - Detects symlinks using lstatSync - Follows them using statSync - Copies actual file/directory content instead of symlink Fixes macOS arm64 codesign failure with electron-builder 26.4.0 which now does ad-hoc signing and runs codesign --verify.
This commit is contained in:
@@ -3,9 +3,49 @@
|
|||||||
* Copies node_modules to the standalone directory in the packaged app
|
* Copies node_modules to the standalone directory in the packaged app
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { cpSync, existsSync } = require("fs")
|
const {
|
||||||
|
copyFileSync,
|
||||||
|
existsSync,
|
||||||
|
lstatSync,
|
||||||
|
mkdirSync,
|
||||||
|
readdirSync,
|
||||||
|
statSync,
|
||||||
|
} = require("fs")
|
||||||
const path = require("path")
|
const path = require("path")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy directory recursively, converting symlinks to regular files/directories.
|
||||||
|
* This is needed because cpSync with dereference:true does NOT convert symlinks.
|
||||||
|
* macOS codesign fails if bundle contains symlinks pointing outside the bundle.
|
||||||
|
*/
|
||||||
|
function copyDereferenced(src, dst) {
|
||||||
|
const lstat = lstatSync(src)
|
||||||
|
|
||||||
|
if (lstat.isSymbolicLink()) {
|
||||||
|
// Follow symlink and check what it points to
|
||||||
|
const stat = statSync(src)
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
// Symlink to directory: recursively copy the directory contents
|
||||||
|
mkdirSync(dst, { recursive: true })
|
||||||
|
for (const entry of readdirSync(src)) {
|
||||||
|
copyDereferenced(path.join(src, entry), path.join(dst, entry))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Symlink to file: copy the actual file content
|
||||||
|
mkdirSync(path.join(dst, ".."), { recursive: true })
|
||||||
|
copyFileSync(src, dst)
|
||||||
|
}
|
||||||
|
} else if (lstat.isDirectory()) {
|
||||||
|
mkdirSync(dst, { recursive: true })
|
||||||
|
for (const entry of readdirSync(src)) {
|
||||||
|
copyDereferenced(path.join(src, entry), path.join(dst, entry))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mkdirSync(path.join(dst, ".."), { recursive: true })
|
||||||
|
copyFileSync(src, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = async (context) => {
|
module.exports = async (context) => {
|
||||||
const appOutDir = context.appOutDir
|
const appOutDir = context.appOutDir
|
||||||
const resourcesDir = path.join(
|
const resourcesDir = path.join(
|
||||||
@@ -25,10 +65,7 @@ module.exports = async (context) => {
|
|||||||
console.log(`[afterPack] Copying node_modules to ${targetNodeModules}`)
|
console.log(`[afterPack] Copying node_modules to ${targetNodeModules}`)
|
||||||
|
|
||||||
if (existsSync(sourceNodeModules) && existsSync(standaloneDir)) {
|
if (existsSync(sourceNodeModules) && existsSync(standaloneDir)) {
|
||||||
cpSync(sourceNodeModules, targetNodeModules, {
|
copyDereferenced(sourceNodeModules, targetNodeModules)
|
||||||
recursive: true,
|
|
||||||
dereference: true,
|
|
||||||
})
|
|
||||||
console.log("[afterPack] node_modules copied successfully")
|
console.log("[afterPack] node_modules copied successfully")
|
||||||
} else {
|
} else {
|
||||||
console.error("[afterPack] Source or target directory not found!")
|
console.error("[afterPack] Source or target directory not found!")
|
||||||
|
|||||||
@@ -6,13 +6,54 @@
|
|||||||
* that electron-builder can properly include
|
* that electron-builder can properly include
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs"
|
import {
|
||||||
|
copyFileSync,
|
||||||
|
existsSync,
|
||||||
|
lstatSync,
|
||||||
|
mkdirSync,
|
||||||
|
readdirSync,
|
||||||
|
rmSync,
|
||||||
|
statSync,
|
||||||
|
} from "node:fs"
|
||||||
import { join } from "node:path"
|
import { join } from "node:path"
|
||||||
import { fileURLToPath } from "node:url"
|
import { fileURLToPath } from "node:url"
|
||||||
|
|
||||||
const __dirname = fileURLToPath(new URL(".", import.meta.url))
|
const __dirname = fileURLToPath(new URL(".", import.meta.url))
|
||||||
const rootDir = join(__dirname, "..")
|
const rootDir = join(__dirname, "..")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy directory recursively, converting symlinks to regular files/directories.
|
||||||
|
* This is needed because cpSync with dereference:true does NOT convert symlinks.
|
||||||
|
* macOS codesign fails if bundle contains symlinks pointing outside the bundle.
|
||||||
|
*/
|
||||||
|
function copyDereferenced(src, dst) {
|
||||||
|
const lstat = lstatSync(src)
|
||||||
|
|
||||||
|
if (lstat.isSymbolicLink()) {
|
||||||
|
// Follow symlink and check what it points to
|
||||||
|
const stat = statSync(src)
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
// Symlink to directory: recursively copy the directory contents
|
||||||
|
mkdirSync(dst, { recursive: true })
|
||||||
|
for (const entry of readdirSync(src)) {
|
||||||
|
copyDereferenced(join(src, entry), join(dst, entry))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Symlink to file: copy the actual file content
|
||||||
|
mkdirSync(join(dst, ".."), { recursive: true })
|
||||||
|
copyFileSync(src, dst)
|
||||||
|
}
|
||||||
|
} else if (lstat.isDirectory()) {
|
||||||
|
mkdirSync(dst, { recursive: true })
|
||||||
|
for (const entry of readdirSync(src)) {
|
||||||
|
copyDereferenced(join(src, entry), join(dst, entry))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mkdirSync(join(dst, ".."), { recursive: true })
|
||||||
|
copyFileSync(src, dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const standaloneDir = join(rootDir, ".next", "standalone")
|
const standaloneDir = join(rootDir, ".next", "standalone")
|
||||||
const staticDir = join(rootDir, ".next", "static")
|
const staticDir = join(rootDir, ".next", "static")
|
||||||
const targetDir = join(rootDir, "electron-standalone")
|
const targetDir = join(rootDir, "electron-standalone")
|
||||||
@@ -30,20 +71,19 @@ mkdirSync(targetDir, { recursive: true })
|
|||||||
|
|
||||||
// Copy standalone (includes node_modules)
|
// Copy standalone (includes node_modules)
|
||||||
console.log("Copying standalone directory...")
|
console.log("Copying standalone directory...")
|
||||||
cpSync(standaloneDir, targetDir, { recursive: true, dereference: true })
|
copyDereferenced(standaloneDir, targetDir)
|
||||||
|
|
||||||
// Copy static files
|
// Copy static files
|
||||||
console.log("Copying static files...")
|
console.log("Copying static files...")
|
||||||
const targetStaticDir = join(targetDir, ".next", "static")
|
const targetStaticDir = join(targetDir, ".next", "static")
|
||||||
mkdirSync(targetStaticDir, { recursive: true })
|
copyDereferenced(staticDir, targetStaticDir)
|
||||||
cpSync(staticDir, targetStaticDir, { recursive: true, dereference: true })
|
|
||||||
|
|
||||||
// Copy public folder (required for favicon-white.svg and other assets)
|
// Copy public folder (required for favicon-white.svg and other assets)
|
||||||
console.log("Copying public folder...")
|
console.log("Copying public folder...")
|
||||||
const publicDir = join(rootDir, "public")
|
const publicDir = join(rootDir, "public")
|
||||||
const targetPublicDir = join(targetDir, "public")
|
const targetPublicDir = join(targetDir, "public")
|
||||||
if (existsSync(publicDir)) {
|
if (existsSync(publicDir)) {
|
||||||
cpSync(publicDir, targetPublicDir, { recursive: true, dereference: true })
|
copyDereferenced(publicDir, targetPublicDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Done! Files prepared in electron-standalone/")
|
console.log("Done! Files prepared in electron-standalone/")
|
||||||
|
|||||||
Reference in New Issue
Block a user