@hominis/fireforge 0.52.0 → 0.54.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/CHANGELOG.md +45 -0
- package/dist/build-info.json +4 -4
- package/dist/src/commands/bootstrap.js +2 -3
- package/dist/src/commands/build-prelock.d.ts +3 -3
- package/dist/src/commands/build-prelock.js +3 -3
- package/dist/src/commands/build.js +4 -0
- package/dist/src/commands/declarations-report.d.ts +9 -3
- package/dist/src/commands/declarations-report.js +18 -11
- package/dist/src/commands/discard.js +3 -3
- package/dist/src/commands/doctor-furnace-config-sync.js +4 -4
- package/dist/src/commands/doctor-furnace.js +5 -5
- package/dist/src/commands/export-adopt-check.d.ts +5 -6
- package/dist/src/commands/export-adopt-check.js +5 -6
- package/dist/src/commands/export-flow.js +6 -9
- package/dist/src/commands/export-staged-registration.d.ts +4 -4
- package/dist/src/commands/export-staged-registration.js +4 -4
- package/dist/src/commands/forward-import-remedy.d.ts +2 -3
- package/dist/src/commands/forward-import-remedy.js +2 -3
- package/dist/src/commands/furnace/create-dry-run.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.d.ts +2 -2
- package/dist/src/commands/furnace/deploy-fragment-includers.js +2 -2
- package/dist/src/commands/furnace/index.js +2 -2
- package/dist/src/commands/lint.js +4 -4
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/lint-ignore-from.d.ts +3 -4
- package/dist/src/commands/patch/lint-ignore-from.js +3 -4
- package/dist/src/commands/patch/move-files-adopt.d.ts +33 -0
- package/dist/src/commands/patch/move-files-adopt.js +65 -0
- package/dist/src/commands/patch/move-files-create.js +41 -20
- package/dist/src/commands/patch/move-files-into.d.ts +18 -0
- package/dist/src/commands/patch/move-files-into.js +125 -60
- package/dist/src/commands/patch/move-files-retire.d.ts +39 -0
- package/dist/src/commands/patch/move-files-retire.js +91 -0
- package/dist/src/commands/patch/move-files.d.ts +3 -0
- package/dist/src/commands/patch/move-files.js +42 -12
- package/dist/src/commands/patch/move-size-tier.d.ts +27 -0
- package/dist/src/commands/patch/move-size-tier.js +66 -0
- package/dist/src/commands/patch/rename.js +1 -1
- package/dist/src/commands/patch/reorder-projection.d.ts +17 -0
- package/dist/src/commands/patch/reorder-projection.js +49 -0
- package/dist/src/commands/patch/reorder-shift.d.ts +30 -0
- package/dist/src/commands/patch/reorder-shift.js +307 -0
- package/dist/src/commands/patch/reorder.d.ts +9 -15
- package/dist/src/commands/patch/reorder.js +52 -50
- package/dist/src/commands/patch/split-plan.d.ts +31 -3
- package/dist/src/commands/patch/split-plan.js +36 -12
- package/dist/src/commands/patch/split-staged.d.ts +2 -2
- package/dist/src/commands/patch/split-staged.js +2 -2
- package/dist/src/commands/patch/split.js +18 -5
- package/dist/src/commands/patch/staged-dependency-entries.d.ts +9 -1
- package/dist/src/commands/patch/staged-dependency-entries.js +32 -4
- package/dist/src/commands/patch/staged-dependency-from.js +15 -9
- package/dist/src/commands/patch/staged-dependency-remove.d.ts +26 -4
- package/dist/src/commands/patch/staged-dependency-remove.js +60 -23
- package/dist/src/commands/patch/staged-dependency.js +35 -24
- package/dist/src/commands/patch/tier.js +2 -2
- package/dist/src/commands/patch-rename-map.d.ts +14 -3
- package/dist/src/commands/patch-rename-map.js +21 -3
- package/dist/src/commands/re-export-adjacent.d.ts +4 -5
- package/dist/src/commands/re-export-lint.d.ts +4 -3
- package/dist/src/commands/re-export-lint.js +4 -3
- package/dist/src/commands/re-export-options.js +8 -2
- package/dist/src/commands/re-export-preflight.js +1 -2
- package/dist/src/commands/re-export-purity-scope.d.ts +1 -1
- package/dist/src/commands/re-export-purity-scope.js +13 -7
- package/dist/src/commands/re-export-retired-declarations.d.ts +22 -0
- package/dist/src/commands/re-export-retired-declarations.js +113 -0
- package/dist/src/commands/re-export-single.js +2 -2
- package/dist/src/commands/re-export-stale-registrations.d.ts +27 -6
- package/dist/src/commands/re-export-stale-registrations.js +65 -21
- package/dist/src/commands/re-export.js +4 -0
- package/dist/src/commands/rebase/continue.js +3 -3
- package/dist/src/commands/register.js +5 -4
- package/dist/src/commands/run.js +11 -4
- package/dist/src/commands/status.js +1 -1
- package/dist/src/commands/test-build-furnace.d.ts +1 -2
- package/dist/src/commands/test-build-furnace.js +1 -2
- package/dist/src/commands/test-build-phase.d.ts +8 -0
- package/dist/src/commands/test-build-phase.js +42 -7
- package/dist/src/commands/test-control-restore.d.ts +40 -0
- package/dist/src/commands/test-control-restore.js +86 -0
- package/dist/src/commands/test-dispatch.js +68 -7
- package/dist/src/commands/test-multi-verdict.js +1 -0
- package/dist/src/commands/test-orchestrate.d.ts +6 -0
- package/dist/src/commands/test-orchestrate.js +32 -1
- package/dist/src/commands/test-perf-scope.d.ts +1 -1
- package/dist/src/commands/test-perf-scope.js +1 -1
- package/dist/src/commands/test-prelock.d.ts +18 -8
- package/dist/src/commands/test-prelock.js +42 -14
- package/dist/src/commands/test-register.js +4 -3
- package/dist/src/commands/test-results.d.ts +10 -1
- package/dist/src/commands/test-results.js +20 -3
- package/dist/src/commands/test-run.d.ts +6 -0
- package/dist/src/commands/test-run.js +23 -4
- package/dist/src/commands/test-shards.d.ts +7 -3
- package/dist/src/commands/test-shards.js +24 -7
- package/dist/src/commands/test-stale-gate.d.ts +6 -1
- package/dist/src/commands/test-stale-gate.js +40 -2
- package/dist/src/commands/test-verdict.d.ts +5 -3
- package/dist/src/commands/test.js +14 -2
- package/dist/src/commands/token.js +2 -2
- package/dist/src/commands/verify.js +1 -1
- package/dist/src/commands/watch.js +1 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/build-audit-resolve.d.ts +4 -5
- package/dist/src/core/build-audit-resolve.js +4 -5
- package/dist/src/core/build-audit-skip.d.ts +2 -2
- package/dist/src/core/build-audit.d.ts +3 -4
- package/dist/src/core/build-baseline-types.d.ts +24 -3
- package/dist/src/core/build-baseline-validate.d.ts +30 -1
- package/dist/src/core/build-baseline-validate.js +127 -35
- package/dist/src/core/build-baseline.d.ts +8 -2
- package/dist/src/core/build-baseline.js +25 -16
- package/dist/src/core/build-jar-escalation.d.ts +4 -4
- package/dist/src/core/build-jar-escalation.js +4 -4
- package/dist/src/core/build-prepare.js +4 -4
- package/dist/src/core/config-validate.js +4 -4
- package/dist/src/core/coverage-extend.d.ts +5 -3
- package/dist/src/core/coverage-extend.js +8 -3
- package/dist/src/core/coverage-records.d.ts +4 -5
- package/dist/src/core/coverage-records.js +4 -5
- package/dist/src/core/destructive.d.ts +2 -2
- package/dist/src/core/destructive.js +2 -2
- package/dist/src/core/discard-baseline.d.ts +2 -2
- package/dist/src/core/discard-baseline.js +3 -3
- package/dist/src/core/engine-session-lock.d.ts +1 -1
- package/dist/src/core/engine-session-lock.js +1 -1
- package/dist/src/core/file-lock-owner.d.ts +5 -5
- package/dist/src/core/file-lock-owner.js +5 -5
- package/dist/src/core/file-lock-queue.js +6 -8
- package/dist/src/core/file-lock-shared.d.ts +4 -4
- package/dist/src/core/file-lock-shared.js +4 -4
- package/dist/src/core/file-lock.js +7 -10
- package/dist/src/core/firefox.js +2 -2
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.js +1 -1
- package/dist/src/core/furnace-apply.js +3 -3
- package/dist/src/core/furnace-operation.js +5 -5
- package/dist/src/core/furnace-registration-jar-inplace.js +5 -6
- package/dist/src/core/furnace-registration-rename.d.ts +5 -5
- package/dist/src/core/furnace-registration-rename.js +5 -5
- package/dist/src/core/furnace-registration-validate.d.ts +2 -1
- package/dist/src/core/furnace-registration-validate.js +2 -1
- package/dist/src/core/furnace-registration.js +2 -2
- package/dist/src/core/git-base.js +4 -3
- package/dist/src/core/git-diff.js +1 -1
- package/dist/src/core/git.js +1 -1
- package/dist/src/core/harness-orphans.d.ts +6 -6
- package/dist/src/core/harness-orphans.js +6 -6
- package/dist/src/core/harness-port-reservation.d.ts +60 -0
- package/dist/src/core/harness-port-reservation.js +122 -0
- package/dist/src/core/history-log-file.d.ts +9 -9
- package/dist/src/core/history-log-file.js +15 -15
- package/dist/src/core/history-log.d.ts +3 -3
- package/dist/src/core/history-log.js +3 -3
- package/dist/src/core/launchable-build.d.ts +39 -0
- package/dist/src/core/launchable-build.js +85 -0
- package/dist/src/core/marionette-port.js +1 -3
- package/dist/src/core/moz-manifest-rules.js +3 -2
- package/dist/src/core/negative-control-compiled.d.ts +13 -3
- package/dist/src/core/negative-control-compiled.js +27 -5
- package/dist/src/core/negative-control-diff.js +31 -6
- package/dist/src/core/parser-fallback.d.ts +5 -5
- package/dist/src/core/parser-fallback.js +5 -5
- package/dist/src/core/patch-identifier-suggest.d.ts +6 -0
- package/dist/src/core/patch-identifier-suggest.js +11 -4
- package/dist/src/core/patch-lint-checkjs.d.ts +1 -1
- package/dist/src/core/patch-lint-checkjs.js +1 -1
- package/dist/src/core/patch-lint-css.js +2 -2
- package/dist/src/core/patch-lint-file-size.d.ts +5 -7
- package/dist/src/core/patch-lint-file-size.js +5 -7
- package/dist/src/core/patch-lint-ignore.d.ts +3 -3
- package/dist/src/core/patch-lint-ignore.js +3 -3
- package/dist/src/core/patch-lint-prettier.d.ts +4 -6
- package/dist/src/core/patch-lint-prettier.js +4 -6
- package/dist/src/core/patch-lint-projection.d.ts +1 -1
- package/dist/src/core/patch-lint-projection.js +1 -1
- package/dist/src/core/patch-lint-queue-types.d.ts +2 -2
- package/dist/src/core/patch-lint-queue-types.js +2 -2
- package/dist/src/core/patch-manifest-consistency.d.ts +2 -2
- package/dist/src/core/patch-manifest-consistency.js +2 -2
- package/dist/src/core/patch-manifest-io.d.ts +5 -1
- package/dist/src/core/patch-manifest-io.js +12 -10
- package/dist/src/core/patch-manifest-key-order.d.ts +3 -4
- package/dist/src/core/patch-manifest-key-order.js +3 -4
- package/dist/src/core/patch-parse.d.ts +3 -3
- package/dist/src/core/patch-parse.js +3 -3
- package/dist/src/core/patch-policy.d.ts +1 -1
- package/dist/src/core/patch-policy.js +1 -1
- package/dist/src/core/patch-source-metadata.d.ts +1 -1
- package/dist/src/core/patch-source-metadata.js +1 -1
- package/dist/src/core/patch-subset.d.ts +5 -3
- package/dist/src/core/patch-subset.js +8 -7
- package/dist/src/core/patch-transform.d.ts +2 -2
- package/dist/src/core/patch-transform.js +2 -2
- package/dist/src/core/rebase-session.js +4 -6
- package/dist/src/core/register-xpcshell-test.d.ts +28 -7
- package/dist/src/core/register-xpcshell-test.js +76 -27
- package/dist/src/core/run-log.d.ts +8 -8
- package/dist/src/core/run-log.js +8 -8
- package/dist/src/core/status-classify.d.ts +1 -2
- package/dist/src/core/status-classify.js +1 -2
- package/dist/src/core/test-harness-crash.d.ts +5 -3
- package/dist/src/core/test-harness-crash.js +13 -14
- package/dist/src/core/test-harness-infra.d.ts +32 -0
- package/dist/src/core/test-harness-infra.js +69 -0
- package/dist/src/core/test-harness-signature.d.ts +6 -0
- package/dist/src/core/test-stale-check.d.ts +38 -0
- package/dist/src/core/test-stale-check.js +82 -1
- package/dist/src/core/test-stall-triage.js +5 -7
- package/dist/src/core/token-category.js +2 -2
- package/dist/src/core/token-inventory.js +3 -3
- package/dist/src/core/token-manager.d.ts +2 -2
- package/dist/src/core/token-manager.js +5 -7
- package/dist/src/core/token-variant.d.ts +6 -6
- package/dist/src/core/token-variant.js +7 -7
- package/dist/src/core/typecheck-shim.js +1 -1
- package/dist/src/core/wire-destroy.d.ts +1 -1
- package/dist/src/core/wire-destroy.js +1 -1
- package/dist/src/core/wire-dom-fragment.js +1 -1
- package/dist/src/core/wire-init.d.ts +1 -1
- package/dist/src/core/wire-init.js +1 -1
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +1 -1
- package/dist/src/core/wire-utils.d.ts +2 -2
- package/dist/src/core/wire-utils.js +3 -3
- package/dist/src/errors/base.d.ts +1 -1
- package/dist/src/errors/base.js +1 -1
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +1 -1
- package/dist/src/types/commands/options.d.ts +38 -3
- package/dist/src/types/config.d.ts +5 -7
- package/dist/src/utils/options.js +2 -2
- package/dist/src/utils/process.js +2 -2
- package/dist/src/utils/regex.d.ts +2 -2
- package/dist/src/utils/regex.js +3 -3
- package/dist/src/utils/sleep.d.ts +5 -6
- package/dist/src/utils/sleep.js +5 -6
- package/dist/src/utils/validation.js +2 -2
- package/docs/configuration.md +28 -23
- package/docs/exit-codes.md +8 -11
- package/docs/furnace.md +3 -3
- package/docs/lifecycle-invariants.md +36 -45
- package/docs/machine-output.md +41 -24
- package/docs/patch-workflow.md +140 -29
- package/docs/run-logs.md +8 -9
- package/docs/testing.md +114 -48
- package/package.json +1 -1
|
@@ -74,10 +74,10 @@ function parseFirefoxBlock(rec) {
|
|
|
74
74
|
throw new ConfigError('Config field "firefox.version" must be a valid Firefox version (e.g., "145.0")');
|
|
75
75
|
}
|
|
76
76
|
const firefoxProduct = requireConfigString(firefoxRec, 'product', 'firefox.product');
|
|
77
|
-
// Uses the shared guard rather than a
|
|
78
|
-
// is the fireforge.json read path: a product added to the union but
|
|
79
|
-
//
|
|
80
|
-
//
|
|
77
|
+
// Uses the shared guard rather than a separate copy of the member list.
|
|
78
|
+
// This is the fireforge.json read path: a product added to the union but
|
|
79
|
+
// not to a local copy would be silently rejected from every project
|
|
80
|
+
// config.
|
|
81
81
|
if (!isValidFirefoxProduct(firefoxProduct)) {
|
|
82
82
|
throw new ConfigError(`Config field "firefox.product" must be one of: ${FIREFOX_PRODUCTS.join(', ')}`);
|
|
83
83
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* collapsing to this build's paths. `--extend-coverage` turns any drop into
|
|
8
8
|
* a refusal before the build.
|
|
9
9
|
*
|
|
10
|
-
* Fingerprints must be complete: a
|
|
10
|
+
* Fingerprints must be complete: a record of packageable inputs only cannot
|
|
11
11
|
* prove that a test fixture or manifest still matches its staged copy.
|
|
12
12
|
*/
|
|
13
13
|
import type { BuildBaseline, CoverageAnchor, CoverageRecord, TestPackagingCoverage } from './build-baseline-types.js';
|
|
@@ -70,9 +70,11 @@ export interface RecordedCoverage {
|
|
|
70
70
|
*
|
|
71
71
|
* @param engineDir - Path to the engine directory
|
|
72
72
|
* @param plan - Plan after {@link applyMozconfigAnchor}
|
|
73
|
-
* @param
|
|
73
|
+
* @param requestedPaths - Request paths this build packaged. Normalized
|
|
74
|
+
* here (no trailing slash, no `./`): the baseline validator rejects the
|
|
75
|
+
* raw CLI shapes, and a baseline it rejects refuses every later run.
|
|
74
76
|
*/
|
|
75
|
-
export declare function recordScopedCoverage(engineDir: string, plan: CoverageRetentionPlan,
|
|
77
|
+
export declare function recordScopedCoverage(engineDir: string, plan: CoverageRetentionPlan, requestedPaths: string[]): Promise<RecordedCoverage>;
|
|
76
78
|
/** Renders one dropped claim with its cause. */
|
|
77
79
|
export declare function describeDroppedClaim(claim: DroppedClaim): string;
|
|
78
80
|
/**
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* collapsing to this build's paths. `--extend-coverage` turns any drop into
|
|
9
9
|
* a refusal before the build.
|
|
10
10
|
*
|
|
11
|
-
* Fingerprints must be complete: a
|
|
11
|
+
* Fingerprints must be complete: a record of packageable inputs only cannot
|
|
12
12
|
* prove that a test fixture or manifest still matches its staged copy.
|
|
13
13
|
*/
|
|
14
14
|
import { toError } from '../utils/errors.js';
|
|
@@ -163,11 +163,16 @@ export async function applyMozconfigAnchor(engineDir, plan) {
|
|
|
163
163
|
*
|
|
164
164
|
* @param engineDir - Path to the engine directory
|
|
165
165
|
* @param plan - Plan after {@link applyMozconfigAnchor}
|
|
166
|
-
* @param
|
|
166
|
+
* @param requestedPaths - Request paths this build packaged. Normalized
|
|
167
|
+
* here (no trailing slash, no `./`): the baseline validator rejects the
|
|
168
|
+
* raw CLI shapes, and a baseline it rejects refuses every later run.
|
|
167
169
|
*/
|
|
168
|
-
export async function recordScopedCoverage(engineDir, plan,
|
|
170
|
+
export async function recordScopedCoverage(engineDir, plan, requestedPaths) {
|
|
169
171
|
if (plan.keepFull)
|
|
170
172
|
return { testPackagingCoverage: 'full' };
|
|
173
|
+
const requested = [
|
|
174
|
+
...new Set(requestedPaths.map(normalizeRequestPath).filter((path) => path.length > 0)),
|
|
175
|
+
];
|
|
171
176
|
const records = { ...plan.retained };
|
|
172
177
|
try {
|
|
173
178
|
const state = await readEngineContentState(engineDir);
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-path packaging-coverage anchors for scoped `fireforge test --build`.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* one of those inputs changed.
|
|
4
|
+
* Each staged request path carries its own anchor restricted to its own
|
|
5
|
+
* staging inputs, and a claim is dropped only when one of those inputs
|
|
6
|
+
* changed. One claim anchored to the whole engine would be replaced by any
|
|
7
|
+
* edit outside the new scope (a peer's, on a shared engine, nearly always).
|
|
9
8
|
*
|
|
10
9
|
* The staging inputs of a request path are its manifest directory (the
|
|
11
10
|
* nearest directory at or above it that holds a test manifest) plus every
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Per-path packaging-coverage anchors for scoped `fireforge test --build`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* one of those inputs changed.
|
|
5
|
+
* Each staged request path carries its own anchor restricted to its own
|
|
6
|
+
* staging inputs, and a claim is dropped only when one of those inputs
|
|
7
|
+
* changed. One claim anchored to the whole engine would be replaced by any
|
|
8
|
+
* edit outside the new scope (a peer's, on a shared engine, nearly always).
|
|
10
9
|
*
|
|
11
10
|
* The staging inputs of a request path are its manifest directory (the
|
|
12
11
|
* nearest directory at or above it that holds a test manifest) plus every
|
|
@@ -128,8 +128,8 @@ export declare function confirmDestructive(input: DestructiveOpInput): Promise<D
|
|
|
128
128
|
/**
|
|
129
129
|
* Appends a single JSONL record to the project's patch history log
|
|
130
130
|
* (`.fireforge/history.jsonl` unless `fireforge.json#history.path` says
|
|
131
|
-
* otherwise; a log at
|
|
132
|
-
*
|
|
131
|
+
* otherwise; a log found at `patches/.fireforge-history.jsonl` is moved
|
|
132
|
+
* there first).
|
|
133
133
|
*
|
|
134
134
|
* Call order matters: append only after the mutation succeeds, never
|
|
135
135
|
* pre-emptively, so rolled-back failures do not leave ghost entries. The log
|
|
@@ -159,8 +159,8 @@ export async function confirmDestructive(input) {
|
|
|
159
159
|
/**
|
|
160
160
|
* Appends a single JSONL record to the project's patch history log
|
|
161
161
|
* (`.fireforge/history.jsonl` unless `fireforge.json#history.path` says
|
|
162
|
-
* otherwise; a log at
|
|
163
|
-
*
|
|
162
|
+
* otherwise; a log found at `patches/.fireforge-history.jsonl` is moved
|
|
163
|
+
* there first).
|
|
164
164
|
*
|
|
165
165
|
* Call order matters: append only after the mutation succeeds, never
|
|
166
166
|
* pre-emptively, so rolled-back failures do not leave ghost entries. The log
|
|
@@ -30,7 +30,7 @@ export interface DiscardBaselinePlan {
|
|
|
30
30
|
/** Rename/copy only: baseline content for `originalPath` when that side is claimed. */
|
|
31
31
|
expectedOriginalContent?: string | null;
|
|
32
32
|
}
|
|
33
|
-
/** Builds an all-unmanaged plan set, the `--to-upstream`
|
|
33
|
+
/** Builds an all-unmanaged plan set, the `--to-upstream` shape. */
|
|
34
34
|
export declare function planUpstreamDiscards(entries: readonly GitStatusEntry[]): DiscardBaselinePlan[];
|
|
35
35
|
/**
|
|
36
36
|
* Plans the restore target for each status entry. Entries claimed by the
|
|
@@ -47,7 +47,7 @@ export declare function planDiscardBaselines(patchesDir: string, engineDir: stri
|
|
|
47
47
|
* Applies one restore plan. Patch-claimed paths end up exactly as `import`
|
|
48
48
|
* leaves them: patched content as an unstaged worktree state (tracked files
|
|
49
49
|
* read ` M`, created files `??`), nothing staged. Unmanaged plans delegate
|
|
50
|
-
* to the
|
|
50
|
+
* to the plain git {@link discardStatusEntry} mechanics.
|
|
51
51
|
*/
|
|
52
52
|
export declare function applyDiscardBaseline(engineDir: string, plan: DiscardBaselinePlan): Promise<void>;
|
|
53
53
|
/** One-line annotation for dry-run listings and confirmation summaries. */
|
|
@@ -24,7 +24,7 @@ import { createPatchedContentContext } from './patch-apply.js';
|
|
|
24
24
|
import { loadPatchesManifestState } from './patch-manifest-io.js';
|
|
25
25
|
import { parseDiffSections } from './patch-parse.js';
|
|
26
26
|
import { buildPatchClaims } from './status-classify.js';
|
|
27
|
-
/** Builds an all-unmanaged plan set, the `--to-upstream`
|
|
27
|
+
/** Builds an all-unmanaged plan set, the `--to-upstream` shape. */
|
|
28
28
|
export function planUpstreamDiscards(entries) {
|
|
29
29
|
return entries.map((entry) => ({ entry, kind: 'unmanaged', owners: [], conflicted: false }));
|
|
30
30
|
}
|
|
@@ -151,7 +151,7 @@ export async function planDiscardBaselines(patchesDir, engineDir, entries) {
|
|
|
151
151
|
* Applies one restore plan. Patch-claimed paths end up exactly as `import`
|
|
152
152
|
* leaves them: patched content as an unstaged worktree state (tracked files
|
|
153
153
|
* read ` M`, created files `??`), nothing staged. Unmanaged plans delegate
|
|
154
|
-
* to the
|
|
154
|
+
* to the plain git {@link discardStatusEntry} mechanics.
|
|
155
155
|
*/
|
|
156
156
|
export async function applyDiscardBaseline(engineDir, plan) {
|
|
157
157
|
if (plan.kind === 'unmanaged') {
|
|
@@ -173,7 +173,7 @@ export async function applyDiscardBaseline(engineDir, plan) {
|
|
|
173
173
|
await writeText(join(engineDir, entry.file), plan.expectedContent);
|
|
174
174
|
}
|
|
175
175
|
// A rename/copy's original side restores to its baseline too: the patch
|
|
176
|
-
// baseline when claimed, else the
|
|
176
|
+
// baseline when claimed, else the HEAD restore (matching what
|
|
177
177
|
// discardStatusEntry does for that side).
|
|
178
178
|
if (entry.originalPath !== undefined) {
|
|
179
179
|
if (plan.expectedOriginalContent !== undefined) {
|
|
@@ -77,7 +77,7 @@ export declare function generationDeltaPaths(before: string, after: string): {
|
|
|
77
77
|
/**
|
|
78
78
|
* Describes what moved between two generation tokens, in operator terms.
|
|
79
79
|
*
|
|
80
|
-
*
|
|
80
|
+
* A refusal that said only that the engine changed would leave the
|
|
81
81
|
* operator to reconstruct the writer by hand: `find -newermt` against the
|
|
82
82
|
* run window, minus the objdir, minus git's own bookkeeping. Everything
|
|
83
83
|
* needed to answer it is already in the two tokens, so the refusal answers
|
|
@@ -281,7 +281,7 @@ export function generationDeltaPaths(before, after) {
|
|
|
281
281
|
/**
|
|
282
282
|
* Describes what moved between two generation tokens, in operator terms.
|
|
283
283
|
*
|
|
284
|
-
*
|
|
284
|
+
* A refusal that said only that the engine changed would leave the
|
|
285
285
|
* operator to reconstruct the writer by hand: `find -newermt` against the
|
|
286
286
|
* run window, minus the objdir, minus git's own bookkeeping. Everything
|
|
287
287
|
* needed to answer it is already in the two tokens, so the refusal answers
|
|
@@ -46,11 +46,11 @@ export declare function readLockOwner(lockPath: string): Promise<LockOwner>;
|
|
|
46
46
|
* time, own start tick, diagnostic metadata) into a lock directory it has
|
|
47
47
|
* just created, and reads the record back to prove it landed.
|
|
48
48
|
*
|
|
49
|
-
* The write is fatal
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
49
|
+
* The write is fatal rather than best-effort. Stale recovery could fall
|
|
50
|
+
* back to the age heuristic, but that heuristic reaps any owner-less lock
|
|
51
|
+
* after five minutes, and the build lock legitimately holds for hours. A
|
|
52
|
+
* holder whose record failed to write would be reaped mid-build and a
|
|
53
|
+
* second process would enter the critical section. On
|
|
54
54
|
* failure the just-created lock directory is removed (nothing else can own
|
|
55
55
|
* it yet) and a {@link GeneralError} names the cause.
|
|
56
56
|
*
|
|
@@ -141,11 +141,11 @@ async function readBackLockOwner(lockPath) {
|
|
|
141
141
|
* time, own start tick, diagnostic metadata) into a lock directory it has
|
|
142
142
|
* just created, and reads the record back to prove it landed.
|
|
143
143
|
*
|
|
144
|
-
* The write is fatal
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
144
|
+
* The write is fatal rather than best-effort. Stale recovery could fall
|
|
145
|
+
* back to the age heuristic, but that heuristic reaps any owner-less lock
|
|
146
|
+
* after five minutes, and the build lock legitimately holds for hours. A
|
|
147
|
+
* holder whose record failed to write would be reaped mid-build and a
|
|
148
|
+
* second process would enter the critical section. On
|
|
149
149
|
* failure the just-created lock directory is removed (nothing else can own
|
|
150
150
|
* it yet) and a {@link GeneralError} names the cause.
|
|
151
151
|
*
|
|
@@ -3,18 +3,16 @@
|
|
|
3
3
|
* Waiter tickets for `withFileLock`: who is queued for a contended lock, in
|
|
4
4
|
* what order, and whose turn it is.
|
|
5
5
|
*
|
|
6
|
-
* The
|
|
7
|
-
*
|
|
8
|
-
* `mkdir` polls
|
|
9
|
-
*
|
|
10
|
-
* was next
|
|
11
|
-
* turn. The tickets now decide the grant: only the head of the queue may
|
|
12
|
-
* attempt the lock, so the position printed is the position honoured.
|
|
6
|
+
* The tickets decide the grant: only the head of the queue may attempt the
|
|
7
|
+
* lock, so the position printed is the position honoured. A free-for-all of
|
|
8
|
+
* `mkdir` polls would let later arrivals polling at 100 ms take every free
|
|
9
|
+
* moment from a waiter whose poll interval had backed off to 2 s, so a run
|
|
10
|
+
* told it was next could watch later runs take the lock in turn.
|
|
13
11
|
*
|
|
14
12
|
* A ticket is a file in `<lock>.waiters/` named
|
|
15
13
|
* `<startedAtMs>-<pid>-<uuid>`. Arrival order is the wait start, with the
|
|
16
14
|
* whole name as a tie-break so every reader sorts the queue identically.
|
|
17
|
-
* Because a ticket
|
|
15
|
+
* Because a ticket blocks everyone behind it, a ticket whose owner is
|
|
18
16
|
* gone must not hold the queue: a dead PID (or a reused one, where the
|
|
19
17
|
* start-tick check can tell) drops out and its ticket is removed, and a
|
|
20
18
|
* ticket its owner has stopped refreshing drops out without being removed,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared holds on a FireForge directory lock.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* serially on a
|
|
4
|
+
* Two build-less `fireforge test` runs on one objdir, each with its own
|
|
5
|
+
* profile and (under auto ports) its own ports, have no reason to wait for
|
|
6
|
+
* each other; with only exclusive holds the gate's browser tiers would run
|
|
7
|
+
* strictly serially on a many-core host. A shared hold lets such runs overlap while
|
|
8
8
|
* anything that writes (a build, a re-export, a test run that builds)
|
|
9
9
|
* still holds the lock alone.
|
|
10
10
|
*
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Shared holds on a FireForge directory lock.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* serially on a
|
|
5
|
+
* Two build-less `fireforge test` runs on one objdir, each with its own
|
|
6
|
+
* profile and (under auto ports) its own ports, have no reason to wait for
|
|
7
|
+
* each other; with only exclusive holds the gate's browser tiers would run
|
|
8
|
+
* strictly serially on a many-core host. A shared hold lets such runs overlap while
|
|
9
9
|
* anything that writes (a build, a re-export, a test run that builds)
|
|
10
10
|
* still holds the lock alone.
|
|
11
11
|
*
|
|
@@ -269,10 +269,9 @@ async function buildLockTimeoutError(lockPath, onTimeoutMessage, cause, queue) {
|
|
|
269
269
|
*
|
|
270
270
|
* The queue is read at the moment the budget expires rather than taken from
|
|
271
271
|
* the last progress probe. A probe snapshot is up to one `waitProgressMs`
|
|
272
|
-
* stale, and
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
* probe at all never had one. Both used to lose the position silently.
|
|
272
|
+
* stale, and it may not exist at all: a short budget can expire before the
|
|
273
|
+
* first probe lands (a slow runner's `registerWaiter` alone can outlast it),
|
|
274
|
+
* and a caller that configured no probe at all never has one.
|
|
276
275
|
*/
|
|
277
276
|
function formatQueuePositionReached(queue) {
|
|
278
277
|
if (queue.depth === 0)
|
|
@@ -423,12 +422,10 @@ export async function withFileLock(lockPath, operation, options = {}) {
|
|
|
423
422
|
// buys a fresh budget, because the wait is working. Only a queue
|
|
424
423
|
// that stops moving starves, which is the case the timeout is for.
|
|
425
424
|
//
|
|
426
|
-
// The first observation is a seed, never an advance.
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
// once, which is the "it does not reliably give up after N
|
|
431
|
-
// seconds" behaviour a downstream fork reported.
|
|
425
|
+
// The first observation is a seed, never an advance. Counted as an
|
|
426
|
+
// advance, the opening probe would hand out a free full budget: a
|
|
427
|
+
// `--wait-lock 300` run would outlive its 300 s even against a queue
|
|
428
|
+
// that never moved once.
|
|
432
429
|
if (hardDeadline !== undefined) {
|
|
433
430
|
if (bestAhead === undefined) {
|
|
434
431
|
bestAhead = probe.queue.ahead;
|
package/dist/src/core/firefox.js
CHANGED
|
@@ -96,8 +96,8 @@ export async function downloadFirefoxSource(options) {
|
|
|
96
96
|
await removeDir(tempDir);
|
|
97
97
|
// Only throw away the ~600 MB cached archive when the failure indicts
|
|
98
98
|
// the archive, not the environment. ENOSPC, a permission problem in
|
|
99
|
-
// destDir, or tar disappearing mid-run
|
|
100
|
-
//
|
|
99
|
+
// destDir, or tar disappearing mid-run leaves a perfectly good download
|
|
100
|
+
// that a retry can reuse without a full re-fetch.
|
|
101
101
|
if (isLikelyArchiveCorruptionError(error)) {
|
|
102
102
|
await invalidateArchiveCache(archive, cacheDir);
|
|
103
103
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* The per-file byte comparison already exists:
|
|
14
14
|
* `checkRegistrationConsistency` for custom components (fragment- and
|
|
15
15
|
* ftl-aware) and the copy-candidate walk for overrides. This module only
|
|
16
|
-
* surfaces what
|
|
16
|
+
* surfaces what those comparisons compute.
|
|
17
17
|
*/
|
|
18
18
|
import type { CustomComponentConfig, OverrideComponentConfig } from '../types/furnace.js';
|
|
19
19
|
/** One deployed, patch-owned file about to be overwritten with different bytes. */
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* The per-file byte comparison already exists:
|
|
15
15
|
* `checkRegistrationConsistency` for custom components (fragment- and
|
|
16
16
|
* ftl-aware) and the copy-candidate walk for overrides. This module only
|
|
17
|
-
* surfaces what
|
|
17
|
+
* surfaces what those comparisons compute.
|
|
18
18
|
*/
|
|
19
19
|
import { readdir } from 'node:fs/promises';
|
|
20
20
|
import { join, relative } from 'node:path';
|
|
@@ -258,9 +258,9 @@ async function applyCustomBatch(ctx, root, markerComment) {
|
|
|
258
258
|
filesAffectedTotal.push(...removed);
|
|
259
259
|
}
|
|
260
260
|
if (!dryRun) {
|
|
261
|
-
// Runs unconditionally
|
|
262
|
-
//
|
|
263
|
-
//
|
|
261
|
+
// Runs unconditionally, including on the `changed === true` path:
|
|
262
|
+
// that is when a deployed engine-only fix gets silently replaced
|
|
263
|
+
// (J6).
|
|
264
264
|
recordOverwriteWarnings(result, await findPatchOwnedOverwrites({
|
|
265
265
|
type: 'custom',
|
|
266
266
|
root,
|
|
@@ -305,11 +305,11 @@ export async function completeJournalRollback(ctx, journal, error, options) {
|
|
|
305
305
|
export async function forceReleaseFurnaceLocksForActiveOperations() {
|
|
306
306
|
const paths = new Set([...activeOperations.values()].map((op) => getFurnaceLockPath(op.root)));
|
|
307
307
|
for (const lockPath of paths) {
|
|
308
|
-
// Ownership-checked, like every other release path.
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
//
|
|
308
|
+
// Ownership-checked, like every other release path. A bare `rm` would
|
|
309
|
+
// delete a lock a different process had acquired in the window between
|
|
310
|
+
// our operation dying and this sweep running. That is the exact race
|
|
311
|
+
// `releaseLock`'s PID verification closes, and the sweeper has no
|
|
312
|
+
// acquisition token to check.
|
|
313
313
|
const removed = await releaseLockIfOwned(lockPath);
|
|
314
314
|
verbose(removed
|
|
315
315
|
? `Removed furnace lock at ${lockPath} during signal teardown`
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* In-place edits to a widget's `toolkit/content/jar.mn` block.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* the lines that change: a deleted file's line goes, a renamed component's
|
|
5
|
+
* Dropping every line of the widget and re-adding the live ones would
|
|
6
|
+
* re-sort the whole block and leave the owning patch carrying reorder
|
|
7
|
+
* hunks. These helpers touch only the lines that change: a deleted file's line goes, a renamed component's
|
|
9
8
|
* lines are rewritten where they stand, and anything still missing is left
|
|
10
9
|
* for `addJarMnEntries` to insert.
|
|
11
10
|
*/
|
|
@@ -15,8 +14,8 @@ import { escapeRegex } from '../utils/regex.js';
|
|
|
15
14
|
import { JAR_MN } from './furnace-constants.js';
|
|
16
15
|
/**
|
|
17
16
|
* The file a widget jar.mn line registers: the `(widgets/<tag>/<file>)`
|
|
18
|
-
* source mapping, or the
|
|
19
|
-
*
|
|
17
|
+
* source mapping, or the `content/global/elements/<tag>.<ext>` target of a
|
|
18
|
+
* line that carries no source mapping. Undefined when the line is
|
|
20
19
|
* not one of this tag's.
|
|
21
20
|
*/
|
|
22
21
|
function registeredFile(line, tagName) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* In-place rename of a custom element registration in customElements.js.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Removing the old entry and adding a new one would, on a registration
|
|
5
|
+
* list the remove path cannot see, leave the old entry beside the new one,
|
|
6
|
+
* and the new entry would lack the project marker every sibling line
|
|
7
|
+
* carries (`// <MARKER>:`), so the next lint would flag it as an unmarked
|
|
8
|
+
* engine edit. Rewriting the tag and module
|
|
9
9
|
* literals inside the existing entry keeps the entry's position, layout and
|
|
10
10
|
* trailing marker comments exactly as they were.
|
|
11
11
|
*/
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* In-place rename of a custom element registration in customElements.js.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Removing the old entry and adding a new one would, on a registration
|
|
6
|
+
* list the remove path cannot see, leave the old entry beside the new one,
|
|
7
|
+
* and the new entry would lack the project marker every sibling line
|
|
8
|
+
* carries (`// <MARKER>:`), so the next lint would flag it as an unmarked
|
|
9
|
+
* engine edit. Rewriting the tag and module
|
|
10
10
|
* literals inside the existing entry keeps the entry's position, layout and
|
|
11
11
|
* trailing marker comments exactly as they were.
|
|
12
12
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared validation for furnace custom element registration placement.
|
|
3
|
-
*
|
|
3
|
+
* Shared by the AST registration editor and the registration validator to
|
|
4
|
+
* avoid duplicating logic.
|
|
4
5
|
*/
|
|
5
6
|
/**
|
|
6
7
|
* Regex for valid custom element tag names. A valid name is lowercase, starts
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
3
|
* Shared validation for furnace custom element registration placement.
|
|
4
|
-
*
|
|
4
|
+
* Shared by the AST registration editor and the registration validator to
|
|
5
|
+
* avoid duplicating logic.
|
|
5
6
|
*/
|
|
6
7
|
import { FurnaceError } from '../errors/furnace.js';
|
|
7
8
|
import { escapeRegex, stripJsComments } from '../utils/regex.js';
|
|
@@ -252,8 +252,8 @@ export async function removeJarMnEntries(engineDir, tagName) {
|
|
|
252
252
|
// line the component registered is removed regardless of the target
|
|
253
253
|
// basename. A helper `.mjs` whose name does not start with the tag (e.g.
|
|
254
254
|
// a renamed `foo-utils.mjs`) otherwise survives the remove pass and leaves
|
|
255
|
-
// a stale registration that breaks packaging. The
|
|
256
|
-
//
|
|
255
|
+
// a stale registration that breaks packaging. The target-path match is
|
|
256
|
+
// kept as an OR for lines that carry no source mapping.
|
|
257
257
|
// Word boundaries keep "moz-card" from matching "moz-card-group".
|
|
258
258
|
const sourcePattern = new RegExp(`\\(widgets/${escapeRegex(tagName)}/`);
|
|
259
259
|
const legacyTargetPattern = new RegExp(`content/global/elements/${escapeRegex(tagName)}\\.`);
|
|
@@ -45,9 +45,10 @@ export const GIT_ADD_CHUNK_TIMEOUT_MS = resolveTimeoutFromEnv(GIT_ADD_CHUNK_TIME
|
|
|
45
45
|
/**
|
|
46
46
|
* In-flight or settled successful `git` availability probe.
|
|
47
47
|
*
|
|
48
|
-
* The probe spawns `which git` (or `where` on Windows)
|
|
49
|
-
*
|
|
50
|
-
*
|
|
48
|
+
* The probe spawns `which git` (or `where` on Windows); running it before
|
|
49
|
+
* every command would mean dozens of extra spawns per `fireforge export`, so
|
|
50
|
+
* the result is shared by every git wrapper in this layer. Only success is
|
|
51
|
+
* cached: a rejection
|
|
51
52
|
* clears the slot so a run that installs git mid-flight (or a test that flips
|
|
52
53
|
* the probe) sees the new answer instead of a sticky refusal.
|
|
53
54
|
*/
|
|
@@ -521,7 +521,7 @@ async function generateBinaryFilePatchWithConfig(repoDir, filePath, gitConfigArg
|
|
|
521
521
|
* "absent", and this branch only runs for files untracked in HEAD). A prior
|
|
522
522
|
* stage-0 entry is re-pointed at its recorded mode and blob. Unmerged entries
|
|
523
523
|
* (stages 1 to 3) cannot be rebuilt through `--cacheinfo`. That degenerate
|
|
524
|
-
* state
|
|
524
|
+
* state falls back to the reset-to-HEAD restore rather than corrupting the
|
|
525
525
|
* conflict.
|
|
526
526
|
* @param repoDir - Repository directory
|
|
527
527
|
* @param filePath - File path (relative to repo root)
|
package/dist/src/core/git.js
CHANGED
|
@@ -46,7 +46,7 @@ const GIT_ADD_ENV = { GIT_INDEX_THREADS: '0' };
|
|
|
46
46
|
* AbortError when the signal fires, so both shapes have to be recognised.
|
|
47
47
|
*/
|
|
48
48
|
function isTimeoutError(error) {
|
|
49
|
-
// `exec`
|
|
49
|
+
// `exec` rejects with a typed ExecTimeoutError when its `timeout`
|
|
50
50
|
// option fires (the raw AbortError check below is kept for defence in
|
|
51
51
|
// depth against other abort paths).
|
|
52
52
|
if (error instanceof ExecTimeoutError)
|
|
@@ -45,12 +45,12 @@ export interface OrphanedHarnessProcess {
|
|
|
45
45
|
* True when `command` IS a harness helper: its executable is a helper
|
|
46
46
|
* binary, or an interpreter whose first argument is a helper script.
|
|
47
47
|
*
|
|
48
|
-
* Structural on purpose.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
48
|
+
* Structural on purpose. Matching the helper names anywhere in the command
|
|
49
|
+
* line is right for the httpd (`xpcshell -g … -f …/server.js`) and wrong for
|
|
50
|
+
* everything that merely mentions such a path: an editor opened on
|
|
51
|
+
* `server.js`, a shell whose command text quotes it, a `grep` over the
|
|
52
|
+
* objdir. Report-only, that would print a misleading `kill`; under the reap
|
|
53
|
+
* posture it would terminate the operator's shell.
|
|
54
54
|
*/
|
|
55
55
|
export declare function matchesHarnessHelper(command: string): boolean;
|
|
56
56
|
/** Objdir provenance: an explicit objdir path, a `obj-…` path segment, or `_tests/`. */
|
|
@@ -55,12 +55,12 @@ function basename(token) {
|
|
|
55
55
|
* True when `command` IS a harness helper: its executable is a helper
|
|
56
56
|
* binary, or an interpreter whose first argument is a helper script.
|
|
57
57
|
*
|
|
58
|
-
* Structural on purpose.
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
58
|
+
* Structural on purpose. Matching the helper names anywhere in the command
|
|
59
|
+
* line is right for the httpd (`xpcshell -g … -f …/server.js`) and wrong for
|
|
60
|
+
* everything that merely mentions such a path: an editor opened on
|
|
61
|
+
* `server.js`, a shell whose command text quotes it, a `grep` over the
|
|
62
|
+
* objdir. Report-only, that would print a misleading `kill`; under the reap
|
|
63
|
+
* posture it would terminate the operator's shell.
|
|
64
64
|
*/
|
|
65
65
|
export function matchesHarnessHelper(command) {
|
|
66
66
|
const [exe, first] = command.trim().split(/\s+/);
|