update electron to v43
This commit is contained in:
parent
68ac0beedf
commit
fb6c8b6ee9
5385 changed files with 513060 additions and 123058 deletions
36
electron/node_modules/app-builder-lib/out/targets/snap/SnapTarget.d.ts
generated
vendored
Normal file
36
electron/node_modules/app-builder-lib/out/targets/snap/SnapTarget.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { Arch } from "builder-util";
|
||||
import { SnapStoreOptions } from "builder-util-runtime";
|
||||
import { Configuration } from "../../configuration";
|
||||
import { Target } from "../../core";
|
||||
import { LinuxPackager } from "../../linuxPackager";
|
||||
import { SnapcraftOptions, SnapOptions } from "../../options/SnapOptions";
|
||||
import { LinuxTargetHelper } from "../LinuxTargetHelper";
|
||||
import { SnapcraftYAML } from "./snapcraft";
|
||||
/** Abstract base for all snap build strategies (core24, legacy core18/20/22, custom pass-through). */
|
||||
export declare abstract class SnapCore<T> {
|
||||
protected readonly packager: LinuxPackager;
|
||||
protected readonly helper: LinuxTargetHelper;
|
||||
protected readonly options: T;
|
||||
protected abstract defaultPlugs: Array<string>;
|
||||
constructor(packager: LinuxPackager, helper: LinuxTargetHelper, options: T);
|
||||
abstract createDescriptor(arch: Arch): Promise<SnapcraftYAML>;
|
||||
abstract buildSnap(params: {
|
||||
snap: SnapcraftYAML;
|
||||
appOutDir: string;
|
||||
stageDir: string;
|
||||
snapArch: Arch;
|
||||
artifactPath: string;
|
||||
}): Promise<void>;
|
||||
}
|
||||
/** Snap build target — merges `snapcraft` (preferred) and legacy `snap` config, then delegates to the appropriate `SnapCore` strategy. */
|
||||
export default class SnapTarget extends Target {
|
||||
protected readonly packager: LinuxPackager;
|
||||
protected readonly helper: LinuxTargetHelper;
|
||||
readonly outDir: string;
|
||||
readonly options: SnapcraftOptions | SnapOptions;
|
||||
constructor(name: string, packager: LinuxPackager, helper: LinuxTargetHelper, outDir: string);
|
||||
build(appOutDir: string, arch: Arch): Promise<any>;
|
||||
protected findSnapPublishConfig(config?: Configuration): SnapStoreOptions | null;
|
||||
private findSnapPublishConfigInPublishNode;
|
||||
private isSnapStoreOptions;
|
||||
}
|
||||
105
electron/node_modules/app-builder-lib/out/targets/snap/SnapTarget.js
generated
vendored
Normal file
105
electron/node_modules/app-builder-lib/out/targets/snap/SnapTarget.js
generated
vendored
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SnapCore = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const path = require("path");
|
||||
const core_1 = require("../../core");
|
||||
const targetUtil_1 = require("../targetUtil");
|
||||
/** Abstract base for all snap build strategies (core24, legacy core18/20/22, custom pass-through). */
|
||||
class SnapCore {
|
||||
constructor(packager, helper, options) {
|
||||
this.packager = packager;
|
||||
this.helper = helper;
|
||||
this.options = options;
|
||||
}
|
||||
}
|
||||
exports.SnapCore = SnapCore;
|
||||
/** Snap build target — merges `snapcraft` (preferred) and legacy `snap` config, then delegates to the appropriate `SnapCore` strategy. */
|
||||
class SnapTarget extends core_1.Target {
|
||||
constructor(name, packager, helper, outDir) {
|
||||
var _a;
|
||||
super(name);
|
||||
this.packager = packager;
|
||||
this.helper = helper;
|
||||
this.outDir = outDir;
|
||||
const { config: { snapcraft, snap }, platformSpecificBuildOptions, } = packager;
|
||||
this.options = (0, builder_util_runtime_1.deepAssign)({}, platformSpecificBuildOptions, (_a = snapcraft !== null && snapcraft !== void 0 ? snapcraft : snap) !== null && _a !== void 0 ? _a : {});
|
||||
}
|
||||
async build(appOutDir, arch) {
|
||||
const packager = this.packager;
|
||||
// tslint:disable-next-line:no-invalid-template-strings
|
||||
const artifactName = packager.expandArtifactNamePattern(this.options, "snap", arch, "${name}_${version}_${arch}.${ext}", false);
|
||||
const artifactPath = path.join(this.outDir, artifactName);
|
||||
await packager.info.emitArtifactBuildStarted({
|
||||
targetPresentableName: "snap",
|
||||
file: artifactPath,
|
||||
arch,
|
||||
});
|
||||
const core = this.helper.getSnapCore();
|
||||
const snap = await core.createDescriptor(arch);
|
||||
builder_util_1.log.debug({ snap }, "snapcraft.yaml descriptor created");
|
||||
await core.buildSnap({
|
||||
snap,
|
||||
appOutDir,
|
||||
stageDir: await (0, targetUtil_1.createStageDirPath)(this, packager, arch),
|
||||
snapArch: arch,
|
||||
artifactPath,
|
||||
});
|
||||
const publishConfig = this.findSnapPublishConfig(packager.config);
|
||||
await packager.info.emitArtifactBuildCompleted({
|
||||
file: artifactPath,
|
||||
safeArtifactName: packager.computeSafeArtifactName(artifactName, "snap", arch, false),
|
||||
target: this,
|
||||
arch,
|
||||
packager,
|
||||
publishConfig,
|
||||
});
|
||||
}
|
||||
findSnapPublishConfig(config) {
|
||||
var _a, _b;
|
||||
const fallback = { provider: "snapStore" };
|
||||
if (!config) {
|
||||
return fallback;
|
||||
}
|
||||
const snapConfig = (_a = config.snapcraft) !== null && _a !== void 0 ? _a : config.snap;
|
||||
if (snapConfig === null || snapConfig === void 0 ? void 0 : snapConfig.publish) {
|
||||
return this.findSnapPublishConfigInPublishNode(snapConfig.publish);
|
||||
}
|
||||
if ((_b = config.linux) === null || _b === void 0 ? void 0 : _b.publish) {
|
||||
const configCandidate = this.findSnapPublishConfigInPublishNode(config.linux.publish);
|
||||
if (configCandidate) {
|
||||
return configCandidate;
|
||||
}
|
||||
}
|
||||
if (config.publish) {
|
||||
const configCandidate = this.findSnapPublishConfigInPublishNode(config.publish);
|
||||
if (configCandidate) {
|
||||
return configCandidate;
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
findSnapPublishConfigInPublishNode(configPublishNode) {
|
||||
if (!configPublishNode) {
|
||||
return null;
|
||||
}
|
||||
if (Array.isArray(configPublishNode)) {
|
||||
for (const configObj of configPublishNode) {
|
||||
if (this.isSnapStoreOptions(configObj)) {
|
||||
return configObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof configPublishNode === `object` && this.isSnapStoreOptions(configPublishNode)) {
|
||||
return configPublishNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
isSnapStoreOptions(configPublishNode) {
|
||||
const snapStoreOptionsCandidate = configPublishNode;
|
||||
return (snapStoreOptionsCandidate === null || snapStoreOptionsCandidate === void 0 ? void 0 : snapStoreOptionsCandidate.provider) === `snapStore`;
|
||||
}
|
||||
}
|
||||
exports.default = SnapTarget;
|
||||
//# sourceMappingURL=SnapTarget.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/targets/snap/SnapTarget.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/targets/snap/SnapTarget.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
52
electron/node_modules/app-builder-lib/out/targets/snap/core24.d.ts
generated
vendored
Normal file
52
electron/node_modules/app-builder-lib/out/targets/snap/core24.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { Arch } from "builder-util";
|
||||
import { PlugDescriptor, SlotDescriptor, SnapOptions24 } from "../../options/SnapOptions";
|
||||
import { SnapCore } from "./SnapTarget";
|
||||
import { SnapcraftYAML } from "./snapcraft";
|
||||
import { Nullish } from "builder-util-runtime";
|
||||
/** Snap build strategy for core24 — generates a native snapcraft.yaml and invokes the snapcraft CLI. */
|
||||
export declare class SnapCore24 extends SnapCore<SnapOptions24> {
|
||||
defaultPlugs: string[];
|
||||
readonly configRelativePath = "snap";
|
||||
readonly guiRelativePath: string;
|
||||
createDescriptor(arch: Arch): Promise<SnapcraftYAML>;
|
||||
private isHostMode;
|
||||
/** Writes the snapcraft.yaml, stages app files, then invokes `buildSnap()` to run the actual snapcraft build. */
|
||||
buildSnap(params: {
|
||||
snap: SnapcraftYAML;
|
||||
appOutDir: string;
|
||||
stageDir: string;
|
||||
snapArch: Arch;
|
||||
artifactPath: string;
|
||||
}): Promise<void>;
|
||||
/** Converts `SnapOptions24` into a fully resolved `SnapcraftYAML` descriptor for the given architecture. */
|
||||
mapSnapOptionsToSnapcraftYAML(arch: Arch): Promise<SnapcraftYAML>;
|
||||
/**
|
||||
* Build environment variables with proper defaults
|
||||
*/
|
||||
private buildEnvironment;
|
||||
/**
|
||||
* Build default layout for core24 with GNOME platform content snaps (non-extension mode)
|
||||
* This allows the app to access libraries from the gnome-46-2404 and mesa-2404 content snaps
|
||||
*/
|
||||
private buildDefaultLayout;
|
||||
/**
|
||||
* Process hooks directory into hook definitions
|
||||
*/
|
||||
private processHooks;
|
||||
/**
|
||||
* Normalize assumes list (can be string or array)
|
||||
*/
|
||||
normalizeAssumesList(assumes: Array<string> | string | Nullish): string[] | undefined;
|
||||
/**
|
||||
* Process plugs or slots into root-level definitions and app-level references
|
||||
*/
|
||||
processPlugOrSlots<T extends Array<string | SlotDescriptor | PlugDescriptor> | SlotDescriptor | PlugDescriptor | null>(items: T): {
|
||||
root: Record<string, unknown> | undefined;
|
||||
app: string[] | undefined;
|
||||
};
|
||||
private isBrowserSandboxAllowed;
|
||||
/**
|
||||
* Expand "default" keyword in arrays of anything
|
||||
*/
|
||||
private expandDefaultsInArray;
|
||||
}
|
||||
449
electron/node_modules/app-builder-lib/out/targets/snap/core24.js
generated
vendored
Normal file
449
electron/node_modules/app-builder-lib/out/targets/snap/core24.js
generated
vendored
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SnapCore24 = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path = require("path");
|
||||
const SnapTarget_1 = require("./SnapTarget");
|
||||
const snapcraftBuilder_1 = require("./snapcraftBuilder");
|
||||
const yaml = require("js-yaml");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
/** Snap build strategy for core24 — generates a native snapcraft.yaml and invokes the snapcraft CLI. */
|
||||
class SnapCore24 extends SnapTarget_1.SnapCore {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
// browser-support is intentionally absent here; it is auto-injected in mapSnapOptionsToSnapcraftYAML
|
||||
// when the user has not provided custom plugs, so it always lands in both root plugs and app plugs.
|
||||
this.defaultPlugs = ["desktop", "desktop-legacy", "home", "x11", "wayland", "unity7", "network", "gsettings", "audio-playback", "pulseaudio", "opengl"];
|
||||
// Snap file hierarchy:
|
||||
// - snap/gui/ gets automatically copied to meta/gui/ in the final snap
|
||||
// - Desktop files in meta/gui/ are used for menu integration
|
||||
this.configRelativePath = "snap";
|
||||
this.guiRelativePath = path.join(this.configRelativePath, "gui");
|
||||
}
|
||||
async createDescriptor(arch) {
|
||||
return await this.mapSnapOptionsToSnapcraftYAML(arch);
|
||||
}
|
||||
isHostMode() {
|
||||
return this.options.useDestructiveMode === true;
|
||||
}
|
||||
/** Writes the snapcraft.yaml, stages app files, then invokes `buildSnap()` to run the actual snapcraft build. */
|
||||
async buildSnap(params) {
|
||||
const { snap, appOutDir, stageDir, artifactPath } = params;
|
||||
const snapDirResolved = path.resolve(stageDir, this.configRelativePath);
|
||||
const snapcraftYamlPath = path.join(snapDirResolved, "snapcraft.yaml");
|
||||
// Create snap/gui directory for desktop files and icons
|
||||
// Snapcraft will automatically copy snap/gui/ contents to meta/gui/ in the final snap
|
||||
const guiOutput = path.resolve(stageDir, this.guiRelativePath);
|
||||
await (0, fs_extra_1.mkdir)(guiOutput, { recursive: true });
|
||||
const yamlContent = yaml.dump(snap, snapcraftBuilder_1.SNAPCRAFT_YAML_OPTIONS);
|
||||
await (0, fs_extra_1.writeFile)(snapcraftYamlPath, yamlContent, "utf8");
|
||||
builder_util_1.log.debug(snap, "generated snapcraft.yaml");
|
||||
// Copy icon to snap/gui/ directory
|
||||
// Snapcraft will automatically copy this to meta/gui/ in the final snap
|
||||
const desktopExtraProps = {};
|
||||
const icon = this.helper.maxIconPath;
|
||||
if (icon) {
|
||||
const iconFileName = `${snap.name}${path.extname(icon)}`;
|
||||
await (0, fs_extra_1.copy)(icon, path.join(guiOutput, iconFileName));
|
||||
// Icon path will be available at ${SNAP}/meta/gui/<icon-file> after installation
|
||||
desktopExtraProps.Icon = `\${SNAP}/meta/gui/${iconFileName}`;
|
||||
}
|
||||
// Create desktop file in snap/gui/ directory
|
||||
// Snapcraft will automatically copy this to meta/gui/ in the final snap
|
||||
const desktopFilePath = path.join(guiOutput, `${this.helper.getDesktopFileName(snap.name)}.desktop`);
|
||||
await this.helper.writeDesktopEntry(this.options, this.packager.executableName + " %U", desktopFilePath, desktopExtraProps);
|
||||
// Copy app files to the project root `app` directory so `source: app`
|
||||
// in the generated `snapcraft.yaml` (which is under `snap/`) can be
|
||||
// resolved by snapcraft running in the build environment.
|
||||
const appDir = path.resolve(stageDir, "app");
|
||||
if (path.resolve(appDir) !== path.resolve(appOutDir)) {
|
||||
builder_util_1.log.debug({ to: builder_util_1.log.filePath(appDir), from: builder_util_1.log.filePath(appOutDir) }, "copying app files to project root app directory");
|
||||
await (0, builder_util_1.copyDir)(appOutDir, appDir);
|
||||
}
|
||||
// Auto-generate `organize` mapping for the app part so top-level helper
|
||||
// binaries and resources are placed under `app/` inside the snap. Update
|
||||
// the already-written `snapcraft.yaml` so the build sees the mapping.
|
||||
try {
|
||||
const appPart = snap.parts[snap.name];
|
||||
if (appPart) {
|
||||
const entries = (await (0, fs_extra_1.readdir)(appOutDir)).sort();
|
||||
const organize = appPart.organize || {};
|
||||
for (const entry of entries) {
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
if (organize[entry]) {
|
||||
continue;
|
||||
}
|
||||
organize[entry] = `app/${entry}`;
|
||||
}
|
||||
appPart.organize = organize;
|
||||
const updatedYaml = yaml.dump(snap, snapcraftBuilder_1.SNAPCRAFT_YAML_OPTIONS);
|
||||
await (0, fs_extra_1.writeFile)(snapcraftYamlPath, updatedYaml, "utf8");
|
||||
builder_util_1.log.debug({ organize }, "updated snapcraft.yaml with organize mapping");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
builder_util_1.log.warn({ error: e.message }, "failed to generate and update organize mapping");
|
||||
}
|
||||
const buildMode = {
|
||||
useLXD: this.options.useLXD === true,
|
||||
useMultipass: this.options.useMultipass === true,
|
||||
useDestructiveMode: this.options.useDestructiveMode === true,
|
||||
remoteBuild: this.options.remoteBuild || undefined,
|
||||
};
|
||||
if (this.packager.packagerOptions.effectiveOptionComputed != null) {
|
||||
const shouldSkip = await this.packager.packagerOptions.effectiveOptionComputed({ snap, ...buildMode });
|
||||
if (shouldSkip) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const rootOptions = this.packager.config.snapcraft;
|
||||
await (0, snapcraftBuilder_1.buildSnap)({
|
||||
snapcraftConfig: snap,
|
||||
artifactPath,
|
||||
stageDir,
|
||||
packager: this.packager,
|
||||
cscLink: rootOptions === null || rootOptions === void 0 ? void 0 : rootOptions.cscLink,
|
||||
...buildMode,
|
||||
});
|
||||
}
|
||||
/** Converts `SnapOptions24` into a fully resolved `SnapcraftYAML` descriptor for the given architecture. */
|
||||
async mapSnapOptionsToSnapcraftYAML(arch) {
|
||||
var _a, _b, _c, _d;
|
||||
const appInfo = this.packager.appInfo;
|
||||
const appName = this.packager.executableName.toLowerCase();
|
||||
const options = this.options;
|
||||
// Default to ["gnome"] in normal builds; no extensions in host/destructive-mode (where the
|
||||
// gnome extension is incompatible). Throw if the user explicitly includes "gnome" in host mode.
|
||||
const hostMode = this.isHostMode();
|
||||
const extensionsList = options.extensions != null ? [...options.extensions] : hostMode ? [] : ["gnome"];
|
||||
if (hostMode && extensionsList.includes("gnome")) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`The "gnome" snapcraft extension is incompatible with host/destructive-mode builds.\n` +
|
||||
`In this mode snapcraft cannot resolve the extension's command-chain source ` +
|
||||
`(/usr/share/snapcraft/extensions/desktop/command-chain) and will fail.\n\n` +
|
||||
`To resolve this, choose one of:\n` +
|
||||
` 1. Remove "gnome" from snapcraft.core24.extensions (or set it to []) and add any\n` +
|
||||
` required stage-packages manually.\n` +
|
||||
` 2. Switch to an isolated build environment by setting snapcraft.core24.useLXD: true\n` +
|
||||
` or snapcraft.core24.useMultipass: true instead of useDestructiveMode.\n\n` +
|
||||
`See: https://snapcraft.io/docs/gnome-extension`);
|
||||
}
|
||||
const resolvedExtensions = extensionsList.length > 0 ? extensionsList : undefined;
|
||||
const useGnomeExtension = extensionsList.includes("gnome");
|
||||
// Create the app part
|
||||
const appPart = {
|
||||
plugin: "dump",
|
||||
source: "app",
|
||||
"build-packages": ((_a = options.buildPackages) === null || _a === void 0 ? void 0 : _a.length) ? options.buildPackages : undefined,
|
||||
"stage-packages": this.expandDefaultsInArray(options.stagePackages, snapcraftBuilder_1.DEFAULT_STAGE_PACKAGES),
|
||||
after: this.expandDefaultsInArray(options.after, []),
|
||||
stage: ((_b = options.appPartStage) === null || _b === void 0 ? void 0 : _b.length) ? options.appPartStage : undefined,
|
||||
};
|
||||
// Process plugs and slots
|
||||
// When using GNOME extension, we don't need to manually configure content snaps
|
||||
// The extension will handle: gnome-46-2404, gtk-3-themes, icon-themes, sound-themes
|
||||
let rootPlugs;
|
||||
let appPlugs;
|
||||
if (useGnomeExtension) {
|
||||
// With GNOME extension, only process user-provided custom plugs
|
||||
const result = options.plugs ? this.processPlugOrSlots(options.plugs) : { root: undefined, app: undefined };
|
||||
rootPlugs = result.root;
|
||||
// Extension automatically adds common plugs, so we only add custom ones
|
||||
appPlugs = result.app;
|
||||
}
|
||||
else {
|
||||
// Without GNOME extension, we need manual content snaps
|
||||
const defaultRootPlugs = {
|
||||
"gtk-3-themes": {
|
||||
interface: "content",
|
||||
target: "$SNAP/data-dir/themes",
|
||||
"default-provider": "gtk-common-themes",
|
||||
},
|
||||
"icon-themes": {
|
||||
interface: "content",
|
||||
target: "$SNAP/data-dir/icons",
|
||||
"default-provider": "gtk-common-themes",
|
||||
},
|
||||
"sound-themes": {
|
||||
interface: "content",
|
||||
target: "$SNAP/data-dir/sounds",
|
||||
"default-provider": "gtk-common-themes",
|
||||
},
|
||||
"gnome-46-2404": {
|
||||
interface: "content",
|
||||
target: "$SNAP/gnome-platform",
|
||||
"default-provider": "gnome-46-2404",
|
||||
},
|
||||
"gpu-2404": {
|
||||
interface: "content",
|
||||
target: "$SNAP/gpu-2404",
|
||||
"default-provider": "mesa-2404",
|
||||
},
|
||||
};
|
||||
const result = options.plugs
|
||||
? this.processPlugOrSlots(options.plugs)
|
||||
: hostMode
|
||||
? { root: undefined, app: this.defaultPlugs }
|
||||
: {
|
||||
root: defaultRootPlugs,
|
||||
app: this.defaultPlugs,
|
||||
};
|
||||
rootPlugs = result.root;
|
||||
appPlugs = result.app;
|
||||
}
|
||||
// Always add browser-support with allow-sandbox so Chromium's internal sandbox
|
||||
// can create user namespaces under strict confinement. Without allow-sandbox: true
|
||||
// the app crashes immediately with "FATAL: Permission denied (13)" in credentials.cc.
|
||||
// Skip the injection only when the user has explicitly provided their own plugs
|
||||
// (they are responsible for including browser-support in that case).
|
||||
if (!options.plugs) {
|
||||
rootPlugs = { ...rootPlugs, "browser-support": { interface: "browser-support", "allow-sandbox": true } };
|
||||
if (!(appPlugs === null || appPlugs === void 0 ? void 0 : appPlugs.includes("browser-support"))) {
|
||||
appPlugs = [...(appPlugs !== null && appPlugs !== void 0 ? appPlugs : []), "browser-support"];
|
||||
}
|
||||
}
|
||||
const { root: rootSlots, app: appSlots } = options.slots ? this.processPlugOrSlots(options.slots) : { root: undefined, app: undefined };
|
||||
// Build the effective arg list for the snap command.
|
||||
// Start with any user-supplied executableArgs, then conditionally add --no-sandbox
|
||||
// if browser-support with allow-sandbox:true is not present in the resolved plugs
|
||||
// (mirrors the same logic in SnapCoreLegacy.buildSnap).
|
||||
const extraArgs = [...((_c = this.options.executableArgs) !== null && _c !== void 0 ? _c : [])];
|
||||
if (this.options.forceX11 === true) {
|
||||
if (!extraArgs.includes("--ozone-platform=x11")) {
|
||||
extraArgs.push("--ozone-platform=x11");
|
||||
}
|
||||
}
|
||||
if (this.helper.isElectronVersionGreaterOrEqualThan("5.0.0") && !this.isBrowserSandboxAllowed(rootPlugs)) {
|
||||
if (!extraArgs.includes("--no-sandbox")) {
|
||||
extraArgs.push("--no-sandbox");
|
||||
}
|
||||
}
|
||||
const commandSuffix = extraArgs.length > 0 ? ` ${extraArgs.join(" ")}` : "";
|
||||
// Create the app configuration
|
||||
const desktopBaseName = this.helper.getDesktopFileName(appName);
|
||||
const app = {
|
||||
command: `app/${this.packager.executableName}${commandSuffix}`,
|
||||
"command-chain": undefined, // explicitly undefined so removeNullish strips it; extensions supply their own command-chain
|
||||
plugs: appPlugs,
|
||||
slots: appSlots,
|
||||
autostart: options.autoStart ? `${desktopBaseName}.desktop` : undefined,
|
||||
desktop: `meta/gui/${desktopBaseName}.desktop`,
|
||||
extensions: resolvedExtensions,
|
||||
};
|
||||
// Icon path — build-time relative path so snapcraft can find the file in snap/gui/
|
||||
await this.helper.icons;
|
||||
const iconPath = this.helper.maxIconPath != null ? `snap/gui/${appName}${path.extname(this.helper.maxIconPath)}` : undefined;
|
||||
// Process hooks if configured
|
||||
const hooksConfig = options.hooks;
|
||||
const hooks = hooksConfig ? await this.processHooks(hooksConfig) : undefined;
|
||||
// Parts configuration - the extension automatically adds a gnome/sdk part
|
||||
// Don't manually add desktop-launch when using the extension
|
||||
const parts = {
|
||||
[appName]: appPart,
|
||||
};
|
||||
// Note: `organize` will be generated later in `buildSnap` based on the
|
||||
// actual contents of the built app directory so helper binaries and
|
||||
// resources are automatically moved under `app/` in the snap.
|
||||
// Build the snapcraft configuration
|
||||
const snapcraft = {
|
||||
// Required fields
|
||||
name: appName,
|
||||
base: "core24",
|
||||
confinement: options.confinement || "strict",
|
||||
parts: parts,
|
||||
// Architecture/Platform — only needed for cross-compilation; snapcraft 8
|
||||
// defaults to host arch and snapcraft 7 rejects this field entirely.
|
||||
...(arch !== (0, builder_util_1.archFromString)(process.arch)
|
||||
? {
|
||||
platforms: {
|
||||
[(0, builder_util_1.toLinuxArchString)(arch, "snap")]: {
|
||||
"build-for": (0, builder_util_1.toLinuxArchString)(arch, "snap"),
|
||||
"build-on": (0, builder_util_1.toLinuxArchString)((0, builder_util_1.archFromString)(process.arch), "snap"),
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
// Metadata - with fallbacks from appInfo
|
||||
version: appInfo.version,
|
||||
summary: options.summary || appInfo.productName,
|
||||
description: this.helper.getDescription(options),
|
||||
grade: options.grade || "stable",
|
||||
title: options.title || appInfo.productName,
|
||||
icon: iconPath,
|
||||
// Build configuration
|
||||
compression: options.compression || undefined,
|
||||
assumes: this.normalizeAssumesList(options.assumes),
|
||||
// Environment
|
||||
environment: this.buildEnvironment(options),
|
||||
// User-supplied layout always wins. Without gnome extension and not in host mode, fall back to content-snap defaults.
|
||||
layout: (_d = options.layout) !== null && _d !== void 0 ? _d : (useGnomeExtension || hostMode ? undefined : this.buildDefaultLayout(options)),
|
||||
// Interfaces
|
||||
plugs: rootPlugs,
|
||||
slots: rootSlots,
|
||||
// Hooks
|
||||
hooks: hooks,
|
||||
// Apps
|
||||
apps: {
|
||||
[appName]: app,
|
||||
},
|
||||
};
|
||||
return (0, builder_util_1.removeNullish)(snapcraft);
|
||||
}
|
||||
/**
|
||||
* Build environment variables with proper defaults
|
||||
*/
|
||||
buildEnvironment(options) {
|
||||
var _a;
|
||||
const env = {};
|
||||
// Add default TMPDIR for Electron/Chromium apps
|
||||
if (!((_a = options.environment) === null || _a === void 0 ? void 0 : _a.TMPDIR)) {
|
||||
env.TMPDIR = "$XDG_RUNTIME_DIR";
|
||||
}
|
||||
if (options.environment) {
|
||||
(0, builder_util_runtime_1.deepAssign)(env, options.environment);
|
||||
}
|
||||
return Object.keys(env).length > 0 ? env : undefined;
|
||||
}
|
||||
/**
|
||||
* Build default layout for core24 with GNOME platform content snaps (non-extension mode)
|
||||
* This allows the app to access libraries from the gnome-46-2404 and mesa-2404 content snaps
|
||||
*/
|
||||
buildDefaultLayout(options) {
|
||||
// If user provides custom layout, use that instead
|
||||
if (options.layout) {
|
||||
return options.layout;
|
||||
}
|
||||
// Default layout for core24 Electron apps using GNOME content snaps WITHOUT extension
|
||||
return {
|
||||
"/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.0": {
|
||||
bind: "$SNAP/gnome-platform/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.0",
|
||||
},
|
||||
"/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.1": {
|
||||
bind: "$SNAP/gnome-platform/usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/webkit2gtk-4.1",
|
||||
},
|
||||
"/usr/share/xml/iso-codes": {
|
||||
bind: "$SNAP/gnome-platform/usr/share/xml/iso-codes",
|
||||
},
|
||||
"/usr/share/libdrm": {
|
||||
bind: "$SNAP/gpu-2404/libdrm",
|
||||
},
|
||||
"/usr/share/drirc.d": {
|
||||
symlink: "$SNAP/gpu-2404/drirc.d",
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Process hooks directory into hook definitions
|
||||
*/
|
||||
async processHooks(hooksPath) {
|
||||
try {
|
||||
const buildResourcesDir = this.packager.buildResourcesDir;
|
||||
const hooksDir = path.resolve(buildResourcesDir, hooksPath);
|
||||
if (!hooksDir.startsWith(buildResourcesDir + path.sep) && hooksDir !== buildResourcesDir) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`snapcraft.core24.hooks must resolve within the build resources directory (got "${hooksDir}")`);
|
||||
}
|
||||
const hookFiles = await (0, fs_extra_1.readdir)(hooksDir);
|
||||
if (hookFiles.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
const hooks = {};
|
||||
for (const hookFile of hookFiles) {
|
||||
const hookName = path.basename(hookFile, path.extname(hookFile));
|
||||
if (!(0, builder_util_runtime_1.isValidKey)(hookName)) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`Invalid hook name: ${hookName}`);
|
||||
}
|
||||
hooks[hookName] = {
|
||||
// Hook definitions will be populated by snapcraft from the files
|
||||
// Just register that these hooks exist
|
||||
};
|
||||
}
|
||||
return hooks;
|
||||
}
|
||||
catch (e) {
|
||||
builder_util_1.log.error({ message: e.message }, "error processing Snap hooks directory");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Normalize assumes list (can be string or array)
|
||||
*/
|
||||
normalizeAssumesList(assumes) {
|
||||
if (!assumes) {
|
||||
return undefined;
|
||||
}
|
||||
if (typeof assumes === "string") {
|
||||
return [assumes];
|
||||
}
|
||||
return assumes.length > 0 ? assumes : undefined;
|
||||
}
|
||||
/**
|
||||
* Process plugs or slots into root-level definitions and app-level references
|
||||
*/
|
||||
processPlugOrSlots(items) {
|
||||
if (!items || (Array.isArray(items) && items.length === 0)) {
|
||||
return { root: undefined, app: undefined };
|
||||
}
|
||||
const root = {};
|
||||
const app = [];
|
||||
// Handle single descriptor object
|
||||
if (!Array.isArray(items)) {
|
||||
Object.entries(items).forEach(([name, config]) => {
|
||||
if (!(0, builder_util_runtime_1.isValidKey)(name)) {
|
||||
throw new Error(`Invalid plug/slot name: ${name}`);
|
||||
}
|
||||
root[name] = config;
|
||||
app.push(name);
|
||||
});
|
||||
return { root, app };
|
||||
}
|
||||
// Handle array - support "default" keyword
|
||||
const processedItems = this.expandDefaultsInArray(items, this.defaultPlugs);
|
||||
for (const item of processedItems !== null && processedItems !== void 0 ? processedItems : []) {
|
||||
if (typeof item === "string") {
|
||||
// Simple string reference
|
||||
app.push(item);
|
||||
}
|
||||
else {
|
||||
// Descriptor object with configuration
|
||||
Object.entries(item).forEach(([name, config]) => {
|
||||
if (!(0, builder_util_runtime_1.isValidKey)(name)) {
|
||||
throw new Error(`Invalid plug/slot name: ${name}`);
|
||||
}
|
||||
root[name] = config;
|
||||
app.push(name);
|
||||
});
|
||||
}
|
||||
}
|
||||
return { root: Object.keys(root).length > 0 ? root : undefined, app: app.length > 0 ? app : undefined };
|
||||
}
|
||||
isBrowserSandboxAllowed(plugs) {
|
||||
if (!plugs) {
|
||||
return false;
|
||||
}
|
||||
for (const plug of Object.values(plugs)) {
|
||||
if ((plug === null || plug === void 0 ? void 0 : plug.interface) === "browser-support" && plug["allow-sandbox"] === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Expand "default" keyword in arrays of anything
|
||||
*/
|
||||
expandDefaultsInArray(items, defaults) {
|
||||
const result = [];
|
||||
for (const item of items !== null && items !== void 0 ? items : []) {
|
||||
if (typeof item === "string" && item === "default") {
|
||||
result.push(...defaults);
|
||||
}
|
||||
else {
|
||||
result.push(item);
|
||||
}
|
||||
}
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
}
|
||||
exports.SnapCore24 = SnapCore24;
|
||||
//# sourceMappingURL=core24.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/targets/snap/core24.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/targets/snap/core24.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
28
electron/node_modules/app-builder-lib/out/targets/snap/coreCustom.d.ts
generated
vendored
Normal file
28
electron/node_modules/app-builder-lib/out/targets/snap/coreCustom.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { Arch } from "builder-util";
|
||||
import { SnapOptionsCustom } from "../../options/SnapOptions";
|
||||
import { SnapCore } from "./SnapTarget";
|
||||
import { SnapcraftYAML } from "./snapcraft";
|
||||
/**
|
||||
* Pass-through snap builder for `base: "custom"`.
|
||||
*
|
||||
* electron-builder reads the file at `snapcraft.custom.yaml` (or the inline object),
|
||||
* writes it into the stage directory, and invokes snapcraft. **Nothing is injected or
|
||||
* modified in any way** — no plugs, extensions, organize mappings, desktop files,
|
||||
* environment variables, layout entries, or stage packages. `linux.*` configuration
|
||||
* is also not cascaded into the descriptor.
|
||||
*
|
||||
* Because electron-builder exerts no control over the descriptor's content, GitHub
|
||||
* issue support for snap runtime problems encountered with custom yaml files is limited.
|
||||
* Prefer a structured base (`core24`, `core22`, etc.) for a fully managed build.
|
||||
*/
|
||||
export declare class SnapCoreCustom extends SnapCore<SnapOptionsCustom> {
|
||||
readonly defaultPlugs: string[];
|
||||
createDescriptor(_arch: Arch): Promise<SnapcraftYAML>;
|
||||
buildSnap(params: {
|
||||
snap: SnapcraftYAML;
|
||||
appOutDir: string;
|
||||
stageDir: string;
|
||||
snapArch: Arch;
|
||||
artifactPath: string;
|
||||
}): Promise<void>;
|
||||
}
|
||||
63
electron/node_modules/app-builder-lib/out/targets/snap/coreCustom.js
generated
vendored
Normal file
63
electron/node_modules/app-builder-lib/out/targets/snap/coreCustom.js
generated
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SnapCoreCustom = void 0;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const yaml = require("js-yaml");
|
||||
const path = require("path");
|
||||
const SnapTarget_1 = require("./SnapTarget");
|
||||
const snapcraftBuilder_1 = require("./snapcraftBuilder");
|
||||
/**
|
||||
* Pass-through snap builder for `base: "custom"`.
|
||||
*
|
||||
* electron-builder reads the file at `snapcraft.custom.yaml` (or the inline object),
|
||||
* writes it into the stage directory, and invokes snapcraft. **Nothing is injected or
|
||||
* modified in any way** — no plugs, extensions, organize mappings, desktop files,
|
||||
* environment variables, layout entries, or stage packages. `linux.*` configuration
|
||||
* is also not cascaded into the descriptor.
|
||||
*
|
||||
* Because electron-builder exerts no control over the descriptor's content, GitHub
|
||||
* issue support for snap runtime problems encountered with custom yaml files is limited.
|
||||
* Prefer a structured base (`core24`, `core22`, etc.) for a fully managed build.
|
||||
*/
|
||||
class SnapCoreCustom extends SnapTarget_1.SnapCore {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.defaultPlugs = [];
|
||||
}
|
||||
async createDescriptor(_arch) {
|
||||
const { yaml: yamlPath } = this.options;
|
||||
if (!yamlPath) {
|
||||
throw new builder_util_1.InvalidConfigurationError('snapcraft.base = "custom" requires an entry in snapcraft.custom.yaml (either a path to a snapcraft.yaml file or a SnapcraftYAML object directly in the configuration)');
|
||||
}
|
||||
if (typeof yamlPath !== "string") {
|
||||
return yamlPath; // fully defined SnapcraftYAML object provided directly in configuration, no file reading necessary
|
||||
}
|
||||
const resolved = path.resolve(this.packager.buildResourcesDir, yamlPath);
|
||||
const buildResourcesDir = this.packager.buildResourcesDir;
|
||||
if (!resolved.startsWith(buildResourcesDir + path.sep) && resolved !== buildResourcesDir) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`snapcraft.custom.yaml must resolve within the build resources directory (got "${resolved}")`);
|
||||
}
|
||||
const raw = await (0, fs_extra_1.readFile)(resolved, "utf8");
|
||||
return yaml.load(raw);
|
||||
}
|
||||
async buildSnap(params) {
|
||||
const { snap, stageDir, artifactPath } = params;
|
||||
const snapDirResolved = path.resolve(stageDir, "snap");
|
||||
const snapcraftYamlPath = path.join(snapDirResolved, "snapcraft.yaml");
|
||||
const yamlContent = yaml.dump(snap, snapcraftBuilder_1.SNAPCRAFT_YAML_OPTIONS);
|
||||
await (0, fs_extra_1.outputFile)(snapcraftYamlPath, yamlContent, "utf8");
|
||||
builder_util_1.log.debug(snap, "using custom snapcraft.yaml (pass-through, no injection)");
|
||||
if (this.packager.packagerOptions.effectiveOptionComputed != null && (await this.packager.packagerOptions.effectiveOptionComputed({ snap }))) {
|
||||
return;
|
||||
}
|
||||
await (0, snapcraftBuilder_1.buildSnap)({
|
||||
snapcraftConfig: snap,
|
||||
artifactPath,
|
||||
stageDir,
|
||||
packager: this.packager,
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.SnapCoreCustom = SnapCoreCustom;
|
||||
//# sourceMappingURL=coreCustom.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/targets/snap/coreCustom.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/targets/snap/coreCustom.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"coreCustom.js","sourceRoot":"","sources":["../../../src/targets/snap/coreCustom.ts"],"names":[],"mappings":";;;AAAA,+CAAmE;AACnE,uCAA+C;AAC/C,gCAA+B;AAC/B,6BAA4B;AAE5B,6CAAuC;AAEvC,yDAAsE;AAEtE;;;;;;;;;;;;GAYG;AACH,MAAa,cAAe,SAAQ,qBAA2B;IAA/D;;QACW,iBAAY,GAAa,EAAE,CAAA;IA0CtC,CAAC;IAxCC,KAAK,CAAC,gBAAgB,CAAC,KAAW;QAChC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,wCAAyB,CACjC,uKAAuK,CACxK,CAAA;QACH,CAAC;QACD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,OAAO,QAAQ,CAAA,CAAC,mGAAmG;QACrH,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAA;QACxE,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAA;QACzD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YACzF,MAAM,IAAI,wCAAyB,CAAC,iFAAiF,QAAQ,IAAI,CAAC,CAAA;QACpI,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAA,mBAAQ,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAkB,CAAA;IACxC,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAA0G;QACxH,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAAA;QAE/C,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QACtD,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAA;QAEtE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,yCAAsB,CAAC,CAAA;QAC3D,MAAM,IAAA,qBAAU,EAAC,iBAAiB,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;QACxD,kBAAG,CAAC,KAAK,CAAC,IAAI,EAAE,0DAA0D,CAAC,CAAA;QAE3E,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,uBAAuB,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,uBAAuB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC7I,OAAM;QACR,CAAC;QAED,MAAM,IAAA,4BAAS,EAAC;YACd,eAAe,EAAE,IAAI;YACrB,YAAY;YACZ,QAAQ;YACR,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAA;IACJ,CAAC;CACF;AA3CD,wCA2CC","sourcesContent":["import { Arch, InvalidConfigurationError, log } from \"builder-util\"\nimport { outputFile, readFile } from \"fs-extra\"\nimport * as yaml from \"js-yaml\"\nimport * as path from \"path\"\nimport { SnapOptionsCustom } from \"../../options/SnapOptions\"\nimport { SnapCore } from \"./SnapTarget\"\nimport { SnapcraftYAML } from \"./snapcraft\"\nimport { buildSnap, SNAPCRAFT_YAML_OPTIONS } from \"./snapcraftBuilder\"\n\n/**\n * Pass-through snap builder for `base: \"custom\"`.\n *\n * electron-builder reads the file at `snapcraft.custom.yaml` (or the inline object),\n * writes it into the stage directory, and invokes snapcraft. **Nothing is injected or\n * modified in any way** — no plugs, extensions, organize mappings, desktop files,\n * environment variables, layout entries, or stage packages. `linux.*` configuration\n * is also not cascaded into the descriptor.\n *\n * Because electron-builder exerts no control over the descriptor's content, GitHub\n * issue support for snap runtime problems encountered with custom yaml files is limited.\n * Prefer a structured base (`core24`, `core22`, etc.) for a fully managed build.\n */\nexport class SnapCoreCustom extends SnapCore<SnapOptionsCustom> {\n readonly defaultPlugs: string[] = []\n\n async createDescriptor(_arch: Arch): Promise<SnapcraftYAML> {\n const { yaml: yamlPath } = this.options\n if (!yamlPath) {\n throw new InvalidConfigurationError(\n 'snapcraft.base = \"custom\" requires an entry in snapcraft.custom.yaml (either a path to a snapcraft.yaml file or a SnapcraftYAML object directly in the configuration)'\n )\n }\n if (typeof yamlPath !== \"string\") {\n return yamlPath // fully defined SnapcraftYAML object provided directly in configuration, no file reading necessary\n }\n const resolved = path.resolve(this.packager.buildResourcesDir, yamlPath)\n const buildResourcesDir = this.packager.buildResourcesDir\n if (!resolved.startsWith(buildResourcesDir + path.sep) && resolved !== buildResourcesDir) {\n throw new InvalidConfigurationError(`snapcraft.custom.yaml must resolve within the build resources directory (got \"${resolved}\")`)\n }\n const raw = await readFile(resolved, \"utf8\")\n return yaml.load(raw) as SnapcraftYAML\n }\n\n async buildSnap(params: { snap: SnapcraftYAML; appOutDir: string; stageDir: string; snapArch: Arch; artifactPath: string }): Promise<void> {\n const { snap, stageDir, artifactPath } = params\n\n const snapDirResolved = path.resolve(stageDir, \"snap\")\n const snapcraftYamlPath = path.join(snapDirResolved, \"snapcraft.yaml\")\n\n const yamlContent = yaml.dump(snap, SNAPCRAFT_YAML_OPTIONS)\n await outputFile(snapcraftYamlPath, yamlContent, \"utf8\")\n log.debug(snap, \"using custom snapcraft.yaml (pass-through, no injection)\")\n\n if (this.packager.packagerOptions.effectiveOptionComputed != null && (await this.packager.packagerOptions.effectiveOptionComputed({ snap }))) {\n return\n }\n\n await buildSnap({\n snapcraftConfig: snap,\n artifactPath,\n stageDir,\n packager: this.packager,\n })\n }\n}\n"]}
|
||||
43
electron/node_modules/app-builder-lib/out/targets/snap/coreLegacy.d.ts
generated
vendored
Normal file
43
electron/node_modules/app-builder-lib/out/targets/snap/coreLegacy.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { Arch } from "builder-util";
|
||||
import { SnapOptions } from "../../options/SnapOptions";
|
||||
import { SnapCore } from "./SnapTarget";
|
||||
import { SnapcraftYAML } from "./snapcraft";
|
||||
export declare class SnapCoreLegacy extends SnapCore<SnapOptions> {
|
||||
private isUseTemplateApp;
|
||||
defaultPlugs: string[];
|
||||
private replaceDefault;
|
||||
createDescriptor(arch: Arch): Promise<SnapcraftYAML>;
|
||||
buildSnap(props: {
|
||||
snap: any;
|
||||
appOutDir: string;
|
||||
stageDir: string;
|
||||
snapArch: Arch;
|
||||
artifactPath: string;
|
||||
}): Promise<void>;
|
||||
private buildWithTemplate;
|
||||
private buildWithoutTemplate;
|
||||
private stageSnapFiles;
|
||||
private normalizePlugConfiguration;
|
||||
private isBrowserSandboxAllowed;
|
||||
private archNameToTriplet;
|
||||
}
|
||||
/** Single-quote a shell argument, escaping any embedded single quotes. */
|
||||
export declare function shellQuote(arg: string): string;
|
||||
/**
|
||||
* Builds the content of command.sh for a snap package.
|
||||
*
|
||||
* For both template and no-template builds, the desktop-integration scripts are
|
||||
* sourced from the snap root ($SNAP):
|
||||
* - Template: scripts are embedded in the template tarball at the snap root.
|
||||
* - No-template: the snapcraft.yaml `launch-scripts` part uses `plugin: dump,
|
||||
* source: scripts`, which stages stageDir/scripts/ contents directly into the
|
||||
* snap root — so $SNAP/desktop-init.sh is correct in both cases.
|
||||
*
|
||||
* The only difference between template and no-template is the app executable prefix:
|
||||
* template apps are at $SNAP/<name>; no-template apps are at $SNAP/app/<name>.
|
||||
*/
|
||||
export declare function buildCommandShContent(opts: {
|
||||
isTemplate: boolean;
|
||||
executableName: string;
|
||||
extraAppArgs: string[];
|
||||
}): string;
|
||||
416
electron/node_modules/app-builder-lib/out/targets/snap/coreLegacy.js
generated
vendored
Normal file
416
electron/node_modules/app-builder-lib/out/targets/snap/coreLegacy.js
generated
vendored
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SnapCoreLegacy = void 0;
|
||||
exports.shellQuote = shellQuote;
|
||||
exports.buildCommandShContent = buildCommandShContent;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const promises_1 = require("fs/promises");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path = require("path");
|
||||
const linux_1 = require("../../toolsets/linux");
|
||||
const electronGet_1 = require("../../util/electronGet");
|
||||
const pathManager_1 = require("../../util/pathManager");
|
||||
const LibUiFramework_1 = require("../../frameworks/LibUiFramework");
|
||||
const SnapTarget_1 = require("./SnapTarget");
|
||||
const snapcraftBuilder_1 = require("./snapcraftBuilder");
|
||||
const js_yaml_1 = require("js-yaml");
|
||||
// Snap template release info from electron-userland/electron-builder-binaries
|
||||
const SNAP_TEMPLATES = {
|
||||
amd64: {
|
||||
releaseName: "snap-template-4.0-2",
|
||||
filenameWithExt: "snap-template-electron-4.0-2-amd64.tar.7z",
|
||||
checksums: { "snap-template-electron-4.0-2-amd64.tar.7z": "5e3ab4e09364ac06f0072b1c2dab9138318c933f6b2c7374f893b5ec44d19e6f" },
|
||||
},
|
||||
armhf: {
|
||||
releaseName: "snap-template-4.0-1",
|
||||
filenameWithExt: "snap-template-electron-4.0-1-armhf.tar.7z",
|
||||
checksums: { "snap-template-electron-4.0-1-armhf.tar.7z": "6f7553e904f4e043bc3019f0899d05e01a283b00b61fec22e932296490e3be6b" },
|
||||
},
|
||||
};
|
||||
// Handles core18/core20/core22 snaps via mksquashfs (template) or snapcraft CLI (no-template).
|
||||
// See: https://github.com/develar/app-builder/blob/master/pkg/package-format/snap
|
||||
class SnapCoreLegacy extends SnapTarget_1.SnapCore {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.isUseTemplateApp = false;
|
||||
this.defaultPlugs = ["desktop", "desktop-legacy", "home", "x11", "wayland", "unity7", "browser-support", "network", "gsettings", "audio-playback", "pulseaudio", "opengl"];
|
||||
}
|
||||
replaceDefault(inList, defaultList) {
|
||||
const result = (0, builder_util_1.replaceDefault)(inList, defaultList);
|
||||
if (result !== defaultList) {
|
||||
this.isUseTemplateApp = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
async createDescriptor(arch) {
|
||||
const appInfo = this.packager.appInfo;
|
||||
const snapName = this.packager.executableName.toLowerCase();
|
||||
const options = this.options;
|
||||
const plugs = this.normalizePlugConfiguration(this.options.plugs);
|
||||
const plugNames = this.replaceDefault(plugs == null ? null : Object.getOwnPropertyNames(plugs), this.defaultPlugs);
|
||||
const slots = this.normalizePlugConfiguration(this.options.slots);
|
||||
const buildPackages = (0, builder_util_runtime_1.asArray)(options.buildPackages);
|
||||
const stagePackages = this.replaceDefault(options.stagePackages, snapcraftBuilder_1.DEFAULT_STAGE_PACKAGES);
|
||||
const stageSet = new Set(stagePackages);
|
||||
const stageMatchesDefaults = stagePackages.length === snapcraftBuilder_1.DEFAULT_STAGE_PACKAGES.length && snapcraftBuilder_1.DEFAULT_STAGE_PACKAGES.every((p) => stageSet.has(p));
|
||||
// Template app is only available for x64/armv7l, and only when no packages are customised.
|
||||
this.isUseTemplateApp = this.options.useTemplateApp !== false && (arch === builder_util_1.Arch.x64 || arch === builder_util_1.Arch.armv7l) && buildPackages.length === 0 && stageMatchesDefaults;
|
||||
const appDescriptor = {
|
||||
command: "command.sh",
|
||||
plugs: plugNames,
|
||||
adapter: "none",
|
||||
};
|
||||
const snap = (0, js_yaml_1.load)(await (0, fs_extra_1.readFile)(path.join((0, pathManager_1.getTemplatePath)("snap"), "snapcraft.yaml"), "utf-8"));
|
||||
if (this.isUseTemplateApp) {
|
||||
delete appDescriptor.adapter;
|
||||
}
|
||||
if (options.base != null) {
|
||||
snap.base = options.base;
|
||||
if (Number(snap.base.split("core")[1]) >= 22) {
|
||||
delete appDescriptor.adapter;
|
||||
}
|
||||
}
|
||||
if (options.grade != null) {
|
||||
snap.grade = options.grade;
|
||||
}
|
||||
if (options.confinement != null) {
|
||||
snap.confinement = options.confinement;
|
||||
}
|
||||
if (options.appPartStage != null) {
|
||||
snap.parts.app.stage = options.appPartStage;
|
||||
}
|
||||
if (options.layout != null) {
|
||||
snap.layout = options.layout;
|
||||
}
|
||||
if (slots != null) {
|
||||
appDescriptor.slots = Object.getOwnPropertyNames(slots);
|
||||
for (const slotName of appDescriptor.slots) {
|
||||
if (!(0, builder_util_runtime_1.isValidKey)(slotName)) {
|
||||
throw new Error(`Invalid plug/slot name: ${slotName}`);
|
||||
}
|
||||
const slotOptions = slots[slotName];
|
||||
if (slotOptions == null) {
|
||||
continue;
|
||||
}
|
||||
if (!snap.slots) {
|
||||
snap.slots = {};
|
||||
}
|
||||
snap.slots[slotName] = slotOptions;
|
||||
}
|
||||
}
|
||||
(0, builder_util_runtime_1.deepAssign)(snap, {
|
||||
name: snapName,
|
||||
version: appInfo.version,
|
||||
title: options.title || appInfo.productName,
|
||||
summary: options.summary || appInfo.productName,
|
||||
compression: options.compression,
|
||||
description: this.helper.getDescription(options),
|
||||
architectures: [(0, builder_util_1.toLinuxArchString)(arch, "snap")],
|
||||
apps: {
|
||||
[snapName]: appDescriptor,
|
||||
},
|
||||
parts: {
|
||||
app: {
|
||||
"stage-packages": stagePackages,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (options.autoStart) {
|
||||
appDescriptor.autostart = `${this.helper.getDesktopFileName(snap.name)}.desktop`;
|
||||
}
|
||||
if (options.confinement === "classic") {
|
||||
delete appDescriptor.plugs;
|
||||
delete snap.plugs;
|
||||
}
|
||||
else {
|
||||
const archTriplet = this.archNameToTriplet(arch);
|
||||
const environment = {
|
||||
PATH: "$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH",
|
||||
SNAP_DESKTOP_RUNTIME: "$SNAP/gnome-platform",
|
||||
LD_LIBRARY_PATH: [
|
||||
"$SNAP_LIBRARY_PATH",
|
||||
"$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/" + archTriplet + ":$SNAP/usr/lib/" + archTriplet,
|
||||
"$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib",
|
||||
"$SNAP/lib/" + archTriplet + ":$SNAP/usr/lib/" + archTriplet,
|
||||
].join(":"),
|
||||
...options.environment,
|
||||
};
|
||||
const allow = options.allowNativeWayland;
|
||||
const isOldElectron = !this.helper.isElectronVersionGreaterOrEqualThan("38.0.0", "7.0.0");
|
||||
if ((allow == null && isOldElectron) || allow === false) {
|
||||
environment.DISABLE_WAYLAND = "1";
|
||||
}
|
||||
appDescriptor.environment = environment;
|
||||
if (plugs != null) {
|
||||
for (const plugName of plugNames) {
|
||||
if (!(0, builder_util_runtime_1.isValidKey)(plugName)) {
|
||||
throw new Error(`Invalid plug/slot name: ${plugName}`);
|
||||
}
|
||||
const plugOptions = plugs[plugName];
|
||||
if (plugOptions == null) {
|
||||
continue;
|
||||
}
|
||||
if (!snap.plugs) {
|
||||
snap.plugs = {};
|
||||
}
|
||||
snap.plugs[plugName] = plugOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (buildPackages.length > 0) {
|
||||
snap.parts.app["build-packages"] = buildPackages;
|
||||
}
|
||||
if (options.after != null) {
|
||||
snap.parts.app.after = options.after;
|
||||
}
|
||||
if (options.assumes != null) {
|
||||
snap.assumes = (0, builder_util_runtime_1.asArray)(options.assumes);
|
||||
}
|
||||
return snap;
|
||||
}
|
||||
async buildSnap(props) {
|
||||
var _a, _b;
|
||||
const { snap, appOutDir, stageDir, snapArch, artifactPath } = props;
|
||||
// Build the args array for effectiveOptionComputed compatibility — tests inspect this.
|
||||
const args = [
|
||||
"snap",
|
||||
"--app",
|
||||
appOutDir,
|
||||
"--stage",
|
||||
stageDir,
|
||||
"--arch",
|
||||
(0, builder_util_1.toLinuxArchString)(snapArch, "snap"),
|
||||
"--output",
|
||||
artifactPath,
|
||||
"--executable",
|
||||
this.packager.executableName,
|
||||
];
|
||||
await this.helper.icons;
|
||||
if (this.helper.maxIconPath != null) {
|
||||
if (!this.isUseTemplateApp) {
|
||||
snap.icon = "snap/gui/icon.png";
|
||||
}
|
||||
args.push("--icon", this.helper.maxIconPath);
|
||||
}
|
||||
const snapMetaDir = path.join(stageDir, this.isUseTemplateApp ? "meta" : "snap");
|
||||
const desktopFile = path.join(snapMetaDir, "gui", `${this.helper.getDesktopFileName(snap.name)}.desktop`);
|
||||
await this.helper.writeDesktopEntry(this.options, this.packager.executableName + " %U", desktopFile, {
|
||||
Icon: "${SNAP}/meta/gui/icon.png",
|
||||
});
|
||||
const extraAppArgs = (_a = this.options.executableArgs) !== null && _a !== void 0 ? _a : [];
|
||||
if (this.helper.isElectronVersionGreaterOrEqualThan("5.0.0") && !this.isBrowserSandboxAllowed(snap)) {
|
||||
const noSandboxArg = "--no-sandbox";
|
||||
if (!extraAppArgs.includes(noSandboxArg)) {
|
||||
extraAppArgs.push(noSandboxArg);
|
||||
}
|
||||
if (this.isUseTemplateApp) {
|
||||
args.push("--exclude", "chrome-sandbox");
|
||||
}
|
||||
}
|
||||
if (extraAppArgs.length > 0) {
|
||||
args.push("--extraAppArgs=" + extraAppArgs.join(" "));
|
||||
}
|
||||
// Capture compression BEFORE it gets stripped from snap for template builds.
|
||||
const compression = (_b = this.options.compression) !== null && _b !== void 0 ? _b : "xz";
|
||||
if (snap.compression != null) {
|
||||
args.push("--compression", snap.compression);
|
||||
}
|
||||
if (this.isUseTemplateApp) {
|
||||
const fieldsToStrip = ["compression", "contact", "donation", "issues", "parts", "source-code", "website"];
|
||||
for (const field of fieldsToStrip) {
|
||||
delete snap[field];
|
||||
}
|
||||
}
|
||||
if (this.packager.packagerOptions.effectiveOptionComputed != null && (await this.packager.packagerOptions.effectiveOptionComputed({ snap, desktopFile, args }))) {
|
||||
return;
|
||||
}
|
||||
await (0, fs_extra_1.outputFile)(path.join(snapMetaDir, this.isUseTemplateApp ? "snap.yaml" : "snapcraft.yaml"), (0, builder_util_1.serializeToYaml)(snap));
|
||||
const hooksDir = await this.packager.getResource(this.options.hooks, "snap-hooks");
|
||||
if (hooksDir != null) {
|
||||
args.push("--hooks", hooksDir);
|
||||
}
|
||||
if (this.isUseTemplateApp) {
|
||||
const templateArch = snapArch === builder_util_1.Arch.x64 ? "amd64" : "armhf";
|
||||
args.push("--template-url", `electron4:${templateArch}`);
|
||||
await this.buildWithTemplate({ appOutDir, stageDir, snapArch, artifactPath, compression, hooksDir, extraAppArgs });
|
||||
}
|
||||
else {
|
||||
await this.buildWithoutTemplate({ appOutDir, stageDir, artifactPath, hooksDir, extraAppArgs });
|
||||
}
|
||||
}
|
||||
async buildWithTemplate(opts) {
|
||||
const { appOutDir, stageDir, snapArch, artifactPath, compression, hooksDir, extraAppArgs } = opts;
|
||||
const templateArch = snapArch === builder_util_1.Arch.x64 ? "amd64" : "armhf";
|
||||
const { releaseName, filenameWithExt, checksums } = SNAP_TEMPLATES[templateArch];
|
||||
builder_util_1.log.info({ releaseName }, "downloading snap template");
|
||||
const templateDir = await (0, electronGet_1.downloadBuilderToolset)({ releaseName, filenameWithExt, checksums, githubOrgRepo: "electron-userland/electron-builder-binaries" });
|
||||
await this.stageSnapFiles({ stageDir, appOutDir, hooksDir, extraAppArgs, isTemplate: true });
|
||||
// Best-effort: remove chrome-sandbox from app dir before mksquashfs scans it.
|
||||
await (0, promises_1.rm)(path.join(appOutDir, "chrome-sandbox"), { force: true });
|
||||
// chmod -R g-s to avoid setgid bits in final image
|
||||
for (const dir of [stageDir, appOutDir, templateDir]) {
|
||||
await (0, builder_util_1.exec)("chmod", ["-R", "g-s", dir]).catch(err => builder_util_1.log.warn({ error: err.message }, "chmod g-s failed"));
|
||||
}
|
||||
const mksquashfsPath = await getMksquashfsPath(snapArch);
|
||||
// Collect top-level entries from each dir as individual path args (mirrors Go ReadDirContentTo)
|
||||
const mksquashfsArgs = [
|
||||
...(await readDirPaths(templateDir)),
|
||||
...(await readDirPaths(stageDir)),
|
||||
...(await readDirPaths(appOutDir, name => name !== "LICENSES.chromium.html" && name !== "LICENSE.electron.txt" && name !== "chrome-sandbox")),
|
||||
artifactPath,
|
||||
"-no-progress",
|
||||
"-quiet",
|
||||
"-noappend",
|
||||
"-comp",
|
||||
compression,
|
||||
"-no-xattrs",
|
||||
"-no-fragments",
|
||||
"-all-root",
|
||||
];
|
||||
await (0, builder_util_1.exec)(mksquashfsPath, mksquashfsArgs, { cwd: stageDir });
|
||||
}
|
||||
async buildWithoutTemplate(opts) {
|
||||
const { appOutDir, stageDir, artifactPath, hooksDir, extraAppArgs } = opts;
|
||||
await this.stageSnapFiles({ stageDir, appOutDir, hooksDir, extraAppArgs, isTemplate: false });
|
||||
// Write desktop integration scripts (embedded in the Go binary, now in our templates)
|
||||
const snapTemplateDir = (0, pathManager_1.getTemplatePath)("snap");
|
||||
for (const script of ["desktop-init.sh", "desktop-common.sh", "desktop-gnome-specific.sh"]) {
|
||||
const src = path.join(snapTemplateDir, script);
|
||||
const dest = path.join(stageDir, "scripts", script);
|
||||
await (0, promises_1.copyFile)(src, dest);
|
||||
// copyFile doesn't preserve mode; chmod 755 explicitly
|
||||
await (0, promises_1.chmod)(dest, 0o755);
|
||||
}
|
||||
// Copy app dir into stage/app/ so snapcraft can pick it up
|
||||
await (0, builder_util_1.copyDir)(appOutDir, path.join(stageDir, "app"));
|
||||
// Run snapcraft (legacy `snap` subcommand)
|
||||
const isDestructiveMode = process.env.SNAP_DESTRUCTIVE_MODE === "true";
|
||||
const snapOutputName = "out.snap";
|
||||
const snapArgs = ["snap", "--output", isDestructiveMode ? artifactPath : snapOutputName];
|
||||
if (isDestructiveMode) {
|
||||
snapArgs.push("--destructive-mode");
|
||||
}
|
||||
await (0, builder_util_1.exec)("snapcraft", snapArgs, {
|
||||
cwd: stageDir,
|
||||
env: { ...process.env, SNAPCRAFT_HAS_TTY: "false" },
|
||||
});
|
||||
if (!isDestructiveMode) {
|
||||
await (0, promises_1.rename)(path.join(stageDir, snapOutputName), artifactPath);
|
||||
}
|
||||
}
|
||||
async stageSnapFiles(opts) {
|
||||
const { stageDir, hooksDir, extraAppArgs, isTemplate } = opts;
|
||||
const snapMetaDir = path.join(stageDir, isTemplate ? "meta" : "snap");
|
||||
// No-template builds place command.sh + desktop scripts in scripts/ which snapcraft stages to snap root.
|
||||
// Template builds write command.sh to the stage root directly; no scripts/ dir is needed.
|
||||
const scriptDir = path.join(stageDir, "scripts");
|
||||
if (!isTemplate) {
|
||||
await (0, promises_1.mkdir)(scriptDir, { recursive: true });
|
||||
}
|
||||
if (this.helper.maxIconPath != null) {
|
||||
const iconDest = path.join(snapMetaDir, "gui", `icon${path.extname(this.helper.maxIconPath)}`);
|
||||
await (0, promises_1.mkdir)(path.dirname(iconDest), { recursive: true });
|
||||
await (0, promises_1.copyFile)(this.helper.maxIconPath, iconDest);
|
||||
}
|
||||
if (hooksDir != null) {
|
||||
await (0, builder_util_1.copyDir)(hooksDir, path.join(snapMetaDir, "hooks"));
|
||||
}
|
||||
// command.sh — template builds write to stage root; no-template writes to scripts/
|
||||
const commandWrapperPath = isTemplate ? path.join(stageDir, "command.sh") : path.join(scriptDir, "command.sh");
|
||||
const commandContent = buildCommandShContent({ isTemplate, executableName: this.packager.executableName, extraAppArgs });
|
||||
await (0, promises_1.writeFile)(commandWrapperPath, commandContent, { mode: 0o755 });
|
||||
await (0, promises_1.chmod)(commandWrapperPath, 0o755);
|
||||
}
|
||||
normalizePlugConfiguration(raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
const result = {};
|
||||
for (const item of Array.isArray(raw) ? raw : [raw]) {
|
||||
if (typeof item === "string") {
|
||||
if (!(0, builder_util_runtime_1.isValidKey)(item)) {
|
||||
throw new Error(`Invalid plug/slot name: ${item}`);
|
||||
}
|
||||
result[item] = null;
|
||||
}
|
||||
else {
|
||||
(0, builder_util_runtime_1.deepAssign)(result, item);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
isBrowserSandboxAllowed(snap) {
|
||||
if (snap.plugs != null) {
|
||||
for (const plugName of Object.keys(snap.plugs)) {
|
||||
const plug = snap.plugs[plugName];
|
||||
if (plug.interface === "browser-support" && plug["allow-sandbox"] === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
archNameToTriplet(arch) {
|
||||
switch (arch) {
|
||||
case builder_util_1.Arch.x64:
|
||||
return "x86_64-linux-gnu";
|
||||
case builder_util_1.Arch.ia32:
|
||||
return "i386-linux-gnu";
|
||||
case builder_util_1.Arch.armv7l:
|
||||
return "arm-linux-gnueabihf";
|
||||
case builder_util_1.Arch.arm64:
|
||||
return "aarch64-linux-gnu";
|
||||
default:
|
||||
throw new Error(`Unsupported arch ${arch}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.SnapCoreLegacy = SnapCoreLegacy;
|
||||
async function getMksquashfsPath(arch) {
|
||||
const envPath = process.env.MKSQUASHFS_PATH;
|
||||
if (envPath) {
|
||||
return envPath;
|
||||
}
|
||||
const { mksquashfs } = await (0, linux_1.getAppImageTools)("0.0.0", arch);
|
||||
return mksquashfs;
|
||||
}
|
||||
async function readDirPaths(dir, filter) {
|
||||
const entries = await (0, promises_1.readdir)(dir);
|
||||
const result = [];
|
||||
for (const name of entries) {
|
||||
if (!filter || filter(name)) {
|
||||
result.push(path.join(dir, name));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/** Single-quote a shell argument, escaping any embedded single quotes. */
|
||||
function shellQuote(arg) {
|
||||
return "'" + arg.replace(/'/g, "'\\''") + "'";
|
||||
}
|
||||
/**
|
||||
* Builds the content of command.sh for a snap package.
|
||||
*
|
||||
* For both template and no-template builds, the desktop-integration scripts are
|
||||
* sourced from the snap root ($SNAP):
|
||||
* - Template: scripts are embedded in the template tarball at the snap root.
|
||||
* - No-template: the snapcraft.yaml `launch-scripts` part uses `plugin: dump,
|
||||
* source: scripts`, which stages stageDir/scripts/ contents directly into the
|
||||
* snap root — so $SNAP/desktop-init.sh is correct in both cases.
|
||||
*
|
||||
* The only difference between template and no-template is the app executable prefix:
|
||||
* template apps are at $SNAP/<name>; no-template apps are at $SNAP/app/<name>.
|
||||
*/
|
||||
function buildCommandShContent(opts) {
|
||||
const { isTemplate, executableName, extraAppArgs } = opts;
|
||||
(0, LibUiFramework_1.validateShellEmbeddable)(executableName, "executableName");
|
||||
const appPrefix = isTemplate ? "" : "app/";
|
||||
let content = `#!/bin/bash -e\nexec "$SNAP/desktop-init.sh" "$SNAP/desktop-common.sh" "$SNAP/desktop-gnome-specific.sh" "$SNAP/${appPrefix}${executableName}"`;
|
||||
if (extraAppArgs.length > 0) {
|
||||
content += " " + extraAppArgs.map(shellQuote).join(" ");
|
||||
}
|
||||
content += ' "$@"';
|
||||
return content;
|
||||
}
|
||||
//# sourceMappingURL=coreLegacy.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/targets/snap/coreLegacy.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/targets/snap/coreLegacy.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
39
electron/node_modules/app-builder-lib/out/targets/snap/snapcraftBuilder.d.ts
generated
vendored
Normal file
39
electron/node_modules/app-builder-lib/out/targets/snap/snapcraftBuilder.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { LinuxPackager } from "../../linuxPackager";
|
||||
import { RemoteBuildOptions } from "../../options/SnapOptions";
|
||||
import { SnapcraftYAML } from "./snapcraft";
|
||||
export declare const SNAPCRAFT_YAML_OPTIONS: {
|
||||
readonly indent: 2;
|
||||
readonly lineWidth: -1;
|
||||
readonly noRefs: true;
|
||||
};
|
||||
export declare const DEFAULT_STAGE_PACKAGES: string[];
|
||||
interface BuildSnapOptions {
|
||||
/** The snapcraft YAML configuration */
|
||||
snapcraftConfig: SnapcraftYAML;
|
||||
/** Working directory where snapcraft.yaml is written and the build executes */
|
||||
stageDir: string;
|
||||
/** Whether to use remote build (builds on Launchpad) */
|
||||
remoteBuild?: RemoteBuildOptions;
|
||||
/** Whether to use LXD for local builds */
|
||||
useLXD?: boolean;
|
||||
/** Whether to use Multipass for local builds */
|
||||
useMultipass?: boolean;
|
||||
/** Whether to use destructive mode (builds directly on host, Linux only) */
|
||||
useDestructiveMode?: boolean;
|
||||
/** The snap output path */
|
||||
artifactPath: string;
|
||||
/** LinuxPackager instance, used to resolve workspace dir for remote build authentication */
|
||||
packager: LinuxPackager;
|
||||
/** Snap Store credentials from SnapcraftOptions root — base64 string or file path */
|
||||
cscLink?: string;
|
||||
}
|
||||
/**
|
||||
* Builds a snap package from SnapcraftYAML configuration.
|
||||
*
|
||||
* `SNAPCRAFT_NO_NETWORK` is intentionally **not** forced to `"1"` here.
|
||||
* All build modes (destructive-mode, LXD, Multipass, remote) require network
|
||||
* access to download stage-packages, the base image, and extensions.
|
||||
* To opt into an offline build, set `SNAPCRAFT_NO_NETWORK=1` in your environment.
|
||||
*/
|
||||
export declare function buildSnap(options: BuildSnapOptions): Promise<string>;
|
||||
export {};
|
||||
419
electron/node_modules/app-builder-lib/out/targets/snap/snapcraftBuilder.js
generated
vendored
Normal file
419
electron/node_modules/app-builder-lib/out/targets/snap/snapcraftBuilder.js
generated
vendored
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DEFAULT_STAGE_PACKAGES = exports.SNAPCRAFT_YAML_OPTIONS = void 0;
|
||||
exports.buildSnap = buildSnap;
|
||||
const builder_util_1 = require("builder-util");
|
||||
const childProcess = require("child_process");
|
||||
const crypto_1 = require("crypto");
|
||||
const electron_publish_1 = require("electron-publish");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path = require("path");
|
||||
const util = require("util");
|
||||
const builder_util_runtime_1 = require("builder-util-runtime");
|
||||
const execAsync = util.promisify(childProcess.exec);
|
||||
exports.SNAPCRAFT_YAML_OPTIONS = { indent: 2, lineWidth: -1, noRefs: true };
|
||||
exports.DEFAULT_STAGE_PACKAGES = ["libnspr4", "libnss3", "libxss1", "libappindicator3-1", "libsecret-1-0"];
|
||||
/**
|
||||
* Validates snapcraft.yaml using snapcraft's built-in `expand-extensions` command.
|
||||
* Throws on failure. The caller in `buildSnap` catches this and treats it as a non-fatal warning.
|
||||
*/
|
||||
async function validateSnapcraftYamlWithCLI(workDir) {
|
||||
try {
|
||||
const { stdout } = await execAsync("snapcraft expand-extensions", {
|
||||
cwd: workDir,
|
||||
timeout: 30000,
|
||||
});
|
||||
builder_util_1.log.debug({ expandedYaml: stdout }, "validated extended snapcraft.yaml");
|
||||
}
|
||||
catch (error) {
|
||||
builder_util_1.log.error({ error: error.message, stderr: error.stderr }, "snapcraft.yaml validation failed");
|
||||
throw new Error(`Invalid snapcraft.yaml: ${error.message}\n` +
|
||||
`Snapcraft output: ${error.stderr || error.stdout || "No output"}\n` +
|
||||
`Run 'snapcraft expand-extensions' in ${workDir} for more details`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Validates snapcraft.yaml configuration with basic client-side checks
|
||||
* This is a fast pre-check before running the full CLI validation
|
||||
*/
|
||||
function validateSnapcraftConfig(config) {
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
// Required fields
|
||||
if (!config.name) {
|
||||
errors.push("name is required");
|
||||
}
|
||||
if (!config.base) {
|
||||
errors.push("base is required");
|
||||
}
|
||||
if (!config.confinement) {
|
||||
errors.push("confinement is required");
|
||||
}
|
||||
if (!config.parts || Object.keys(config.parts).length === 0) {
|
||||
errors.push("at least one part is required");
|
||||
}
|
||||
// Name validation
|
||||
if (config.name) {
|
||||
if (!/^[a-z0-9-]*$/.test(config.name)) {
|
||||
errors.push("name must only contain lowercase letters, numbers, and hyphens");
|
||||
}
|
||||
if (config.name.length > 40) {
|
||||
errors.push("name must be 40 characters or less");
|
||||
}
|
||||
if (config.name.startsWith("-") || config.name.endsWith("-")) {
|
||||
errors.push("name cannot start or end with a hyphen");
|
||||
}
|
||||
}
|
||||
// Parts validation
|
||||
Object.entries(config.parts).forEach(([partName, part]) => {
|
||||
if (!part.plugin) {
|
||||
errors.push(`part '${partName}' missing required 'plugin' field`);
|
||||
}
|
||||
});
|
||||
// Apps validation
|
||||
if (config.apps) {
|
||||
Object.entries(config.apps).forEach(([appName, app]) => {
|
||||
if (!app.command) {
|
||||
errors.push(`app '${appName}' missing required 'command' field`);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Summary validation
|
||||
if (config.summary && config.summary.length > 78) {
|
||||
warnings.push(`summary is ${config.summary.length} characters (recommended: 78 or less)`);
|
||||
}
|
||||
// Log results
|
||||
if (errors.length > 0) {
|
||||
builder_util_1.log.error({ errors }, "snapcraft.yaml validation failed");
|
||||
throw new builder_util_1.InvalidConfigurationError(`Invalid snapcraft.yaml: ${errors.join(", ")}`);
|
||||
}
|
||||
if (warnings.length > 0) {
|
||||
builder_util_1.log.warn({ warnings }, "snapcraft.yaml validation warnings");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Retry wrapper for operations that may fail transiently
|
||||
*/
|
||||
async function executeWithRetry(fn, options = {}) {
|
||||
var _a;
|
||||
const { maxRetries = 3, retryDelay = 5000, retryableErrors = ["network timeout", "connection refused", "temporary failure", "snap store error"] } = options;
|
||||
let lastError;
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
return await fn();
|
||||
}
|
||||
catch (error) {
|
||||
lastError = error;
|
||||
const errorMessage = ((_a = error.message) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "";
|
||||
const isRetryable = retryableErrors.some(pattern => errorMessage.includes(pattern));
|
||||
if (attempt < maxRetries && isRetryable) {
|
||||
builder_util_1.log.warn({ attempt, maxRetries, error: error.message, retryIn: retryDelay }, "build failed with retryable error, retrying...");
|
||||
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw lastError;
|
||||
}
|
||||
/**
|
||||
* Cleans up build artifacts
|
||||
*/
|
||||
async function cleanupBuildArtifacts(workDir) {
|
||||
const artifactsToClean = ["parts", "stage", "prime"];
|
||||
for (const artifact of artifactsToClean) {
|
||||
const artifactPath = path.join(workDir, artifact);
|
||||
try {
|
||||
await (0, fs_extra_1.remove)(artifactPath);
|
||||
builder_util_1.log.debug({ artifact }, "cleaned build artifact");
|
||||
}
|
||||
catch (e) {
|
||||
builder_util_1.log.debug({ artifact, error: e.message }, "no build artifact to clean");
|
||||
}
|
||||
}
|
||||
try {
|
||||
const files = await (0, fs_extra_1.readdir)(workDir);
|
||||
for (const file of files) {
|
||||
if (file.endsWith(".snap")) {
|
||||
await (0, fs_extra_1.remove)(path.join(workDir, file));
|
||||
builder_util_1.log.debug({ file }, "cleaned snap file");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
builder_util_1.log.debug({ error: e.message }, "no snap files to clean");
|
||||
}
|
||||
}
|
||||
async function copySnapToArtifactPath(workDir, outputBasename, outputFileName) {
|
||||
const snapInWorkDir = path.join(workDir, outputBasename);
|
||||
if (snapInWorkDir !== outputFileName) {
|
||||
await (0, fs_extra_1.ensureDir)(path.dirname(outputFileName));
|
||||
await (0, fs_extra_1.copyFile)(snapInWorkDir, outputFileName);
|
||||
builder_util_1.log.debug({ from: snapInWorkDir, to: outputFileName }, "copied snap from build dir to artifact path");
|
||||
}
|
||||
return outputFileName;
|
||||
}
|
||||
/**
|
||||
* Builds a snap package from SnapcraftYAML configuration.
|
||||
*
|
||||
* `SNAPCRAFT_NO_NETWORK` is intentionally **not** forced to `"1"` here.
|
||||
* All build modes (destructive-mode, LXD, Multipass, remote) require network
|
||||
* access to download stage-packages, the base image, and extensions.
|
||||
* To opt into an offline build, set `SNAPCRAFT_NO_NETWORK=1` in your environment.
|
||||
*/
|
||||
async function buildSnap(options) {
|
||||
const { SNAPCRAFT_NO_NETWORK } = process.env;
|
||||
const { snapcraftConfig, artifactPath, remoteBuild, stageDir, useLXD = false, useMultipass = false, useDestructiveMode = false, cscLink } = options;
|
||||
const isolatedEnv = {
|
||||
...(SNAPCRAFT_NO_NETWORK != null ? { SNAPCRAFT_NO_NETWORK } : {}),
|
||||
};
|
||||
if (useDestructiveMode) {
|
||||
isolatedEnv.SNAPCRAFT_BUILD_ENVIRONMENT = "host";
|
||||
}
|
||||
if (useLXD && process.platform !== "linux") {
|
||||
throw new builder_util_1.InvalidConfigurationError(`useLXD is only supported on Linux. On ${process.platform}, use useMultipass or remoteBuild instead.`);
|
||||
}
|
||||
if (useDestructiveMode && process.platform !== "linux") {
|
||||
throw new builder_util_1.InvalidConfigurationError(`useDestructiveMode is only supported on Linux (requires Ubuntu 24.04 host for core24). On ${process.platform}, use useMultipass or remoteBuild instead.`);
|
||||
}
|
||||
// Config validation — throws InvalidConfigurationError, no build artifacts exist yet.
|
||||
validateSnapcraftConfig(snapcraftConfig);
|
||||
try {
|
||||
await validateSnapcraftYamlWithCLI(stageDir);
|
||||
}
|
||||
catch (validationError) {
|
||||
builder_util_1.log.warn({ error: validationError.message }, "snapcraft CLI pre-validation failed (non-fatal), continuing build");
|
||||
}
|
||||
await ensureSnapcraftInstalled();
|
||||
// Inject credentials for all build modes from snapcraft.cscLink / SNAP_CSC_LINK.
|
||||
const credEnv = await (0, electron_publish_1.resolveSnapCredentials)(cscLink, options.packager.buildResourcesDir);
|
||||
(0, builder_util_runtime_1.deepAssign)(isolatedEnv, credEnv);
|
||||
if (remoteBuild === null || remoteBuild === void 0 ? void 0 : remoteBuild.enabled) {
|
||||
// Remote-build auth does additional checks (interactive session, throws on missing creds)
|
||||
// and overrides any credential already set above.
|
||||
const authEnv = await ensureRemoteBuildAuthentication(cscLink, options.packager.buildResourcesDir);
|
||||
(0, builder_util_runtime_1.deepAssign)(isolatedEnv, authEnv);
|
||||
}
|
||||
const projectAppDir = path.join(stageDir, "app");
|
||||
if (!(await (0, fs_extra_1.pathExists)(projectAppDir))) {
|
||||
throw new builder_util_1.InvalidConfigurationError(`snap build failed: expected app directory not found at ${projectAppDir}`);
|
||||
}
|
||||
builder_util_1.log.debug({ appFiles: (await (0, fs_extra_1.readdir)(projectAppDir)).slice(0, 20) }, "app directory contents (truncated)");
|
||||
if (!(remoteBuild === null || remoteBuild === void 0 ? void 0 : remoteBuild.enabled) && !useLXD && !useMultipass && !useDestructiveMode && process.platform !== "linux") {
|
||||
throw new builder_util_1.InvalidConfigurationError(`No snap build environment specified for ${process.platform}. Set one of: useMultipass, useLXD (Linux only), useDestructiveMode (Linux only), or remoteBuild.enabled`);
|
||||
}
|
||||
// Actual build — only this step can leave partial artifacts that need cleanup.
|
||||
try {
|
||||
return await executeWithRetry(() => executeSnapcraftBuild({
|
||||
workDir: stageDir,
|
||||
remoteBuild,
|
||||
outputSnap: artifactPath,
|
||||
useLXD,
|
||||
useMultipass,
|
||||
useDestructiveMode,
|
||||
isolatedEnv: isolatedEnv,
|
||||
}), { maxRetries: (remoteBuild === null || remoteBuild === void 0 ? void 0 : remoteBuild.enabled) ? 3 : 1, retryDelay: 10000 });
|
||||
}
|
||||
catch (error) {
|
||||
builder_util_1.log.error({ error: error.message }, "snap build failed");
|
||||
await cleanupBuildArtifacts(stageDir).catch((cleanupError) => {
|
||||
builder_util_1.log.warn({ error: cleanupError.message }, "failed to cleanup build artifacts");
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Ensures snapcraft is installed on the system
|
||||
*/
|
||||
async function ensureSnapcraftInstalled() {
|
||||
try {
|
||||
const { stdout } = await execAsync("snapcraft --version");
|
||||
builder_util_1.log.info({ version: stdout.trim() }, "snapcraft found");
|
||||
}
|
||||
catch (error) {
|
||||
builder_util_1.log.error({ error: error.message }, "snapcraft is not installed");
|
||||
const platform = process.platform;
|
||||
if (platform === "linux") {
|
||||
builder_util_1.log.error(null, "Install with: sudo snap install snapcraft --classic");
|
||||
}
|
||||
else if (platform === "darwin") {
|
||||
builder_util_1.log.error(null, "Install snapcraft with: pip3 install snapcraft");
|
||||
builder_util_1.log.error(null, "On macOS, useMultipass or remoteBuild are the only supported build modes for core24");
|
||||
}
|
||||
else if (platform === "win32") {
|
||||
builder_util_1.log.error(null, "Install snapcraft via WSL2 or use remote-build");
|
||||
builder_util_1.log.error(null, "See: https://snapcraft.io/docs/snapcraft-overview");
|
||||
}
|
||||
throw new builder_util_1.InvalidConfigurationError("snapcraft not found - please install snapcraft to continue");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Resolves Snapcraft Store authentication for remote builds and returns the credential
|
||||
* env entries to inject. Returns an empty map when snapcraft can authenticate itself
|
||||
* (interactive session). Throws when no credential source is found.
|
||||
*/
|
||||
async function ensureRemoteBuildAuthentication(cscLink, resourcesDir) {
|
||||
var _a;
|
||||
builder_util_1.log.debug(null, "resolving remote build authentication...");
|
||||
// 1. snapcraft.cscLink / SNAP_CSC_LINK — config-level or env credential (base64 or file path).
|
||||
// resolveSnapCredentials already ran for all build modes; re-run here so remote-build
|
||||
// gets the same result and the interactive-session fallback is only reached when neither is set.
|
||||
const credEnv = await (0, electron_publish_1.resolveSnapCredentials)(cscLink, resourcesDir);
|
||||
if (Object.keys(credEnv).length > 0) {
|
||||
return credEnv;
|
||||
}
|
||||
// 2. SNAPCRAFT_STORE_CREDENTIALS env var — directly provide the credentials string (not base64-encoded).
|
||||
const SNAPCRAFT_STORE_CREDENTIALS = (_a = process.env.SNAPCRAFT_STORE_CREDENTIALS) === null || _a === void 0 ? void 0 : _a.trim();
|
||||
if (!(0, builder_util_1.isEmptyOrSpaces)(SNAPCRAFT_STORE_CREDENTIALS)) {
|
||||
builder_util_1.log.debug(null, "using SNAPCRAFT_STORE_CREDENTIALS from environment, verbatim");
|
||||
return { SNAPCRAFT_STORE_CREDENTIALS };
|
||||
}
|
||||
// 3. Interactive snapcraft session.
|
||||
try {
|
||||
const { stdout } = await execAsync("snapcraft whoami");
|
||||
if (stdout.includes("email:")) {
|
||||
builder_util_1.log.debug({ account: stdout.trim() }, "already authenticated with snapcraft");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// Not logged in, fall through to error.
|
||||
}
|
||||
throw new builder_util_1.InvalidConfigurationError("Snapcraft authentication required for remote build.\n" +
|
||||
"Authenticate with one of any:\n" +
|
||||
" 1. Set SNAP_CSC_LINK\n" +
|
||||
" 2. Set snapcraft.cscLink in your build config\n" +
|
||||
" 3. Run: snapcraft login\n" +
|
||||
" 4. Set SNAPCRAFT_STORE_CREDENTIALS environment variable directly");
|
||||
}
|
||||
/**
|
||||
* Executes the snapcraft build command
|
||||
*/
|
||||
async function executeSnapcraftBuild(options) {
|
||||
const { workDir, outputSnap: outputFileName, remoteBuild, useLXD, useMultipass, useDestructiveMode, isolatedEnv } = options;
|
||||
let processedEnv = { ...(0, builder_util_1.stripSensitiveEnvVars)(process.env), ...isolatedEnv };
|
||||
// Use a UUID-based temp name as the --output target so the copy below doesn't
|
||||
// depend on snapcraft's naming convention (which always uses underscores).
|
||||
const tmpSnap = `eb-snap-${(0, crypto_1.randomUUID)().replace(/-/g, "")}.snap`;
|
||||
if (useDestructiveMode && !(remoteBuild === null || remoteBuild === void 0 ? void 0 : remoteBuild.enabled)) {
|
||||
return await runDestructiveBuild(workDir, processedEnv, tmpSnap, outputFileName);
|
||||
}
|
||||
const command = "snapcraft";
|
||||
const args = [];
|
||||
if (remoteBuild === null || remoteBuild === void 0 ? void 0 : remoteBuild.enabled) {
|
||||
const remoteBuildArgs = generateRemoteBuildArgs(remoteBuild, workDir);
|
||||
// Remote build on Launchpad (works from any platform)
|
||||
args.push(...remoteBuildArgs.args);
|
||||
processedEnv = { ...processedEnv, ...remoteBuildArgs.isolatedEnv };
|
||||
}
|
||||
else {
|
||||
// `snapcraft pack` runs the full lifecycle (pull → build → stage → prime → pack).
|
||||
// snapcraft 8.x removed --use-multipass entirely; Multipass is now configured
|
||||
// via the SNAPCRAFT_BUILD_ENVIRONMENT env var (or auto-selected on macOS).
|
||||
// --use-lxd remains a supported CLI flag on `pack`.
|
||||
args.push("pack");
|
||||
if (useLXD) {
|
||||
args.push("--use-lxd");
|
||||
builder_util_1.log.debug(null, "using LXD for build");
|
||||
}
|
||||
else if (useMultipass) {
|
||||
processedEnv.SNAPCRAFT_BUILD_ENVIRONMENT = "multipass";
|
||||
builder_util_1.log.debug(null, "using Multipass for build (via SNAPCRAFT_BUILD_ENVIRONMENT)");
|
||||
}
|
||||
else {
|
||||
args.push("--output", tmpSnap);
|
||||
}
|
||||
}
|
||||
if (builder_util_1.log.isDebugEnabled) {
|
||||
args.push("--verbose");
|
||||
}
|
||||
builder_util_1.log.info({ workDir: builder_util_1.log.filePath(workDir) }, "executing snapcraft");
|
||||
await (0, builder_util_1.spawn)(command, args, {
|
||||
cwd: workDir,
|
||||
env: processedEnv,
|
||||
});
|
||||
if ((remoteBuild === null || remoteBuild === void 0 ? void 0 : remoteBuild.enabled) || useLXD || useMultipass) {
|
||||
// snapcraft names the output snap itself (e.g. <name>_<version>_<arch>.snap).
|
||||
// Each electron-builder build invocation targets exactly one arch, so exactly one snap is expected.
|
||||
const files = await (0, fs_extra_1.readdir)(workDir);
|
||||
const builtSnap = files.find(f => f.endsWith(".snap"));
|
||||
if (!builtSnap) {
|
||||
throw new Error(`Build succeeded but no .snap file found in ${workDir}`);
|
||||
}
|
||||
return copySnapToArtifactPath(workDir, builtSnap, outputFileName);
|
||||
}
|
||||
return copySnapToArtifactPath(workDir, tmpSnap, outputFileName);
|
||||
}
|
||||
function generateRemoteBuildArgs(remoteBuild, workDir) {
|
||||
const isolatedEnv = {};
|
||||
const args = ["remote-build"];
|
||||
builder_util_1.log.debug(null, "using remote-build (Launchpad)");
|
||||
// Add remote build specific options
|
||||
if (remoteBuild.launchpadUsername) {
|
||||
args.push("--user", remoteBuild.launchpadUsername);
|
||||
}
|
||||
if (remoteBuild.acceptPublicUpload) {
|
||||
args.push("--launchpad-accept-public-upload");
|
||||
}
|
||||
else {
|
||||
builder_util_1.log.warn(null, "your project will be publicly uploaded to Launchpad. Use `acceptPublicUpload: true` to suppress this warning");
|
||||
}
|
||||
if (remoteBuild.privateProject) {
|
||||
args.push("--project", remoteBuild.privateProject);
|
||||
builder_util_1.log.debug({ project: remoteBuild.privateProject }, "using private Launchpad project");
|
||||
}
|
||||
if (remoteBuild.buildFor) {
|
||||
args.push("--build-for", remoteBuild.buildFor);
|
||||
builder_util_1.log.debug({ arch: remoteBuild.buildFor }, "building for architecture");
|
||||
}
|
||||
if (remoteBuild.recover) {
|
||||
args.push("--recover");
|
||||
builder_util_1.log.debug(null, "recovering previous build");
|
||||
}
|
||||
if (remoteBuild.strategy) {
|
||||
isolatedEnv.SNAPCRAFT_REMOTE_BUILD_STRATEGY = remoteBuild.strategy;
|
||||
}
|
||||
if (remoteBuild.timeout) {
|
||||
args.push("--timeout", String(remoteBuild.timeout));
|
||||
builder_util_1.log.debug({ timeout: `${remoteBuild.timeout}s` }, "build timeout configured");
|
||||
}
|
||||
// Remote-build downloads the finished snap into workDir.
|
||||
// --output-dir (not --output <file>) lets snapcraft name the file itself.
|
||||
args.push("--output-dir", workDir);
|
||||
return { args, isolatedEnv };
|
||||
}
|
||||
// Snapcraft 8 (craft-application) hangs after a successful destructive-mode
|
||||
// build in containerised environments (Docker/CI without snapd running).
|
||||
// craft-application's PackageService teardown tries to reach
|
||||
// /run/snapd-snap.socket (snapctl IPC) which doesn't exist without a live
|
||||
// snapd daemon — causing an indefinite block.
|
||||
//
|
||||
// Work-around: split into two steps:
|
||||
// 1. `snapcraft prime --destructive-mode` — runs pull/build/stage/prime,
|
||||
// exits cleanly (no post-pack teardown executed).
|
||||
// 2. `snapcraft pack <primeDir>` — packs the pre-primed directory without
|
||||
// running the full build lifecycle, avoiding the problematic teardown.
|
||||
async function runDestructiveBuild(workDir, processedEnv, tmpSnap, outputFileName) {
|
||||
const primeArgs = ["prime", "--destructive-mode"];
|
||||
if (builder_util_1.log.isDebugEnabled) {
|
||||
primeArgs.push("--verbose");
|
||||
}
|
||||
builder_util_1.log.info({ command: `snapcraft ${primeArgs.join(" ")}`, workDir: builder_util_1.log.filePath(workDir) }, "snapcraft prime (1/2)");
|
||||
await (0, builder_util_1.spawn)("snapcraft", primeArgs, {
|
||||
cwd: workDir,
|
||||
env: processedEnv,
|
||||
});
|
||||
const primeDir = path.join(workDir, "prime");
|
||||
const snapcraftPackArgs = ["pack", "--output", tmpSnap, primeDir];
|
||||
if (builder_util_1.log.isDebugEnabled) {
|
||||
snapcraftPackArgs.push("--verbose");
|
||||
}
|
||||
builder_util_1.log.info({ command: `snapcraft ${snapcraftPackArgs.join(" ")}`, workDir: builder_util_1.log.filePath(workDir) }, "snapcraft pack prime dir (2/2)");
|
||||
await (0, builder_util_1.spawn)("snapcraft", snapcraftPackArgs, {
|
||||
cwd: workDir,
|
||||
env: processedEnv,
|
||||
});
|
||||
return copySnapToArtifactPath(workDir, tmpSnap, outputFileName);
|
||||
}
|
||||
//# sourceMappingURL=snapcraftBuilder.js.map
|
||||
1
electron/node_modules/app-builder-lib/out/targets/snap/snapcraftBuilder.js.map
generated
vendored
Normal file
1
electron/node_modules/app-builder-lib/out/targets/snap/snapcraftBuilder.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue