@hominis/fireforge 0.45.0 → 0.46.1
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 +409 -446
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +21 -15
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +7 -2
- package/dist/src/cli.js +47 -47
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +3 -4
- package/dist/src/commands/build.js +27 -17
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -10
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
- package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
- package/dist/src/commands/doctor-furnace-jar.js +1 -1
- package/dist/src/commands/doctor-furnace.js +22 -22
- package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
- package/dist/src/commands/doctor-orphaned-harness.js +14 -23
- package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
- package/dist/src/commands/doctor-patch-manifest.js +7 -6
- package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
- package/dist/src/commands/doctor-source-pin.d.ts +12 -12
- package/dist/src/commands/doctor-source-pin.js +14 -14
- package/dist/src/commands/doctor-working-tree.d.ts +3 -3
- package/dist/src/commands/doctor-working-tree.js +3 -3
- package/dist/src/commands/doctor.d.ts +3 -1
- package/dist/src/commands/doctor.js +15 -16
- package/dist/src/commands/download.js +50 -37
- package/dist/src/commands/export-all.js +29 -12
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +29 -59
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +12 -12
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +7 -13
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +4 -6
- package/dist/src/commands/export-shared.d.ts +51 -32
- package/dist/src/commands/export-shared.js +17 -32
- package/dist/src/commands/export.js +14 -5
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
- package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
- package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
- package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
- package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
- package/dist/src/commands/furnace/chrome-doc.js +18 -18
- package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +7 -12
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +6 -9
- package/dist/src/commands/furnace/create-features.d.ts +2 -2
- package/dist/src/commands/furnace/create-features.js +2 -2
- package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
- package/dist/src/commands/furnace/create-mochikit.js +7 -7
- package/dist/src/commands/furnace/create-templates.d.ts +31 -15
- package/dist/src/commands/furnace/create-templates.js +20 -19
- package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
- package/dist/src/commands/furnace/create-xpcshell.js +8 -8
- package/dist/src/commands/furnace/create.d.ts +1 -1
- package/dist/src/commands/furnace/create.js +35 -29
- package/dist/src/commands/furnace/deploy.js +15 -6
- package/dist/src/commands/furnace/diff.js +7 -7
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/furnace/init.js +17 -16
- package/dist/src/commands/furnace/list.js +2 -2
- package/dist/src/commands/furnace/override.d.ts +1 -1
- package/dist/src/commands/furnace/override.js +43 -34
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +15 -7
- package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
- package/dist/src/commands/furnace/remove-mutations.js +19 -19
- package/dist/src/commands/furnace/remove-state.d.ts +1 -1
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +4 -8
- package/dist/src/commands/furnace/rename-browser-test.js +10 -15
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
- package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
- package/dist/src/commands/furnace/rename.js +36 -36
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +19 -16
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +22 -29
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +27 -12
- package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
- package/dist/src/commands/lint-per-run-checkjs.js +14 -15
- package/dist/src/commands/lint-report.d.ts +3 -3
- package/dist/src/commands/lint-report.js +4 -4
- package/dist/src/commands/lint.d.ts +5 -4
- package/dist/src/commands/lint.js +36 -36
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +4 -6
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +19 -20
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +23 -33
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
- package/dist/src/commands/patch/lint-ignore.js +33 -44
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +29 -15
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +41 -37
- package/dist/src/commands/patch/move-files.js +5 -14
- package/dist/src/commands/patch/patch-context.d.ts +1 -1
- package/dist/src/commands/patch/rename.d.ts +4 -4
- package/dist/src/commands/patch/rename.js +35 -49
- package/dist/src/commands/patch/reorder.js +35 -48
- package/dist/src/commands/patch/split-plan.d.ts +7 -8
- package/dist/src/commands/patch/split-plan.js +10 -13
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +50 -48
- package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +22 -28
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +20 -30
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +25 -3
- package/dist/src/commands/re-export-adjacent.js +40 -24
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +23 -27
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +33 -33
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +52 -44
- package/dist/src/commands/re-export-lint.d.ts +29 -30
- package/dist/src/commands/re-export-lint.js +36 -29
- package/dist/src/commands/re-export-options.d.ts +1 -1
- package/dist/src/commands/re-export-options.js +1 -1
- package/dist/src/commands/re-export-register.d.ts +1 -1
- package/dist/src/commands/re-export-register.js +1 -1
- package/dist/src/commands/re-export-scan.d.ts +1 -1
- package/dist/src/commands/re-export-scan.js +12 -9
- package/dist/src/commands/re-export-single.d.ts +23 -4
- package/dist/src/commands/re-export-single.js +39 -31
- package/dist/src/commands/re-export.js +35 -17
- package/dist/src/commands/rebase/abort.js +9 -14
- package/dist/src/commands/rebase/continue.js +20 -19
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +5 -5
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +20 -24
- package/dist/src/commands/register.js +5 -5
- package/dist/src/commands/reset.js +1 -1
- package/dist/src/commands/resolve.d.ts +2 -2
- package/dist/src/commands/resolve.js +21 -13
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +38 -51
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +20 -20
- package/dist/src/commands/setup.js +4 -10
- package/dist/src/commands/source.js +9 -2
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +6 -6
- package/dist/src/commands/status-json.d.ts +14 -13
- package/dist/src/commands/status-json.js +9 -8
- package/dist/src/commands/status-output.d.ts +3 -3
- package/dist/src/commands/status-output.js +5 -5
- package/dist/src/commands/status-ownership.d.ts +3 -3
- package/dist/src/commands/status-ownership.js +3 -3
- package/dist/src/commands/status.js +25 -26
- package/dist/src/commands/test-build-phase.d.ts +3 -3
- package/dist/src/commands/test-build-phase.js +48 -24
- package/dist/src/commands/test-diagnose.d.ts +1 -1
- package/dist/src/commands/test-diagnose.js +20 -20
- package/dist/src/commands/test-modes.d.ts +4 -4
- package/dist/src/commands/test-modes.js +4 -5
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +40 -33
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +17 -17
- package/dist/src/commands/test-verdict.d.ts +19 -5
- package/dist/src/commands/test-verdict.js +26 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +73 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +26 -10
- package/dist/src/commands/tree.js +26 -21
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +16 -16
- package/dist/src/commands/verify.d.ts +3 -3
- package/dist/src/commands/verify.js +10 -10
- package/dist/src/commands/watch.js +11 -11
- package/dist/src/commands/wire.js +17 -16
- package/dist/src/core/ast-utils.d.ts +7 -7
- package/dist/src/core/ast-utils.js +8 -8
- package/dist/src/core/branding.d.ts +5 -12
- package/dist/src/core/branding.js +6 -5
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +10 -7
- package/dist/src/core/build-audit-platform.d.ts +32 -3
- package/dist/src/core/build-audit-platform.js +153 -13
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +10 -9
- package/dist/src/core/build-audit-resolve.d.ts +5 -5
- package/dist/src/core/build-audit-resolve.js +6 -6
- package/dist/src/core/build-audit-skip.d.ts +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- package/dist/src/core/build-audit-transforms.d.ts +2 -2
- package/dist/src/core/build-audit-transforms.js +3 -3
- package/dist/src/core/build-audit.d.ts +21 -8
- package/dist/src/core/build-audit.js +142 -40
- package/dist/src/core/build-baseline-types.d.ts +19 -18
- package/dist/src/core/build-baseline-types.js +1 -1
- package/dist/src/core/build-baseline.d.ts +48 -31
- package/dist/src/core/build-baseline.js +20 -43
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +18 -17
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +14 -14
- package/dist/src/core/build-prepare.d.ts +4 -12
- package/dist/src/core/build-prepare.js +22 -26
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +3 -21
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +3 -3
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +22 -12
- package/dist/src/core/config.d.ts +12 -12
- package/dist/src/core/config.js +21 -25
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +20 -20
- package/dist/src/core/destructive.d.ts +14 -14
- package/dist/src/core/destructive.js +9 -9
- package/dist/src/core/diff-hunks.d.ts +2 -2
- package/dist/src/core/diff-hunks.js +7 -7
- package/dist/src/core/discard-baseline.d.ts +10 -10
- package/dist/src/core/discard-baseline.js +22 -23
- package/dist/src/core/display-state.d.ts +11 -11
- package/dist/src/core/display-state.js +12 -12
- package/dist/src/core/engine-changes.d.ts +2 -2
- package/dist/src/core/engine-changes.js +2 -2
- package/dist/src/core/engine-precondition.d.ts +5 -13
- package/dist/src/core/engine-precondition.js +5 -10
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +50 -54
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +14 -19
- package/dist/src/core/file-lock.js +90 -128
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +61 -36
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +38 -22
- package/dist/src/core/firefox-extract.d.ts +8 -7
- package/dist/src/core/firefox-extract.js +45 -27
- package/dist/src/core/firefox.d.ts +34 -36
- package/dist/src/core/firefox.js +13 -44
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +2 -8
- package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
- package/dist/src/core/furnace-apply-ftl.js +8 -8
- package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
- package/dist/src/core/furnace-apply-helpers.js +28 -39
- package/dist/src/core/furnace-apply-output.js +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
- package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
- package/dist/src/core/furnace-apply.d.ts +4 -4
- package/dist/src/core/furnace-apply.js +50 -29
- package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
- package/dist/src/core/furnace-checksum-utils.js +5 -5
- package/dist/src/core/furnace-config-custom.d.ts +1 -1
- package/dist/src/core/furnace-config-custom.js +2 -2
- package/dist/src/core/furnace-config-order.js +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +3 -3
- package/dist/src/core/furnace-config-tokens.js +3 -3
- package/dist/src/core/furnace-config-validate.js +2 -2
- package/dist/src/core/furnace-config.d.ts +5 -5
- package/dist/src/core/furnace-config.js +40 -53
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +9 -8
- package/dist/src/core/furnace-css-fragments.d.ts +6 -6
- package/dist/src/core/furnace-css-fragments.js +11 -11
- package/dist/src/core/furnace-dir-entry.d.ts +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- package/dist/src/core/furnace-jsconfig.d.ts +7 -7
- package/dist/src/core/furnace-jsconfig.js +22 -20
- package/dist/src/core/furnace-operation.d.ts +22 -19
- package/dist/src/core/furnace-operation.js +38 -34
- package/dist/src/core/furnace-precondition.d.ts +10 -10
- package/dist/src/core/furnace-precondition.js +8 -8
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +5 -8
- package/dist/src/core/furnace-registration-ast.d.ts +2 -3
- package/dist/src/core/furnace-registration-ast.js +9 -12
- package/dist/src/core/furnace-registration-remove.d.ts +4 -4
- package/dist/src/core/furnace-registration-remove.js +6 -6
- package/dist/src/core/furnace-registration-validate.d.ts +2 -2
- package/dist/src/core/furnace-registration-validate.js +2 -2
- package/dist/src/core/furnace-registration.d.ts +7 -6
- package/dist/src/core/furnace-registration.js +29 -36
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-stale-export.d.ts +17 -16
- package/dist/src/core/furnace-stale-export.js +16 -15
- package/dist/src/core/furnace-staleness.d.ts +2 -2
- package/dist/src/core/furnace-staleness.js +2 -2
- package/dist/src/core/furnace-state-persist.d.ts +12 -12
- package/dist/src/core/furnace-state-persist.js +10 -10
- package/dist/src/core/furnace-step-errors.d.ts +6 -6
- package/dist/src/core/furnace-step-errors.js +6 -6
- package/dist/src/core/furnace-validate-accessibility.js +14 -14
- package/dist/src/core/furnace-validate-compatibility.js +9 -9
- package/dist/src/core/furnace-validate-registration.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +18 -20
- package/dist/src/core/furnace-validate-structure.d.ts +1 -1
- package/dist/src/core/furnace-validate-structure.js +4 -4
- package/dist/src/core/furnace-validate.js +9 -9
- package/dist/src/core/furnace-version-drift.d.ts +5 -5
- package/dist/src/core/furnace-version-drift.js +5 -5
- package/dist/src/core/git-base.d.ts +6 -4
- package/dist/src/core/git-base.js +29 -7
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +13 -13
- package/dist/src/core/git-diff.js +121 -189
- package/dist/src/core/git-file-ops.d.ts +6 -13
- package/dist/src/core/git-file-ops.js +11 -35
- package/dist/src/core/git-readonly-index.d.ts +12 -14
- package/dist/src/core/git-readonly-index.js +12 -16
- package/dist/src/core/git-status.d.ts +9 -2
- package/dist/src/core/git-status.js +23 -11
- package/dist/src/core/git.d.ts +3 -9
- package/dist/src/core/git.js +28 -57
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +28 -27
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/license-headers.d.ts +19 -18
- package/dist/src/core/license-headers.js +29 -28
- package/dist/src/core/mach-build-artifacts.d.ts +21 -21
- package/dist/src/core/mach-build-artifacts.js +23 -23
- package/dist/src/core/mach-error-hints.d.ts +5 -10
- package/dist/src/core/mach-error-hints.js +14 -14
- package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
- package/dist/src/core/mach-known-noise-filter.js +57 -56
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +17 -16
- package/dist/src/core/mach-python.d.ts +3 -0
- package/dist/src/core/mach-python.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +24 -12
- package/dist/src/core/mach-resource-shim.js +124 -21
- package/dist/src/core/mach.d.ts +59 -73
- package/dist/src/core/mach.js +47 -115
- package/dist/src/core/marionette-port.d.ts +15 -30
- package/dist/src/core/marionette-port.js +46 -89
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +32 -50
- package/dist/src/core/markdown-table.d.ts +9 -9
- package/dist/src/core/markdown-table.js +14 -14
- package/dist/src/core/mochitest-server-port.d.ts +8 -8
- package/dist/src/core/mochitest-server-port.js +17 -17
- package/dist/src/core/module-resolution-preflight.d.ts +8 -8
- package/dist/src/core/module-resolution-preflight.js +11 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
- package/dist/src/core/moz-manifest-helpers.js +7 -7
- package/dist/src/core/moz-manifest-register.d.ts +1 -1
- package/dist/src/core/moz-manifest-register.js +2 -2
- package/dist/src/core/moz-manifest-rules.js +46 -42
- package/dist/src/core/moz-manifest-tokenizers.js +1 -1
- package/dist/src/core/ownership-table.d.ts +5 -5
- package/dist/src/core/ownership-table.js +7 -7
- package/dist/src/core/parser-fallback.d.ts +3 -3
- package/dist/src/core/parser-fallback.js +3 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
- package/dist/src/core/patch-apply-fuzz.js +13 -13
- package/dist/src/core/patch-apply.d.ts +13 -14
- package/dist/src/core/patch-apply.js +36 -42
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +21 -4
- package/dist/src/core/patch-export-update.js +7 -6
- package/dist/src/core/patch-export.d.ts +20 -30
- package/dist/src/core/patch-export.js +55 -77
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
- package/dist/src/core/patch-identifier-suggest.js +4 -4
- package/dist/src/core/patch-lint-binary.d.ts +12 -18
- package/dist/src/core/patch-lint-cache.d.ts +18 -2
- package/dist/src/core/patch-lint-cache.js +16 -19
- package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
- package/dist/src/core/patch-lint-checkjs.js +78 -64
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
- package/dist/src/core/patch-lint-creators.d.ts +5 -9
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +27 -19
- package/dist/src/core/patch-lint-cross.js +67 -110
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +15 -11
- package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
- package/dist/src/core/patch-lint-diff-tag.js +5 -5
- package/dist/src/core/patch-lint-diff.d.ts +4 -4
- package/dist/src/core/patch-lint-diff.js +4 -4
- package/dist/src/core/patch-lint-file-size.d.ts +3 -3
- package/dist/src/core/patch-lint-file-size.js +6 -6
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +46 -46
- package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
- package/dist/src/core/patch-lint-module-registration.js +1 -1
- package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
- package/dist/src/core/patch-lint-mozbuild.js +10 -10
- package/dist/src/core/patch-lint-observer.d.ts +3 -3
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint-ownership.d.ts +6 -6
- package/dist/src/core/patch-lint-ownership.js +6 -6
- package/dist/src/core/patch-lint-prettier.d.ts +6 -6
- package/dist/src/core/patch-lint-prettier.js +7 -7
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
- package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
- package/dist/src/core/patch-lint.d.ts +41 -35
- package/dist/src/core/patch-lint.js +52 -49
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +11 -11
- package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
- package/dist/src/core/patch-manifest-consistency.js +16 -17
- package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
- package/dist/src/core/patch-manifest-files-affected.js +3 -3
- package/dist/src/core/patch-manifest-io.d.ts +14 -14
- package/dist/src/core/patch-manifest-io.js +35 -34
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +4 -4
- package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
- package/dist/src/core/patch-manifest-resolve.js +7 -7
- package/dist/src/core/patch-manifest-validate.js +3 -3
- package/dist/src/core/patch-manifest.d.ts +2 -2
- package/dist/src/core/patch-manifest.js +2 -2
- package/dist/src/core/patch-parse.d.ts +32 -21
- package/dist/src/core/patch-parse.js +40 -15
- package/dist/src/core/patch-policy.js +15 -27
- package/dist/src/core/patch-registration-refs.d.ts +4 -4
- package/dist/src/core/patch-registration-refs.js +7 -7
- package/dist/src/core/patch-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +8 -16
- package/dist/src/core/patch-transform.js +13 -23
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +6 -6
- package/dist/src/core/rebase-session.d.ts +9 -15
- package/dist/src/core/rebase-session.js +13 -25
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- package/dist/src/core/register-result.d.ts +1 -1
- package/dist/src/core/register-result.js +1 -1
- package/dist/src/core/register-scaffold.d.ts +2 -2
- package/dist/src/core/register-scaffold.js +8 -7
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +6 -5
- package/dist/src/core/register-xpcshell-test.d.ts +2 -2
- package/dist/src/core/register-xpcshell-test.js +2 -2
- package/dist/src/core/run-log-redact.d.ts +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +21 -10
- package/dist/src/core/run-log.js +76 -27
- package/dist/src/core/shared-ftl.d.ts +2 -2
- package/dist/src/core/shared-ftl.js +6 -6
- package/dist/src/core/signal-critical.d.ts +2 -2
- package/dist/src/core/signal-critical.js +4 -6
- package/dist/src/core/smoke-patterns.d.ts +5 -6
- package/dist/src/core/smoke-patterns.js +15 -20
- package/dist/src/core/state-file.d.ts +15 -4
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-binary.d.ts +8 -8
- package/dist/src/core/status-binary.js +12 -12
- package/dist/src/core/status-classify.d.ts +17 -17
- package/dist/src/core/status-classify.js +13 -12
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +40 -25
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +69 -69
- package/dist/src/core/test-harness-output.d.ts +7 -7
- package/dist/src/core/test-harness-output.js +7 -7
- package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
- package/dist/src/core/test-harness-verdict-notes.js +4 -4
- package/dist/src/core/test-path-scope.d.ts +8 -8
- package/dist/src/core/test-path-scope.js +11 -11
- package/dist/src/core/test-stale-check.d.ts +22 -23
- package/dist/src/core/test-stale-check.js +31 -30
- package/dist/src/core/test-stale-symlink.d.ts +1 -1
- package/dist/src/core/test-stale-symlink.js +1 -1
- package/dist/src/core/test-stall-triage.d.ts +9 -9
- package/dist/src/core/test-stall-triage.js +22 -22
- package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +35 -2
- package/dist/src/core/token-category.js +67 -58
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +9 -9
- package/dist/src/core/token-dark-mode.js +13 -25
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +4 -4
- package/dist/src/core/token-manager.js +22 -22
- package/dist/src/core/token-scaffold.d.ts +4 -4
- package/dist/src/core/token-scaffold.js +4 -4
- package/dist/src/core/token-variant.d.ts +14 -14
- package/dist/src/core/token-variant.js +52 -53
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +23 -23
- package/dist/src/core/tree-cow.d.ts +3 -5
- package/dist/src/core/tree-cow.js +8 -8
- package/dist/src/core/tree-guard.d.ts +3 -3
- package/dist/src/core/tree-guard.js +23 -23
- package/dist/src/core/tree-store.d.ts +15 -15
- package/dist/src/core/tree-store.js +39 -38
- package/dist/src/core/typecheck-shim.d.ts +16 -15
- package/dist/src/core/typecheck-shim.js +26 -25
- package/dist/src/core/typecheck.d.ts +12 -12
- package/dist/src/core/typecheck.js +33 -33
- package/dist/src/core/wire-destroy.d.ts +2 -2
- package/dist/src/core/wire-destroy.js +5 -5
- package/dist/src/core/wire-dom-fragment.d.ts +3 -3
- package/dist/src/core/wire-dom-fragment.js +12 -23
- package/dist/src/core/wire-init.d.ts +2 -2
- package/dist/src/core/wire-init.js +7 -7
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +3 -3
- package/dist/src/core/wire-utils.d.ts +9 -9
- package/dist/src/core/wire-utils.js +16 -28
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +28 -30
- package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
- package/dist/src/core/xpcshell-profile-dir.js +7 -7
- package/dist/src/errors/base.d.ts +69 -16
- package/dist/src/errors/base.js +95 -26
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +26 -34
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +9 -9
- package/dist/src/errors/git.js +21 -31
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +11 -13
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +8 -8
- package/dist/src/errors/run.d.ts +1 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/types/commands/options.d.ts +155 -200
- package/dist/src/types/commands/patches.d.ts +19 -19
- package/dist/src/types/commands/project.d.ts +3 -3
- package/dist/src/types/config.d.ts +52 -19
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/types/json.d.ts +3 -3
- package/dist/src/types/json.js +2 -2
- package/dist/src/types/typecheck.d.ts +3 -3
- package/dist/src/utils/assert.d.ts +4 -16
- package/dist/src/utils/assert.js +7 -24
- package/dist/src/utils/build-info.d.ts +6 -6
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +7 -6
- package/dist/src/utils/child-env.js +5 -5
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +2 -2
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/errors.d.ts +8 -8
- package/dist/src/utils/errors.js +8 -8
- package/dist/src/utils/fs.d.ts +1 -1
- package/dist/src/utils/fs.js +15 -20
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.js +11 -11
- package/dist/src/utils/machine-output.js +2 -2
- package/dist/src/utils/options.d.ts +14 -20
- package/dist/src/utils/options.js +26 -27
- package/dist/src/utils/package-root.js +5 -14
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +10 -9
- package/dist/src/utils/process-group.js +37 -36
- package/dist/src/utils/process.d.ts +70 -55
- package/dist/src/utils/process.js +129 -179
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +9 -9
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/stdio-drain.d.ts +7 -7
- package/dist/src/utils/stdio-drain.js +8 -8
- package/dist/src/utils/validation.d.ts +12 -49
- package/dist/src/utils/validation.js +26 -36
- package/docs/README.md +2 -2
- package/docs/configuration.md +163 -69
- package/docs/exit-codes.md +66 -49
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +414 -247
- package/docs/machine-output.md +58 -34
- package/docs/patch-workflow.md +48 -44
- package/docs/run-logs.md +72 -28
- package/docs/testing.md +105 -98
- package/docs/verification-trees.md +23 -22
- package/package.json +7 -6
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* loop calls {@link reExportSinglePatchWithIndexLockRetry} per selected
|
|
6
6
|
* patch.
|
|
7
7
|
*/
|
|
8
|
-
import { getProjectPaths } from '../core/config.js';
|
|
9
8
|
import { stdioIsInteractive } from '../core/destructive.js';
|
|
10
9
|
import { enforceFreshFurnaceSources } from '../core/furnace-stale-export.js';
|
|
11
10
|
import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
@@ -14,6 +13,7 @@ import { updatePatchAndMetadata } from '../core/patch-export.js';
|
|
|
14
13
|
import { buildProjectedManifest, enforcePatchPolicy } from '../core/patch-policy.js';
|
|
15
14
|
import { isGitIndexLockConflict } from '../errors/git.js';
|
|
16
15
|
import { info, success, warn } from '../utils/logger.js';
|
|
16
|
+
import { sleep } from '../utils/sleep.js';
|
|
17
17
|
import { findMissingFiles, reportAdjacentUnmanagedFiles } from './re-export-adjacent.js';
|
|
18
18
|
import { reportForeignDrift } from './re-export-drift.js';
|
|
19
19
|
import { lintReExportedPatch, refreshQueueCtxEntry, storeReExportLintResult, } from './re-export-lint.js';
|
|
@@ -23,23 +23,24 @@ const GIT_INDEX_LOCK_RETRY_MS = 300;
|
|
|
23
23
|
* Retries a single patch re-export exactly once when the failure is
|
|
24
24
|
* transient git `index.lock` contention (an external git process holding
|
|
25
25
|
* the engine repo's index). The retry re-enters `reExportSinglePatch`
|
|
26
|
-
* from the top, so it re-reads clean state
|
|
26
|
+
* from the top, so it re-reads clean state. A second lock failure
|
|
27
27
|
* propagates to the loop's honest "N of M" accounting.
|
|
28
28
|
*/
|
|
29
|
-
export async function reExportSinglePatchWithIndexLockRetry(
|
|
29
|
+
export async function reExportSinglePatchWithIndexLockRetry(args) {
|
|
30
30
|
try {
|
|
31
|
-
return await reExportSinglePatch(
|
|
31
|
+
return await reExportSinglePatch(args);
|
|
32
32
|
}
|
|
33
33
|
catch (error) {
|
|
34
34
|
if (!isGitIndexLockConflict(error)) {
|
|
35
35
|
throw error;
|
|
36
36
|
}
|
|
37
|
-
warn(`${patch.filename}: git index.lock contention detected — retrying once after ${
|
|
38
|
-
await
|
|
39
|
-
return await reExportSinglePatch(
|
|
37
|
+
warn(`${args.patch.filename}: git index.lock contention detected — retrying once after ${GIT_INDEX_LOCK_RETRY_MS} ms...`);
|
|
38
|
+
await sleep(GIT_INDEX_LOCK_RETRY_MS);
|
|
39
|
+
return await reExportSinglePatch(args);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
async function reExportSinglePatch(
|
|
42
|
+
async function reExportSinglePatch(args) {
|
|
43
|
+
const { patch, paths, manifest, options, isDryRun, config, adjacentCtx, driftCtx, lintCtx } = args;
|
|
43
44
|
let currentFilesAffected = [...patch.filesAffected];
|
|
44
45
|
// --- Scan for new/removed files ---
|
|
45
46
|
if (options.scan) {
|
|
@@ -52,10 +53,10 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
52
53
|
...(options.scanFiles !== undefined ? { scanFiles: options.scanFiles } : {}),
|
|
53
54
|
});
|
|
54
55
|
// Forward-import gate at adoption time (runs in dry-run too): refuse
|
|
55
|
-
// to adopt unmanaged files that import modules created by
|
|
56
|
-
// patches
|
|
57
|
-
// field-reported footgun. Applies to broad --scan, --scan-file,
|
|
58
|
-
// the --scan-files bulk assignments alike.
|
|
56
|
+
// to adopt unmanaged files that import modules created by later
|
|
57
|
+
// patches, because the after-the-fact lint failure this leaves behind
|
|
58
|
+
// is the field-reported footgun. Applies to broad --scan, --scan-file,
|
|
59
|
+
// and the --scan-files bulk assignments alike.
|
|
59
60
|
await assertScanAdoptionsHaveNoForwardImports({
|
|
60
61
|
patchesDir: paths.patches,
|
|
61
62
|
engineDir: paths.engine,
|
|
@@ -81,7 +82,7 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
81
82
|
// When neither `--scan` nor `--files` is set and some of the manifest's
|
|
82
83
|
// claimed files no longer exist on disk, the re-export silently writes a
|
|
83
84
|
// refreshed body whose filesAffected still names the vanished paths.
|
|
84
|
-
// That is the documented contract, but it is also a footgun
|
|
85
|
+
// That is the documented contract, but it is also a footgun: a later
|
|
85
86
|
// `verify` then fails on manifest-consistency with no obvious trigger.
|
|
86
87
|
// Emit one advisory warning up-front when the drift is cheap to detect,
|
|
87
88
|
// so the operator can re-run with `--scan` or `--files` before the stale
|
|
@@ -91,9 +92,9 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
91
92
|
return false;
|
|
92
93
|
}
|
|
93
94
|
// --- Explicit file-subset path ---
|
|
94
|
-
// When --files is given, the target filesAffected is authoritative
|
|
95
|
+
// When --files is given, the target filesAffected is authoritative: drop
|
|
95
96
|
// anything not in the list, add anything new. This is the surgical repair
|
|
96
|
-
// primitive that replaces hand-editing patches.json
|
|
97
|
+
// primitive that replaces hand-editing patches.json. The user has already
|
|
97
98
|
// acknowledged via confirmDestructive (done in the caller) that any drop
|
|
98
99
|
// is intentional.
|
|
99
100
|
if (options.files !== undefined) {
|
|
@@ -108,16 +109,16 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
108
109
|
}
|
|
109
110
|
// Stale-furnace-source gate: re-export captures deployed engine copies, so
|
|
110
111
|
// a component source edited after the last furnace apply would land in the
|
|
111
|
-
// patch as its
|
|
112
|
+
// patch as its old deployed content. Refuse (or warn under
|
|
112
113
|
// --allow-stale-furnace) before diffing. Runs in dry-run too so the failure
|
|
113
114
|
// surfaces early.
|
|
114
115
|
await enforceFreshFurnaceSources(paths.root, currentFilesAffected, options.allowStaleFurnace === true, 're-export');
|
|
115
116
|
const absentFiles = await findMissingFiles(paths.engine, currentFilesAffected);
|
|
116
|
-
// A path absent from disk but tracked in engine HEAD is a
|
|
117
|
+
// A path absent from disk but tracked in engine HEAD is a deletion, and
|
|
117
118
|
// `git diff HEAD` renders it as a real `deleted file mode` section. Only
|
|
118
119
|
// a never-tracked path has nothing to diff. Skipping both alike meant a
|
|
119
120
|
// retired file quietly left the patch body while staying in its file
|
|
120
|
-
// list
|
|
121
|
+
// list, so the patch then claimed a file it could not restore.
|
|
121
122
|
const trackedAbsent = await listTrackedInHead(paths.engine, absentFiles);
|
|
122
123
|
const deletedFiles = absentFiles.filter((f) => trackedAbsent.has(f));
|
|
123
124
|
const untrackedAbsent = absentFiles.filter((f) => !trackedAbsent.has(f));
|
|
@@ -147,9 +148,9 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
147
148
|
}
|
|
148
149
|
// Foreign-drift preview + optional hard stop: show which
|
|
149
150
|
// payload lines are about to enter the body that the old body did not
|
|
150
|
-
// carry
|
|
151
|
-
//
|
|
152
|
-
// dry-run and --scan)
|
|
151
|
+
// carry, the case where a concurrent session's uncommitted edits in
|
|
152
|
+
// owned files would be silently absorbed. Always previews (including
|
|
153
|
+
// dry-run and --scan). Refuses only under --refuse-foreign-drift.
|
|
153
154
|
if (await reportForeignDrift({
|
|
154
155
|
patch,
|
|
155
156
|
patchesDir: paths.patches,
|
|
@@ -166,7 +167,7 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
166
167
|
command: 're-export',
|
|
167
168
|
forceUnsafe: options.forceUnsafe === true,
|
|
168
169
|
});
|
|
169
|
-
// Lint against the
|
|
170
|
+
// Lint against the once-per-invocation hoisted context (queue context +
|
|
170
171
|
// queue-wide checkJs program + per-patch result cache) instead of
|
|
171
172
|
// rebuilding ~37 s of setup for every patch in the loop.
|
|
172
173
|
const projectedMetadata = { ...patch, ...updates };
|
|
@@ -212,17 +213,24 @@ async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, co
|
|
|
212
213
|
* directory lock (a split write would let a concurrent queue mutation
|
|
213
214
|
* leave body and `filesAffected` disagreeing), then keeps the run's
|
|
214
215
|
* in-memory state honest: the queue context entry is refreshed and the
|
|
215
|
-
* fresh lint result is stored keyed against the just-written body
|
|
216
|
-
* state a repeat invocation will observe
|
|
216
|
+
* fresh lint result is stored keyed against the just-written body (the
|
|
217
|
+
* state a repeat invocation will observe), and the in-memory
|
|
217
218
|
* manifest row mirrors the on-disk write for later loop iterations
|
|
218
219
|
* (notably `--all --scan`, where `getClaimedFiles` reads this manifest).
|
|
219
220
|
*/
|
|
220
221
|
async function commitRefreshedPatch(args) {
|
|
221
222
|
const { patch, paths, manifest, options, config, lintCtx, diffContent, updates } = args;
|
|
222
|
-
const bodyChanged = await updatePatchAndMetadata(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
223
|
+
const bodyChanged = await updatePatchAndMetadata({
|
|
224
|
+
patchesDir: paths.patches,
|
|
225
|
+
filename: patch.filename,
|
|
226
|
+
newContent: diffContent,
|
|
227
|
+
updates,
|
|
228
|
+
onCommitted: undefined,
|
|
229
|
+
policyGate: {
|
|
230
|
+
config,
|
|
231
|
+
command: 're-export',
|
|
232
|
+
forceUnsafe: options.forceUnsafe === true,
|
|
233
|
+
},
|
|
226
234
|
});
|
|
227
235
|
refreshQueueCtxEntry(lintCtx, patch.filename, diffContent);
|
|
228
236
|
if (args.lintResult !== null) {
|
|
@@ -238,8 +246,8 @@ async function commitRefreshedPatch(args) {
|
|
|
238
246
|
};
|
|
239
247
|
}
|
|
240
248
|
}
|
|
241
|
-
// A bulk run refreshes every patch
|
|
242
|
-
// did not move buries the patches that
|
|
249
|
+
// A bulk run refreshes every patch. Saying "Re-exported" for one whose body
|
|
250
|
+
// did not move buries the patches that did move. The run still counts this
|
|
243
251
|
// patch as successfully refreshed, so `--stamp` completeness is unaffected.
|
|
244
252
|
if (bodyChanged) {
|
|
245
253
|
success(`Re-exported ${patch.filename}`);
|
|
@@ -250,7 +258,7 @@ async function commitRefreshedPatch(args) {
|
|
|
250
258
|
}
|
|
251
259
|
/**
|
|
252
260
|
* Threads the patch's own `lintIgnore` list through so the per-patch
|
|
253
|
-
* suppression honoured by export/export-all is also honoured here
|
|
261
|
+
* suppression honoured by export/export-all is also honoured here. A
|
|
254
262
|
* re-export could otherwise not refresh an advisory-noisy but intentional
|
|
255
263
|
* patch without the blunt `--skip-lint`. The paired `patch.tier` threads the
|
|
256
264
|
* explicit branding-threshold opt-in the same way. The CLI flags `--tier`
|
|
@@ -9,7 +9,7 @@ import { loadPatchesManifest, resolvePatchIdentifier, stampPatchVersions, } from
|
|
|
9
9
|
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
10
10
|
import { elapsedSince } from '../utils/elapsed.js';
|
|
11
11
|
import { toError } from '../utils/errors.js';
|
|
12
|
-
import { cancel, info, intro, isCancel, outro, spinner, success, warn } from '../utils/logger.js';
|
|
12
|
+
import { cancel, info, intro, isCancel, outro, spinner, success, warn, } from '../utils/logger.js';
|
|
13
13
|
import { loadScanFilesAssignments, withDryRunPurityGuard, withDryRunReExportLock, } from './re-export-bulk-scan.js';
|
|
14
14
|
import { warnUnseenExpectedDrift } from './re-export-drift.js';
|
|
15
15
|
import { reExportFilesInPlace } from './re-export-files.js';
|
|
@@ -26,15 +26,16 @@ async function resolveSelectedPatches(patches, options, manifest) {
|
|
|
26
26
|
for (const identifier of patches) {
|
|
27
27
|
const match = resolvePatchIdentifier(identifier, manifest.patches);
|
|
28
28
|
if (!match) {
|
|
29
|
-
// Suggest
|
|
30
|
-
// whole ~300-entry manifest, burying the
|
|
29
|
+
// Suggest close matches instead of dumping the queue: a wrong guess
|
|
30
|
+
// would otherwise print the whole ~300-entry manifest, burying the
|
|
31
|
+
// error it was reporting.
|
|
31
32
|
throw new InvalidArgumentError(formatPatchNotFoundError(identifier, manifest.patches), identifier);
|
|
32
33
|
}
|
|
33
34
|
selectedPatches.push(match);
|
|
34
35
|
}
|
|
35
36
|
return selectedPatches;
|
|
36
37
|
}
|
|
37
|
-
// No patches specified
|
|
38
|
+
// No patches specified: prompt or error
|
|
38
39
|
const isInteractive = stdioIsInteractive();
|
|
39
40
|
if (!isInteractive) {
|
|
40
41
|
throw new InvalidArgumentError('Specify patch identifiers or use --all in non-interactive mode.\n\n' +
|
|
@@ -143,7 +144,17 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
143
144
|
const patchOptions = assignedScanFiles !== undefined ? { ...options, scanFiles: assignedScanFiles } : options;
|
|
144
145
|
progress.message(`Re-exporting ${index + 1}/${selectedPatches.length}: ${patch.filename} (${patch.filesAffected.length} file(s), ${elapsedSince(startedAt)} elapsed)...`);
|
|
145
146
|
try {
|
|
146
|
-
const exported = await reExportSinglePatchWithIndexLockRetry(
|
|
147
|
+
const exported = await reExportSinglePatchWithIndexLockRetry({
|
|
148
|
+
patch,
|
|
149
|
+
paths,
|
|
150
|
+
manifest,
|
|
151
|
+
options: patchOptions,
|
|
152
|
+
isDryRun,
|
|
153
|
+
config,
|
|
154
|
+
adjacentCtx,
|
|
155
|
+
driftCtx,
|
|
156
|
+
lintCtx,
|
|
157
|
+
});
|
|
147
158
|
if (exported) {
|
|
148
159
|
reExported++;
|
|
149
160
|
reExportedFilenames.push(patch.filename);
|
|
@@ -166,7 +177,7 @@ export async function reExportCommand(projectRoot, patches, options) {
|
|
|
166
177
|
}
|
|
167
178
|
// `--stamp` only fires on a run where every selected patch refreshed
|
|
168
179
|
// cleanly. A partial success would leave some patches with a stale body
|
|
169
|
-
// but a new version
|
|
180
|
+
// but a new version, the opposite of the "what I tested, what the
|
|
170
181
|
// manifest says" invariant `sourceEsrVersion` exists to record. A
|
|
171
182
|
// non-empty `reExportedFilenames` with fewer entries than `selectedPatches`
|
|
172
183
|
// means a lint failure or missing-file skip landed somewhere in the loop,
|
|
@@ -204,7 +215,7 @@ function buildForeignDriftContext(options) {
|
|
|
204
215
|
/**
|
|
205
216
|
* Names `--expect-unmanaged` paths that were never met this run. A typo'd
|
|
206
217
|
* carve-out silently leaves the refusal armed for the path it was meant to
|
|
207
|
-
* admit
|
|
218
|
+
* admit, and reads as an approval that is in force when it is not.
|
|
208
219
|
* A warning rather than a refusal: an approved path legitimately goes unmet
|
|
209
220
|
* when the reviewed file has since been adopted into a patch, which is the
|
|
210
221
|
* outcome the carve-out exists to be retired by.
|
|
@@ -227,19 +238,26 @@ function warnUnseenApprovedUnmanaged(adjacentCtx) {
|
|
|
227
238
|
function throwRunLevelRefusals(adjacentCtx, driftCtx, progress) {
|
|
228
239
|
if (adjacentCtx.refusals.length > 0) {
|
|
229
240
|
progress.error('Re-export refused');
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
241
|
+
// Each offender is named with the owned directory that made it
|
|
242
|
+
// adjacent: an unattended run reads only this line, and without the
|
|
243
|
+
// anchor it cannot tell which of a multi-directory patch's locations
|
|
244
|
+
// the file sits beside.
|
|
245
|
+
const offenders = adjacentCtx.refusals
|
|
246
|
+
.map((r) => `${r.patchFilename} (${r.anchored.join(', ')})`)
|
|
247
|
+
.join('; ');
|
|
248
|
+
throw new GeneralError(`Refused ${adjacentCtx.refusals.length} patch(es) with adjacent unmanaged files ` +
|
|
249
|
+
`(--refuse-adjacent-unmanaged): ${offenders}. Adjacent means the file sits in a ` +
|
|
250
|
+
`directory the patch already owns a file in. Adopt reviewed files with ` +
|
|
251
|
+
`--scan --scan-file, or export them as a new patch.`);
|
|
234
252
|
}
|
|
235
253
|
if (driftCtx.refusals.length > 0) {
|
|
236
254
|
progress.error('Re-export refused');
|
|
237
255
|
const names = driftCtx.refusals.map((r) => r.patchFilename).join(', ');
|
|
238
256
|
const unreadable = driftCtx.refusals.filter((r) => r.reason === 'baseline-unreadable');
|
|
239
257
|
const unreadablePart = unreadable.length > 0
|
|
240
|
-
? ` ${
|
|
258
|
+
? ` ${unreadable.length} of these refused because the old patch body was missing or unreadable, so the drift comparison could not run (fail-closed).`
|
|
241
259
|
: '';
|
|
242
|
-
throw new GeneralError(`Refused ${
|
|
260
|
+
throw new GeneralError(`Refused ${driftCtx.refusals.length} patch(es) whose refreshed body would absorb ` +
|
|
243
261
|
`engine edits not present in the old patch body (--refuse-foreign-drift): ${names}.${unreadablePart}\n\n` +
|
|
244
262
|
'The flag cannot tell WHO wrote those lines, and the two populations have opposite ' +
|
|
245
263
|
'remedies:\n' +
|
|
@@ -254,7 +272,7 @@ function throwRunLevelRefusals(adjacentCtx, driftCtx, progress) {
|
|
|
254
272
|
* Prints the end-of-run summary and enforces the exit contract: a partial run
|
|
255
273
|
* exits non-zero by default. "Re-exported 2 of 3" printing with exit 0 lets a
|
|
256
274
|
* partial refresh ride an `&&` chain as success. The summary still prints
|
|
257
|
-
* first so the honest "N of M" accounting stays visible
|
|
275
|
+
* first so the honest "N of M" accounting stays visible. The throw then
|
|
258
276
|
* carries the failed/skipped breakdown. Dry-run included: a preview
|
|
259
277
|
* reporting that the real run would partially fail must not read as a passing
|
|
260
278
|
* preview in scripts.
|
|
@@ -283,9 +301,9 @@ function reportReExportOutcome(args) {
|
|
|
283
301
|
if (reExported < selectedCount) {
|
|
284
302
|
const skippedCount = selectedCount - reExported - args.failedFilenames.length;
|
|
285
303
|
const failedPart = args.failedFilenames.length > 0 ? ` Failed: ${args.failedFilenames.join(', ')}.` : '';
|
|
286
|
-
const skippedPart = skippedCount > 0 ? ` Skipped: ${
|
|
287
|
-
throw new GeneralError(`${isDryRun ? '[dry-run] Would re-export' : 'Re-exported'} only ${
|
|
288
|
-
`${
|
|
304
|
+
const skippedPart = skippedCount > 0 ? ` Skipped: ${skippedCount} patch(es) (see warnings above).` : '';
|
|
305
|
+
throw new GeneralError(`${isDryRun ? '[dry-run] Would re-export' : 'Re-exported'} only ${reExported} of ` +
|
|
306
|
+
`${selectedCount} selected patch(es).${failedPart}${skippedPart} ` +
|
|
289
307
|
'Partial re-export exits non-zero so it cannot pass as success in scripts; ' +
|
|
290
308
|
'the per-patch errors are listed above.');
|
|
291
309
|
}
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Rebase abort flow.
|
|
4
4
|
*/
|
|
5
|
-
import { getProjectPaths
|
|
5
|
+
import { getProjectPaths } from '../../core/config.js';
|
|
6
6
|
import { clearAppliedFurnaceState } from '../../core/furnace-config.js';
|
|
7
7
|
import { resetChanges } from '../../core/git.js';
|
|
8
8
|
import { clearRebaseSession, getRebaseSessionPath, readRebaseSession, } from '../../core/rebase-session.js';
|
|
9
9
|
import { NoRebaseSessionError } from '../../errors/rebase.js';
|
|
10
10
|
import { intro, outro, spinner, success, warn } from '../../utils/logger.js';
|
|
11
|
+
import { clearPendingResolution } from '../pending-resolution.js';
|
|
11
12
|
import { confirmDirtyEngineReset } from './confirm.js';
|
|
12
13
|
/**
|
|
13
14
|
* Handles `fireforge rebase --abort`.
|
|
14
15
|
*/
|
|
15
16
|
export async function handleAbort(projectRoot, yes) {
|
|
16
17
|
intro('FireForge Rebase — Abort');
|
|
17
|
-
// Abort is the escape hatch, so it
|
|
18
|
-
//
|
|
19
|
-
//
|
|
18
|
+
// Abort is the escape hatch, so it does not require a valid session, only
|
|
19
|
+
// that one is present. Nothing below reads the session object (the restore
|
|
20
|
+
// works off `paths.engine` and `resetChanges`), and an
|
|
20
21
|
// `if (!session) throw` would refuse to run against a corrupt file, which
|
|
21
22
|
// is the only thing that could have cleared it.
|
|
22
23
|
const read = await readRebaseSession(projectRoot);
|
|
@@ -39,8 +40,8 @@ export async function handleAbort(projectRoot, yes) {
|
|
|
39
40
|
return;
|
|
40
41
|
}
|
|
41
42
|
const s = spinner('Restoring engine to pre-rebase state...');
|
|
42
|
-
// Step 1: git reset. If this fails, the rebase session
|
|
43
|
-
// so the user can retry the abort
|
|
43
|
+
// Step 1: git reset. If this fails, the rebase session must stay on disk
|
|
44
|
+
// so the user can retry the abort: resetChanges is the only irreversible
|
|
44
45
|
// operation in this handler and everything downstream assumes it ran.
|
|
45
46
|
try {
|
|
46
47
|
await resetChanges(paths.engine);
|
|
@@ -57,14 +58,8 @@ export async function handleAbort(projectRoot, yes) {
|
|
|
57
58
|
// idempotently re-clear furnace state.
|
|
58
59
|
await clearAppliedFurnaceState(projectRoot);
|
|
59
60
|
// Step 3: clear pending resolution transactionally.
|
|
60
|
-
await
|
|
61
|
-
|
|
62
|
-
return current;
|
|
63
|
-
const next = { ...current };
|
|
64
|
-
delete next.pendingResolution;
|
|
65
|
-
return next;
|
|
66
|
-
});
|
|
67
|
-
// Step 4: clear the rebase session LAST so a failure in any prior step
|
|
61
|
+
await clearPendingResolution(projectRoot);
|
|
62
|
+
// Step 4: clear the rebase session last so a failure in any prior step
|
|
68
63
|
// preserves the session on disk and a retry of --abort can succeed.
|
|
69
64
|
await clearRebaseSession(projectRoot);
|
|
70
65
|
success('Rebase aborted and session cleared.');
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Rebase --continue flow.
|
|
4
4
|
*/
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { getProjectPaths
|
|
6
|
+
import { getProjectPaths } from '../../core/config.js';
|
|
7
7
|
import { getStagedDiffForFiles } from '../../core/git-diff.js';
|
|
8
8
|
import { stageFiles, unstageFiles } from '../../core/git-file-ops.js';
|
|
9
9
|
import { updatePatchAndMetadata } from '../../core/patch-export.js';
|
|
@@ -14,13 +14,14 @@ import { GeneralError } from '../../errors/base.js';
|
|
|
14
14
|
import { CorruptRebaseSessionError, NoRebaseSessionError, RebaseError, } from '../../errors/rebase.js';
|
|
15
15
|
import { pathExists } from '../../utils/fs.js';
|
|
16
16
|
import { info, intro, success, warn } from '../../utils/logger.js';
|
|
17
|
+
import { clearPendingResolution } from '../pending-resolution.js';
|
|
17
18
|
import { runPatchLoop } from './patch-loop.js';
|
|
18
19
|
/**
|
|
19
20
|
* Handles `fireforge rebase --continue`.
|
|
20
21
|
*/
|
|
21
22
|
export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
22
23
|
intro('FireForge Rebase — Continue');
|
|
23
|
-
// A present-but-unreadable session is
|
|
24
|
+
// A present-but-unreadable session is not "no session in progress". That
|
|
24
25
|
// conflation is what made a corrupt file unrecoverable. Name the file and
|
|
25
26
|
// point at --abort, which can now clear it.
|
|
26
27
|
const read = await readRebaseSession(projectRoot);
|
|
@@ -33,10 +34,10 @@ export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
|
33
34
|
const paths = getProjectPaths(projectRoot);
|
|
34
35
|
// Special case: every patch has already applied but a previous run failed
|
|
35
36
|
// somewhere in the post-apply work (re-export, version stamping). In that
|
|
36
|
-
// state currentIndex is past the end of the queue
|
|
37
|
+
// state currentIndex is past the end of the queue. Jumping straight back
|
|
37
38
|
// into runPatchLoop replays the no-op apply loop and re-attempts the
|
|
38
|
-
// post-apply pipeline. Without this branch the user would be stuck
|
|
39
|
-
//
|
|
39
|
+
// post-apply pipeline. Without this branch the user would be stuck: there
|
|
40
|
+
// is no failed patch to resolve, but the session is still active.
|
|
40
41
|
if (session.currentIndex >= session.patches.length) {
|
|
41
42
|
info('All patches already applied; retrying post-apply re-export and version stamping.');
|
|
42
43
|
await runPatchLoop(projectRoot, session, paths, maxFuzz, waitLockSeconds);
|
|
@@ -77,10 +78,15 @@ export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
|
77
78
|
// updatePatchMetadata sequence can interleave with a concurrent export /
|
|
78
79
|
// re-export / patch reorder / patch compact and leave the manifest
|
|
79
80
|
// disagreeing with the freshly-written patch body. Mirrors resolve.ts.
|
|
80
|
-
await updatePatchAndMetadata(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
await updatePatchAndMetadata({
|
|
82
|
+
patchesDir: paths.patches,
|
|
83
|
+
filename: currentPatch.filename,
|
|
84
|
+
newContent: diffContent,
|
|
85
|
+
updates: {
|
|
86
|
+
sourceEsrVersion: session.toVersion,
|
|
87
|
+
sourceVersion: session.toVersion,
|
|
88
|
+
...(session.toProduct !== undefined ? { sourceProduct: session.toProduct } : {}),
|
|
89
|
+
},
|
|
84
90
|
});
|
|
85
91
|
}
|
|
86
92
|
finally {
|
|
@@ -93,9 +99,10 @@ export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
|
93
99
|
// clear is held until both writes land, matching the guarantee the apply
|
|
94
100
|
// loop in patch-loop.ts provides.
|
|
95
101
|
await runInSignalCriticalSection(`rebase-continue:${currentPatch.filename}`, async () => {
|
|
96
|
-
//
|
|
97
|
-
// failure's `error` and `conflictingFiles` on a
|
|
98
|
-
// persist that to the session file. The union
|
|
102
|
+
// The entry is replaced rather than mutated. Flipping `status` in place
|
|
103
|
+
// would leave the failure's `error` and `conflictingFiles` on a
|
|
104
|
+
// now-resolved entry and persist that to the session file. The union
|
|
105
|
+
// type rules that out.
|
|
99
106
|
session.patches[session.currentIndex] = {
|
|
100
107
|
filename: currentPatch.filename,
|
|
101
108
|
status: 'resolved',
|
|
@@ -104,13 +111,7 @@ export async function handleContinue(projectRoot, maxFuzz, waitLockSeconds) {
|
|
|
104
111
|
await saveRebaseSession(projectRoot, session);
|
|
105
112
|
// Clear pending resolution transactionally so concurrent state-file
|
|
106
113
|
// writes to unrelated keys are not clobbered by a stale reload.
|
|
107
|
-
await
|
|
108
|
-
if (!current.pendingResolution)
|
|
109
|
-
return current;
|
|
110
|
-
const next = { ...current };
|
|
111
|
-
delete next.pendingResolution;
|
|
112
|
-
return next;
|
|
113
|
-
});
|
|
114
|
+
await clearPendingResolution(projectRoot);
|
|
114
115
|
});
|
|
115
116
|
success(`Resolved ${currentPatch.filename}`);
|
|
116
117
|
// Continue applying remaining patches
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* `fireforge rebase
|
|
3
|
+
* `fireforge rebase`: semi-automated Firefox source version upgrade.
|
|
4
4
|
*
|
|
5
5
|
* Orchestrates the full patch-rebase workflow:
|
|
6
6
|
* 1. Reset engine to baseline
|
|
@@ -17,7 +17,7 @@ import { clearAppliedFurnaceState } from '../../core/furnace-config.js';
|
|
|
17
17
|
import { getHead, resetChanges } from '../../core/git.js';
|
|
18
18
|
import { discoverPatches } from '../../core/patch-files.js';
|
|
19
19
|
import { loadPatchesManifest } from '../../core/patch-manifest.js';
|
|
20
|
-
import {
|
|
20
|
+
import { getPatchSourceVersion } from '../../core/patch-source-metadata.js';
|
|
21
21
|
import { getRebaseSessionPath, readRebaseSession, saveRebaseSession, } from '../../core/rebase-session.js';
|
|
22
22
|
import { GeneralError } from '../../errors/base.js';
|
|
23
23
|
import { CorruptRebaseSessionError, RebaseSessionExistsError } from '../../errors/rebase.js';
|
|
@@ -33,7 +33,7 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
33
33
|
const isDryRun = options.dryRun === true;
|
|
34
34
|
const maxFuzz = options.maxFuzz ?? 3;
|
|
35
35
|
intro(isDryRun ? 'FireForge Rebase (dry run)' : 'FireForge Rebase');
|
|
36
|
-
// One read decides liveness
|
|
36
|
+
// One read decides liveness and validity: a pathExists pre-probe here left
|
|
37
37
|
// a window where the file vanished between probe and read, reporting
|
|
38
38
|
// "already in progress" with no session on disk.
|
|
39
39
|
const existing = await readRebaseSession(projectRoot);
|
|
@@ -59,7 +59,7 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
59
59
|
}
|
|
60
60
|
// Determine the "from" version from the patches
|
|
61
61
|
const patchVersions = new Set(manifest.patches.map((p) => getPatchSourceVersion(p)));
|
|
62
|
-
const patchProducts = new Set(manifest.patches.map((p) =>
|
|
62
|
+
const patchProducts = new Set(manifest.patches.map((p) => p.sourceProduct).filter(Boolean));
|
|
63
63
|
const sortedVersions = [...patchVersions].sort();
|
|
64
64
|
const fromVersion = sortedVersions[0] ?? currentVersion;
|
|
65
65
|
const fromProduct = [...patchProducts].sort()[0] ?? config.firefox.product;
|
|
@@ -93,7 +93,7 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
93
93
|
const resetSpinner = spinner('Resetting engine to baseline...');
|
|
94
94
|
await resetChanges(paths.engine);
|
|
95
95
|
resetSpinner.stop('Engine reset to baseline');
|
|
96
|
-
// Clear Furnace state
|
|
96
|
+
// Clear Furnace state: the engine no longer contains deployed components.
|
|
97
97
|
await clearAppliedFurnaceState(projectRoot);
|
|
98
98
|
// Create rebase session
|
|
99
99
|
const allPatches = await discoverPatches(paths.patches);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Patch application loop and re-export flow.
|
|
3
3
|
*/
|
|
4
|
-
import type { getProjectPaths } from '../../core/config.js';
|
|
5
4
|
import type { RebaseSession } from '../../core/rebase-session.js';
|
|
5
|
+
import type { ProjectPaths } from '../../types/config.js';
|
|
6
6
|
/**
|
|
7
7
|
* Runs the patch application loop, re-exports applied patches, and stamps versions.
|
|
8
8
|
*
|
|
@@ -12,4 +12,4 @@ import type { RebaseSession } from '../../core/rebase-session.js';
|
|
|
12
12
|
* @param maxFuzz - Maximum context-reduction steps for `git apply -C<n>`
|
|
13
13
|
* @param waitLockSeconds - `--wait-lock` budget for the patch-directory lock
|
|
14
14
|
*/
|
|
15
|
-
export declare function runPatchLoop(projectRoot: string, session: RebaseSession, paths:
|
|
15
|
+
export declare function runPatchLoop(projectRoot: string, session: RebaseSession, paths: ProjectPaths, maxFuzz: number, waitLockSeconds?: number): Promise<void>;
|
|
@@ -20,13 +20,14 @@ import { toError } from '../../utils/errors.js';
|
|
|
20
20
|
import { pathExists } from '../../utils/fs.js';
|
|
21
21
|
import { error, info, outro, spinner, success, warn } from '../../utils/logger.js';
|
|
22
22
|
import { isValidFirefoxVersion } from '../../utils/validation.js';
|
|
23
|
+
import { clearPendingResolution } from '../pending-resolution.js';
|
|
23
24
|
import { buildRebaseConflictSummary } from './conflict-summary.js';
|
|
24
25
|
import { printSummary } from './summary.js';
|
|
25
26
|
/**
|
|
26
27
|
* Builds the session entry for a patch-apply outcome.
|
|
27
28
|
*
|
|
28
|
-
*
|
|
29
|
-
* discriminated union
|
|
29
|
+
* The entry is constructed whole rather than assigned field by field, so the
|
|
30
|
+
* discriminated union stops a status being flipped while the previous
|
|
30
31
|
* status's payload stays behind, which is how
|
|
31
32
|
* `{ status: 'resolved', error, conflictingFiles }` reaches the session file.
|
|
32
33
|
*
|
|
@@ -67,9 +68,10 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
67
68
|
const patchFile = allPatches.find((p) => p.filename === entry.filename);
|
|
68
69
|
if (!patchFile) {
|
|
69
70
|
warn(`Patch file not found for ${entry.filename}, skipping.`);
|
|
70
|
-
//
|
|
71
|
-
// change is a new value rather than a field
|
|
72
|
-
//
|
|
71
|
+
// The entry is replaced rather than mutated: it is a discriminated
|
|
72
|
+
// union, so a status change is a new value rather than a field
|
|
73
|
+
// assignment, and a status flip cannot strand the previous status's
|
|
74
|
+
// payload.
|
|
73
75
|
session.patches[i] = { filename: entry.filename, status: 'skipped' };
|
|
74
76
|
session.currentIndex = i + 1;
|
|
75
77
|
await saveRebaseSession(projectRoot, session);
|
|
@@ -100,9 +102,9 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
100
102
|
}
|
|
101
103
|
else {
|
|
102
104
|
// Set pendingResolution in state for visibility. Kept outside the
|
|
103
|
-
// critical section
|
|
104
|
-
// and its absence would at most cause `fireforge status`
|
|
105
|
-
// pending-conflict hint until the next state write.
|
|
105
|
+
// critical section, since it is advisory UX rather than a correctness
|
|
106
|
+
// invariant, and its absence would at most cause `fireforge status`
|
|
107
|
+
// to omit the pending-conflict hint until the next state write.
|
|
106
108
|
await updateState(projectRoot, (current) => ({
|
|
107
109
|
...current,
|
|
108
110
|
pendingResolution: {
|
|
@@ -144,7 +146,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
144
146
|
s.stop('All patches applied');
|
|
145
147
|
// Re-export all successfully applied patches. Failures here mean the
|
|
146
148
|
// engine has been rebased onto the new Firefox version but some .patch
|
|
147
|
-
// files were not refreshed
|
|
149
|
+
// files were not refreshed, so the queue would lie about what version each
|
|
148
150
|
// patch was tested against if we proceeded to stamp. Refuse to claim
|
|
149
151
|
// success and leave the session in place so the user can recover via
|
|
150
152
|
// `fireforge rebase --continue` after fixing the underlying cause.
|
|
@@ -163,7 +165,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
163
165
|
`still describe the pre-rebase source. Re-export them manually (e.g. ` +
|
|
164
166
|
`"fireforge re-export") and verify the overlapping hunks before the next import.`);
|
|
165
167
|
}
|
|
166
|
-
// Stamp versions
|
|
168
|
+
// Stamp versions, only for patches whose .patch file now actually
|
|
167
169
|
// reflects the new source (overlap-skipped ones keep their old stamp so
|
|
168
170
|
// the queue does not lie about what each patch was tested against).
|
|
169
171
|
const overlapSkippedSet = new Set(overlapSkipped);
|
|
@@ -176,19 +178,19 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
176
178
|
}
|
|
177
179
|
// Stamp every Furnace override's `baseVersion` to match the rebased
|
|
178
180
|
// Firefox source version. Without it, a successful source bump leaves
|
|
179
|
-
// overrides in a doctor-failing drift state
|
|
180
|
-
// pre-rebase source as its baseline
|
|
181
|
+
// overrides in a doctor-failing drift state, each still claiming the
|
|
182
|
+
// pre-rebase source as its baseline, and every subsequent
|
|
181
183
|
// `fireforge doctor` fails `Furnace component validation`. The stamp is
|
|
182
184
|
// unconditional per the helper's contract: rebase already succeeded on
|
|
183
185
|
// the patch side, so the operator is committing to the new source
|
|
184
|
-
// baseline
|
|
186
|
+
// baseline. Per-component health checking stays with
|
|
185
187
|
// `fireforge furnace validate` / `doctor --repair-furnace`.
|
|
186
188
|
//
|
|
187
189
|
// "Unconditional" means unconditional on component health, not on the
|
|
188
190
|
// value: `stampFurnaceOverrideBaseVersions` assigns and persists whatever
|
|
189
191
|
// string it is handed, so a session whose `toVersion` is not a real
|
|
190
192
|
// Firefox version would rewrite every override's baseline to that value.
|
|
191
|
-
// `isValidSession` rejects such a session at read time
|
|
193
|
+
// `isValidSession` rejects such a session at read time. This refuses to
|
|
192
194
|
// persist it even if a future caller reaches here another way.
|
|
193
195
|
if (!isValidFirefoxVersion(session.toVersion)) {
|
|
194
196
|
throw new RebaseError(`Refusing to stamp Furnace override baseVersion(s): the rebase session's target version ` +
|
|
@@ -208,13 +210,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz, waitLoc
|
|
|
208
210
|
await clearRebaseSession(projectRoot);
|
|
209
211
|
// Clear pending resolution if any (transactionally, so a concurrent
|
|
210
212
|
// state write to an unrelated key is not clobbered by a stale reload).
|
|
211
|
-
await
|
|
212
|
-
if (!current.pendingResolution)
|
|
213
|
-
return current;
|
|
214
|
-
const next = { ...current };
|
|
215
|
-
delete next.pendingResolution;
|
|
216
|
-
return next;
|
|
217
|
-
});
|
|
213
|
+
await clearPendingResolution(projectRoot);
|
|
218
214
|
info('');
|
|
219
215
|
success(`All patches re-exported with sourceVersion=${session.toVersion}`);
|
|
220
216
|
outro('Rebase complete!');
|
|
@@ -225,13 +221,13 @@ async function reExportAppliedPatches(session, paths, waitLockSeconds) {
|
|
|
225
221
|
const manifest = await loadPatchesManifest(paths.patches);
|
|
226
222
|
if (!manifest)
|
|
227
223
|
return { failures, overlapSkipped };
|
|
228
|
-
// Re-export writes `getDiffForFilesAgainstHead(files)
|
|
224
|
+
// Re-export writes `getDiffForFilesAgainstHead(files)`, the cumulative
|
|
229
225
|
// diff of those files. For a file claimed by two patches (a supported
|
|
230
|
-
// `--allow-overlap` queue), that diff contains
|
|
226
|
+
// `--allow-overlap` queue), that diff contains both patches' hunks, so
|
|
231
227
|
// rewriting each patch with it would duplicate the shared file's hunks
|
|
232
228
|
// into every owner: the very next import then fails or silently
|
|
233
229
|
// double-materialises. Refuse to auto-re-export any patch whose files
|
|
234
|
-
// overlap another patch
|
|
230
|
+
// overlap another patch. The operator re-exports those manually where
|
|
235
231
|
// per-patch attribution is possible.
|
|
236
232
|
const fileOwners = new Map();
|
|
237
233
|
for (const patch of manifest.patches) {
|