@rightkit/release 0.2.173 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -5
- package/bin/darwin/rightkit-swap +0 -0
- package/bin/darwin/rightkit-swap.sign.json +1 -1
- package/cli/right-release.mjs +34 -6
- package/command-spec.mjs +80 -0
- package/deps-cargo.mjs +55 -0
- package/deps.mjs +7 -0
- package/development-signing.mjs +135 -4
- package/development.mjs +12 -11
- package/dist-scan.mjs +102 -0
- package/dmg-build.mjs +53 -4
- package/icon-pack.mjs +117 -0
- package/in-place-install.mjs +32 -7
- package/init-command.mjs +116 -0
- package/install-app-windows.mjs +108 -17
- package/install-app.mjs +68 -11
- package/install-tauri-devid.mjs +106 -47
- package/local-publish.mjs +317 -29
- package/mac-bundle-signing.mjs +143 -1
- package/mac-signing-matrix.mjs +73 -6
- package/macho-approval-hash.mjs +181 -0
- package/macos-signing-session.mjs +12 -2
- package/managed-cargo.mjs +49 -1
- package/media-sidecar.mjs +20 -4
- package/mirror-root-artifact.mjs +69 -21
- package/npm-license-notices.mjs +159 -0
- package/ownership-dependency-allowlist.json +1 -0
- package/ownership.mjs +37 -4
- package/package-recipe-targets.mjs +180 -16
- package/package.json +1 -1
- package/pe-content.mjs +133 -0
- package/portable-development.mjs +9 -9
- package/publication-gate.mjs +70 -3
- package/publish-cargo.mjs +26 -7
- package/qa-build-features.mjs +7 -1
- package/recipe-build.mjs +346 -0
- package/release-dependencies-command.mjs +45 -0
- package/release-dependencies.mjs +60 -0
- package/release-switch-scan.mjs +17 -7
- package/release.mjs +98 -12
- package/rightkit-ownership.json +46 -2
- package/rightkit-signing-agent.mjs +10 -4
- package/rightkit-versions.json +11 -6
- package/runtime-budgets.mjs +28 -12
- package/stage-binary.mjs +1 -1
- package/stage-sidecar-command.mjs +36 -4
- package/stage-sidecar.mjs +926 -74
- package/test-command.mjs +190 -0
- package/toolchain-swift.mjs +239 -0
- package/web-build.mjs +67 -0
package/install-tauri-devid.mjs
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Pipeline (installTauriDevId): copy the built .app to a private staging copy -> sign nested code, then the app,
|
|
5
5
|
// with the stable Developer ID (signMacosDevelopmentBundle) -> assert the designated requirement equals the
|
|
6
|
-
// installed copy's (assertStableDesignatedRequirement) -> install at the fixed path
|
|
7
|
-
// (installApp, dev mode) -> verify the installed copy; any verify failure
|
|
8
|
-
//
|
|
6
|
+
// installed copy's (assertStableDesignatedRequirement) -> install at the fixed path with NO backup of the old copy
|
|
7
|
+
// (installApp, dev mode; Orthic-Labs/rightkit#348) -> verify the installed copy; any verify failure removes the new
|
|
8
|
+
// copy and leaves the path absent (reinstall from an older DMG). Nothing ever creates `<dest>.previous`.
|
|
9
|
+
// resetTauriDevId removes the install, only when asked (mode "remove").
|
|
9
10
|
//
|
|
10
11
|
// Every external call (copy, sign, run, install, file system) is injectable through `deps`; the defaults are the
|
|
11
12
|
// real RightKit pieces. macOS paths are POSIX, so this module uses path.posix throughout.
|
|
@@ -14,9 +15,9 @@ import { cpSync, existsSync, mkdtempSync, readFileSync, renameSync, rmSync } fro
|
|
|
14
15
|
import os from "node:os";
|
|
15
16
|
import path from "node:path";
|
|
16
17
|
import { spawnSync } from "./background-process.mjs";
|
|
17
|
-
import { assertStableDesignatedRequirement, signMacosDevelopmentBundle } from "./development-signing.mjs";
|
|
18
|
+
import { assertSignedIdentities, assertStableDesignatedRequirement, readDevSigningSettings, signMacosDevelopmentBundle } from "./development-signing.mjs";
|
|
18
19
|
import { installApp } from "./install-app.mjs";
|
|
19
|
-
import { previousPathOf } from "./in-place-install.mjs";
|
|
20
|
+
import { previousPathOf } from "./in-place-install.mjs"; // only to clear a stale `.previous` an older RightKit left; never to create one
|
|
20
21
|
|
|
21
22
|
export const TAURI_DEVID_KIND = "tauri-devid";
|
|
22
23
|
|
|
@@ -39,6 +40,7 @@ export function defaultDeps() {
|
|
|
39
40
|
run: spawnSync,
|
|
40
41
|
sign: signMacosDevelopmentBundle,
|
|
41
42
|
assertRequirement: assertStableDesignatedRequirement,
|
|
43
|
+
assertIdentities: assertSignedIdentities,
|
|
42
44
|
installApp,
|
|
43
45
|
exists: existsSync,
|
|
44
46
|
makeTemp: () => mkdtempSync(P.join(os.tmpdir(), "rightkit-tauri-devid-")),
|
|
@@ -50,20 +52,84 @@ export function defaultDeps() {
|
|
|
50
52
|
};
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
const invalid = (message) => new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", message);
|
|
56
|
+
const SAME_IDENTITY_RULE = "dev builds use the SAME install path and bundle id as production (else permission issues), replaced in place with no backup copy; no separate .dev identity";
|
|
57
|
+
|
|
58
|
+
/** The tauri config file for a descriptor: `install.tauriConfig` (contained, relative to the app root) or `tauri.conf.json` beside the manifest. */
|
|
59
|
+
function tauriConfigPath(descriptor, appRoot) {
|
|
60
|
+
if (descriptor.tauriConfig !== undefined) return absolute(appRoot, descriptor.tauriConfig);
|
|
61
|
+
return absolute(appRoot, P.join(P.dirname(descriptor.manifestPath ?? "src-tauri/Cargo.toml"), "tauri.conf.json"));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** `{ productName?, identifier? }` from the tauri config, or null when it cannot be read or parsed. */
|
|
65
|
+
function readTauriConfig(descriptor, appRoot, readFile) {
|
|
66
|
+
try {
|
|
67
|
+
const parsed = JSON.parse(String(readFile(tauriConfigPath(descriptor, appRoot))));
|
|
68
|
+
const pick = (value) => (typeof value === "string" && value ? value : undefined);
|
|
69
|
+
return { productName: pick(parsed?.productName), identifier: pick(parsed?.identifier) };
|
|
70
|
+
} catch { return null; }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The `tauri-devid` descriptor, validated. Accepts the config root or the descriptor itself.
|
|
75
|
+
* Fail-closed on identity: the destination must be exactly `/Applications/<productName>.app`, where productName is the
|
|
76
|
+
* tauri.conf.json productName (install.productName must equal it) and, when the release config declares
|
|
77
|
+
* `targets.mac.notarize.app`, the basename of that app must agree. There is no other destination.
|
|
78
|
+
* With `readFile` (the install and reset paths) the tauri config must be readable (`tauri.conf.json` beside the manifest, or
|
|
79
|
+
* `install.tauriConfig`) or `install.bundleId` must be set explicitly; without it only the descriptor's shape is checked.
|
|
80
|
+
* `releaseConfig` is the release config root when `config` is the bare descriptor.
|
|
81
|
+
*/
|
|
82
|
+
export function resolveTauriDevIdDescriptor(config, { appRoot = "", readFile, releaseConfig } = {}) {
|
|
55
83
|
const descriptor = config?.development?.targets?.mac?.install ?? config;
|
|
56
84
|
if (!descriptor || descriptor.kind !== TAURI_DEVID_KIND) throw new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", `development.targets.mac.install.kind must be "${TAURI_DEVID_KIND}"`);
|
|
57
85
|
if (typeof descriptor.productName !== "string" || !descriptor.productName) throw new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", "install.productName is required");
|
|
58
86
|
if (typeof descriptor.destination !== "string" || !P.isAbsolute(descriptor.destination) || !descriptor.destination.endsWith(".app") || descriptor.destination.split("/").includes("..")) {
|
|
59
87
|
throw new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", "install.destination must be an absolute /…/<Product>.app path (the one fixed install path, for example /Applications/<Product>.app)");
|
|
60
88
|
}
|
|
61
|
-
if (descriptor.
|
|
89
|
+
if (descriptor.tauriConfig !== undefined && (typeof descriptor.tauriConfig !== "string" || !descriptor.tauriConfig || P.isAbsolute(descriptor.tauriConfig) || /^[A-Za-z]:/.test(descriptor.tauriConfig) || descriptor.tauriConfig.split(/[\/]/).includes("..") || !/\.json$/i.test(descriptor.tauriConfig))) {
|
|
90
|
+
throw invalid("install.tauriConfig must be a relative path to a .json file inside the app");
|
|
91
|
+
}
|
|
92
|
+
const destination = P.normalize(descriptor.destination);
|
|
93
|
+
const release = releaseConfig ?? (config?.development ? config : undefined);
|
|
94
|
+
const notarizeApp = release?.targets?.mac?.notarize?.app;
|
|
95
|
+
const notarizeName = typeof notarizeApp === "string" && notarizeApp.replaceAll("\\", "/").replace(/\/+$/, "").endsWith(".app") ? P.basename(notarizeApp.replaceAll("\\", "/").replace(/\/+$/, ""), ".app") : undefined;
|
|
96
|
+
if (readFile) {
|
|
97
|
+
const tauri = readTauriConfig(descriptor, appRoot, readFile);
|
|
98
|
+
if (!tauri && descriptor.tauriConfig !== undefined) throw invalid(`install.tauriConfig ${descriptor.tauriConfig} cannot be read or is not JSON; the production identity is read from it`);
|
|
99
|
+
if (!tauri && !descriptor.bundleId) throw invalid("cannot establish the production identity: tauri.conf.json (beside the manifest, or install.tauriConfig) is unreadable and install.bundleId is not set; set either so the install can be checked against it");
|
|
100
|
+
if (tauri?.productName !== undefined && tauri.productName !== descriptor.productName) throw invalid(`install.productName ${JSON.stringify(descriptor.productName)} differs from the tauri.conf.json productName ${JSON.stringify(tauri.productName)}: ${SAME_IDENTITY_RULE}`);
|
|
101
|
+
}
|
|
102
|
+
if (notarizeName !== undefined && notarizeName !== descriptor.productName) throw invalid(`install.productName ${JSON.stringify(descriptor.productName)} disagrees with targets.mac.notarize.app (${notarizeName}.app): ${SAME_IDENTITY_RULE}`);
|
|
103
|
+
if (destination !== `/Applications/${descriptor.productName}.app`) {
|
|
104
|
+
throw invalid(`install.destination ${destination} is not the production install path /Applications/${descriptor.productName}.app: ${SAME_IDENTITY_RULE}`);
|
|
105
|
+
}
|
|
106
|
+
for (const key of ["devIdentity", "refuseSystemApplications"]) {
|
|
107
|
+
if (descriptor[key] !== undefined) throw invalid(`install.${key} is not supported: ${SAME_IDENTITY_RULE}`);
|
|
108
|
+
}
|
|
109
|
+
if (descriptor.signing !== undefined) throw new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", `install.signing is not allowed for ${TAURI_DEVID_KIND}: ad hoc signing (signing: "-") changes the code identity every build and resets privacy grants; dev builds sign with the same Developer ID as release`);
|
|
62
110
|
const binaries = descriptor.verifyBinaries ?? [];
|
|
63
111
|
if (!Array.isArray(binaries) || binaries.some((item) => typeof item !== "string" || !item || P.isAbsolute(item) || item.split("/").includes(".."))) {
|
|
64
112
|
throw new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", "install.verifyBinaries must be relative paths inside the app, for example Contents/MacOS/<name>");
|
|
65
113
|
}
|
|
66
|
-
|
|
114
|
+
// Shape of the per-binary signing keys (identifiers, identifierTemplate, entitlements, timestamp, assert, assertTeamSignedNested).
|
|
115
|
+
try { readDevSigningSettings(descriptor, config?.development ? config : {}); }
|
|
116
|
+
catch (error) { throw new TauriDevIdError("TAURI_DEVID_CONFIG_INVALID", error.message); }
|
|
117
|
+
return { ...descriptor, destination, verifyBinaries: binaries, appRoot };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** The built .app's CFBundleIdentifier must equal the production identifier (tauri.conf.json, and install.bundleId when set). Fail-closed. */
|
|
121
|
+
function assertBuiltIdentity({ source, descriptor, appRoot, env, deps }) {
|
|
122
|
+
const production = readTauriConfig(descriptor, appRoot, deps.readFile)?.identifier ?? null;
|
|
123
|
+
if (descriptor.bundleId && production && descriptor.bundleId !== production) {
|
|
124
|
+
throw invalid(`install.bundleId ${descriptor.bundleId} differs from the tauri.conf.json identifier ${production}: ${SAME_IDENTITY_RULE}`);
|
|
125
|
+
}
|
|
126
|
+
const expected = production ?? descriptor.bundleId;
|
|
127
|
+
if (!expected) throw invalid(`no production bundle identifier: the tauri.conf.json identifier is unreadable and install.bundleId is not set, so the built app cannot be checked: ${SAME_IDENTITY_RULE}`);
|
|
128
|
+
const read = deps.run("/usr/bin/plutil", ["-extract", "CFBundleIdentifier", "raw", "-o", "-", P.join(source, "Contents", "Info.plist")], { cwd: appRoot, env, encoding: "utf8", windowsHide: true, shell: false });
|
|
129
|
+
const actual = read.error || read.status !== 0 ? null : String(read.stdout ?? "").trim();
|
|
130
|
+
if (actual !== expected) {
|
|
131
|
+
throw new TauriDevIdError("TAURI_DEVID_BUNDLE_ID_MISMATCH", `built ${source} CFBundleIdentifier ${actual === null ? "(unreadable)" : JSON.stringify(actual)} is not the production identifier ${JSON.stringify(expected)}: ${SAME_IDENTITY_RULE}`, { builtBundleId: actual, productionBundleId: expected });
|
|
132
|
+
}
|
|
67
133
|
}
|
|
68
134
|
|
|
69
135
|
const builtPathOf = (built, appRoot) => {
|
|
@@ -74,21 +140,7 @@ const builtPathOf = (built, appRoot) => {
|
|
|
74
140
|
|
|
75
141
|
const digestOf = (deps, file) => createHash("sha256").update(deps.readFile(file)).digest("hex");
|
|
76
142
|
|
|
77
|
-
|
|
78
|
-
function restorePrevious(destination, deps) {
|
|
79
|
-
const previous = previousPathOf(destination);
|
|
80
|
-
if (!deps.exists(previous)) throw new TauriDevIdError("TAURI_DEVID_NO_PREVIOUS", `no rollback copy at ${previous}`);
|
|
81
|
-
const aside = `${destination}.reset`;
|
|
82
|
-
deps.remove(aside);
|
|
83
|
-
const hadCurrent = deps.exists(destination);
|
|
84
|
-
if (hadCurrent) deps.rename(destination, aside);
|
|
85
|
-
try { deps.rename(previous, destination); }
|
|
86
|
-
catch (error) { if (hadCurrent) deps.rename(aside, destination); throw error; }
|
|
87
|
-
deps.remove(aside);
|
|
88
|
-
return { destination, restoredFrom: previous };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function verifyInstalled({ appRoot, destination, staged, expectedRequirement, binaries, env, deps }) {
|
|
143
|
+
function verifyInstalled({ appRoot, destination, staged, expectedRequirement, binaries, env, deps, descriptor, config, signing }) {
|
|
92
144
|
const strict = deps.run("codesign", ["--verify", "--strict", "--deep", destination], { cwd: appRoot, env, encoding: "utf8", windowsHide: true, shell: false });
|
|
93
145
|
if (strict.error || strict.status !== 0) throw new TauriDevIdError("TAURI_DEVID_VERIFY_FAILED", `installed ${destination} failed codesign --verify --strict --deep: ${strict.error?.message ?? text(strict)}`);
|
|
94
146
|
const display = deps.run("codesign", ["--display", "-r-", destination], { cwd: appRoot, env, encoding: "utf8", windowsHide: true, shell: false });
|
|
@@ -96,6 +148,14 @@ function verifyInstalled({ appRoot, destination, staged, expectedRequirement, bi
|
|
|
96
148
|
if (display.status !== 0 || actual !== expectedRequirement) {
|
|
97
149
|
throw new TauriDevIdError("TAURI_DEVID_VERIFY_FAILED", `installed ${destination} designated requirement ${JSON.stringify(actual)} is not the signed ${JSON.stringify(expectedRequirement)}`, { installedRequirement: actual, designatedRequirement: expectedRequirement });
|
|
98
150
|
}
|
|
151
|
+
// Declared identity assertions (install.assert, install.assertTeamSignedNested) against the installed copy; a failure rolls back.
|
|
152
|
+
const settings = readDevSigningSettings(descriptor, config?.development ? config : {});
|
|
153
|
+
if (settings.assertions.length || settings.assertTeamSignedNested) {
|
|
154
|
+
try {
|
|
155
|
+
deps.assertIdentities({ root: appRoot, bundle: destination, settings, teamIdentifier: signing.teamIdentifier, identity: signing.identity, env, run: deps.run, join: P.join, label: "installed copy",
|
|
156
|
+
...(deps.listFiles ? { listFiles: deps.listFiles } : {}), ...(deps.isMachO ? { isMachO: deps.isMachO } : {}) });
|
|
157
|
+
} catch (error) { throw new TauriDevIdError("TAURI_DEVID_VERIFY_FAILED", `installed ${destination} failed its identity assertions: ${error.message}`, { problems: error.problems }); }
|
|
158
|
+
}
|
|
99
159
|
for (const binary of binaries) {
|
|
100
160
|
let want; let got;
|
|
101
161
|
try { want = digestOf(deps, P.join(staged, binary)); got = digestOf(deps, P.join(destination, binary)); }
|
|
@@ -107,14 +167,16 @@ function verifyInstalled({ appRoot, destination, staged, expectedRequirement, bi
|
|
|
107
167
|
/**
|
|
108
168
|
* @param {{appRoot: string, config: object, built: string|{app: string}, deps?: object, env?: object}} options
|
|
109
169
|
* `config` is the app's release config (development.targets.mac.install is the `tauri-devid` descriptor).
|
|
110
|
-
* @returns {Promise<{installed: string,
|
|
170
|
+
* @returns {Promise<{installed: string, designatedRequirement: string, identity: string, teamIdentifier: string, signing: object}>}
|
|
111
171
|
*/
|
|
112
|
-
export async function installTauriDevId({ appRoot, config, built, deps = {}, env = {} }) {
|
|
172
|
+
export async function installTauriDevId({ appRoot, config, built, deps = {}, env = {}, releaseConfig }) {
|
|
113
173
|
const d = { ...defaultDeps(), ...deps };
|
|
114
|
-
const descriptor = resolveTauriDevIdDescriptor(config, { appRoot });
|
|
174
|
+
const descriptor = resolveTauriDevIdDescriptor(config, { appRoot, readFile: d.readFile, releaseConfig });
|
|
115
175
|
const destination = descriptor.destination;
|
|
116
176
|
const source = builtPathOf(built, appRoot);
|
|
117
177
|
if (!d.exists(source)) throw new TauriDevIdError("TAURI_DEVID_BUILT_INVALID", `built app not found: ${source}`);
|
|
178
|
+
// Same identity as production: the built bundle id must be the production identifier, or nothing is copied or signed.
|
|
179
|
+
assertBuiltIdentity({ source, descriptor, appRoot, env, deps: d });
|
|
118
180
|
const name = P.basename(destination);
|
|
119
181
|
const tempRoot = d.makeTemp();
|
|
120
182
|
// The staging copy carries the final bundle name so installApp installs <dest dir>/<name> without renaming.
|
|
@@ -122,42 +184,39 @@ export async function installTauriDevId({ appRoot, config, built, deps = {}, env
|
|
|
122
184
|
try {
|
|
123
185
|
d.copyApp(source, staged);
|
|
124
186
|
// 1. Sign: nested code first, then the app, with the stable Developer ID (development-signing orders it deepest first).
|
|
125
|
-
const signing = await d.sign({ root: appRoot, bundle: staged, descriptor, config, env });
|
|
187
|
+
const signing = await d.sign({ root: appRoot, bundle: staged, descriptor, config, env, ...(d.listFiles ? { listFiles: d.listFiles } : {}), ...(d.isMachO ? { isMachO: d.isMachO } : {}) });
|
|
126
188
|
if (signing.adhoc || !signing.designatedRequirement) throw new TauriDevIdError("TAURI_DEVID_SIGNING_UNSTABLE", `signing produced no stable Developer ID designated requirement for ${staged}; refusing to install`);
|
|
127
189
|
// 2. Same identity as the installed copy, or fail: a changed designated requirement resets every privacy grant.
|
|
128
190
|
if (d.exists(destination)) await d.assertRequirement({ root: appRoot, installed: destination, expected: signing.designatedRequirement, env, run: d.run });
|
|
129
|
-
// 3. Install at the fixed path
|
|
130
|
-
|
|
131
|
-
//
|
|
191
|
+
// 3. Install at the fixed path. The replaced copy is NOT kept anywhere (no <dest>.previous, no backup of any kind).
|
|
192
|
+
await d.installApp({ app: staged, dev: true, dest: P.dirname(destination), appName: name, bundleId: descriptor.bundleId ?? null, relaunch: null }, { env });
|
|
193
|
+
// A stale <dest>.previous from an older RightKit must not survive a dev install either.
|
|
194
|
+
d.remove(previousPathOf(destination));
|
|
195
|
+
// 4. Verify the installed copy; a failure removes the bad copy and leaves the path absent: reinstall from an older DMG.
|
|
132
196
|
try {
|
|
133
|
-
verifyInstalled({ appRoot, destination, staged, expectedRequirement: signing.designatedRequirement, binaries: descriptor.verifyBinaries, env, deps: d });
|
|
197
|
+
verifyInstalled({ appRoot, destination, staged, expectedRequirement: signing.designatedRequirement, binaries: descriptor.verifyBinaries, env, deps: d, descriptor, config, signing });
|
|
134
198
|
} catch (error) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
error.rolledBack = rolledBack;
|
|
199
|
+
d.remove(destination);
|
|
200
|
+
error.rolledBack = "removed-failed-install";
|
|
201
|
+
error.message = `${error.message}; the failed install was removed and no old copy is kept: reinstall from an older DMG`;
|
|
139
202
|
throw error;
|
|
140
203
|
}
|
|
141
204
|
d.log(`right-release dev: installed ${destination}; identity=${signing.identity}; TeamIdentifier=${signing.teamIdentifier}; designated=${signing.designatedRequirement}`);
|
|
142
|
-
return { installed: destination,
|
|
205
|
+
return { installed: destination, designatedRequirement: signing.designatedRequirement, identity: signing.identity, teamIdentifier: signing.teamIdentifier, signing };
|
|
143
206
|
} finally { d.remove(tempRoot); }
|
|
144
207
|
}
|
|
145
208
|
|
|
146
209
|
/**
|
|
147
|
-
* Deliberate reset of a fixed install
|
|
148
|
-
*
|
|
210
|
+
* Deliberate reset of a fixed install: mode "remove" (required, there is no default) deletes the install and any stale
|
|
211
|
+
* `.previous` (and, with `resetPrivacy`, runs `tccutil reset All <bundleId>`). There is no restore mode: dev installs keep
|
|
212
|
+
* no old copy (Orthic-Labs/rightkit#348), reinstall from an older DMG instead.
|
|
149
213
|
* Quit the app first; nothing here kills processes.
|
|
150
214
|
*/
|
|
151
|
-
export async function resetTauriDevId({ appRoot, config, mode
|
|
215
|
+
export async function resetTauriDevId({ appRoot, config, mode, resetPrivacy = false, deps = {}, env = {}, releaseConfig }) {
|
|
152
216
|
const d = { ...defaultDeps(), ...deps };
|
|
153
|
-
const descriptor = resolveTauriDevIdDescriptor(config, { appRoot });
|
|
217
|
+
const descriptor = resolveTauriDevIdDescriptor(config, { appRoot, readFile: d.readFile, releaseConfig });
|
|
154
218
|
const destination = descriptor.destination;
|
|
155
|
-
if (mode
|
|
156
|
-
const result = restorePrevious(destination, d);
|
|
157
|
-
d.log(`right-release dev: restored ${destination} from ${result.restoredFrom}`);
|
|
158
|
-
return { mode, ...result };
|
|
159
|
-
}
|
|
160
|
-
if (mode !== "remove") throw new TauriDevIdError("TAURI_DEVID_RESET_MODE_INVALID", `mode must be "restore" or "remove", got ${JSON.stringify(mode)}`);
|
|
219
|
+
if (mode !== "remove") throw new TauriDevIdError("TAURI_DEVID_RESET_MODE_INVALID", `mode must be "remove" (restore was removed: dev installs keep no old copy), got ${JSON.stringify(mode)}`);
|
|
161
220
|
d.remove(destination);
|
|
162
221
|
d.remove(previousPathOf(destination));
|
|
163
222
|
let privacyReset = false;
|