@hominis/fireforge 0.44.4 → 0.46.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 +120 -0
- package/dist/bin/fireforge.js +6 -0
- 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 +5 -1
- package/dist/src/cli.js +20 -21
- package/dist/src/commands/bootstrap.js +1 -2
- package/dist/src/commands/build.js +15 -6
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/doctor-check-core.d.ts +0 -6
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-orphaned-harness.d.ts +0 -6
- package/dist/src/commands/doctor-orphaned-harness.js +4 -12
- package/dist/src/commands/doctor-post-rebase-audit.js +1 -1
- package/dist/src/commands/doctor-source-pin.d.ts +29 -0
- package/dist/src/commands/doctor-source-pin.js +81 -0
- package/dist/src/commands/doctor.d.ts +2 -0
- package/dist/src/commands/doctor.js +9 -8
- package/dist/src/commands/download.js +35 -24
- package/dist/src/commands/export-all.js +21 -4
- package/dist/src/commands/export-flow.js +15 -60
- package/dist/src/commands/export-placement-conflicts.js +3 -3
- package/dist/src/commands/export-placement-gate.js +2 -8
- package/dist/src/commands/export-placement-policy.js +3 -5
- package/dist/src/commands/export-shared.d.ts +42 -23
- package/dist/src/commands/export-shared.js +4 -19
- package/dist/src/commands/export.js +10 -1
- 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.js +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +3 -8
- package/dist/src/commands/furnace/create-dry-run.js +2 -5
- package/dist/src/commands/furnace/create-templates.d.ts +17 -1
- package/dist/src/commands/furnace/create-templates.js +2 -1
- package/dist/src/commands/furnace/create.js +25 -19
- package/dist/src/commands/furnace/deploy.js +11 -2
- package/dist/src/commands/furnace/init.js +2 -1
- package/dist/src/commands/furnace/override.js +28 -19
- package/dist/src/commands/furnace/refresh.js +9 -1
- package/dist/src/commands/furnace/remove-mutations.d.ts +6 -7
- package/dist/src/commands/furnace/remove-mutations.js +0 -1
- package/dist/src/commands/furnace/remove.js +2 -6
- package/dist/src/commands/furnace/rename-browser-test.js +1 -7
- package/dist/src/commands/furnace/rename.js +29 -29
- package/dist/src/commands/furnace/status.js +12 -9
- 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/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +2 -9
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +19 -4
- package/dist/src/commands/lint-per-run-checkjs.d.ts +2 -2
- package/dist/src/commands/lint.d.ts +2 -1
- package/dist/src/commands/lint.js +1 -1
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +2 -4
- package/dist/src/commands/patch/compact.js +14 -15
- package/dist/src/commands/patch/delete.js +15 -25
- 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 +0 -8
- package/dist/src/commands/patch/lint-ignore.js +19 -29
- package/dist/src/commands/patch/move-files-create.js +24 -10
- package/dist/src/commands/patch/move-files-into.js +38 -37
- package/dist/src/commands/patch/move-files.js +4 -13
- package/dist/src/commands/patch/rename.js +27 -41
- package/dist/src/commands/patch/reorder.js +25 -38
- package/dist/src/commands/patch/split-plan.d.ts +4 -5
- package/dist/src/commands/patch/split-plan.js +4 -11
- package/dist/src/commands/patch/split.js +45 -43
- package/dist/src/commands/patch/staged-dependency.js +16 -22
- package/dist/src/commands/patch/tier.js +15 -25
- 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 +32 -2
- package/dist/src/commands/re-export-adjacent.js +51 -10
- package/dist/src/commands/re-export-bulk-scan.js +6 -10
- package/dist/src/commands/re-export-drift.d.ts +8 -0
- package/dist/src/commands/re-export-drift.js +65 -4
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +38 -32
- package/dist/src/commands/re-export-lint.d.ts +3 -4
- package/dist/src/commands/re-export-lint.js +9 -2
- package/dist/src/commands/re-export-options.js +19 -5
- package/dist/src/commands/re-export-register.js +5 -1
- package/dist/src/commands/re-export-scan.js +8 -8
- package/dist/src/commands/re-export-single.d.ts +22 -3
- package/dist/src/commands/re-export-single.js +19 -11
- package/dist/src/commands/re-export.js +44 -27
- package/dist/src/commands/rebase/abort.js +3 -8
- package/dist/src/commands/rebase/continue.js +12 -12
- package/dist/src/commands/rebase/index.js +2 -2
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +2 -7
- package/dist/src/commands/resolve.js +18 -10
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +12 -25
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +16 -16
- package/dist/src/commands/setup.js +3 -9
- package/dist/src/commands/source.js +8 -1
- package/dist/src/commands/status-check.js +2 -2
- package/dist/src/commands/status-output.js +2 -2
- package/dist/src/commands/status.js +3 -4
- package/dist/src/commands/test-build-phase.d.ts +2 -2
- package/dist/src/commands/test-build-phase.js +33 -8
- package/dist/src/commands/test-diagnose.js +14 -5
- package/dist/src/commands/test-modes.d.ts +2 -2
- package/dist/src/commands/test-modes.js +0 -1
- package/dist/src/commands/test-register.js +6 -3
- package/dist/src/commands/test-run.js +29 -21
- package/dist/src/commands/test-stale-gate.js +8 -5
- package/dist/src/commands/test-verdict.d.ts +16 -2
- package/dist/src/commands/test-verdict.js +18 -3
- package/dist/src/commands/test.js +51 -7
- 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 +17 -1
- package/dist/src/commands/tree.js +7 -2
- package/dist/src/commands/typecheck.js +9 -9
- package/dist/src/commands/wire.js +4 -3
- package/dist/src/core/branding.d.ts +0 -7
- package/dist/src/core/branding.js +3 -2
- package/dist/src/core/browser-wire.js +6 -3
- package/dist/src/core/build-audit-platform.d.ts +29 -0
- package/dist/src/core/build-audit-platform.js +140 -0
- package/dist/src/core/build-audit-registration.js +3 -2
- 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.d.ts +15 -2
- package/dist/src/core/build-audit.js +154 -12
- package/dist/src/core/build-baseline.d.ts +45 -28
- package/dist/src/core/build-baseline.js +6 -29
- package/dist/src/core/build-jar-escalation.d.ts +64 -0
- package/dist/src/core/build-jar-escalation.js +128 -0
- package/dist/src/core/build-overwrite-guard.js +1 -1
- package/dist/src/core/build-prepare.d.ts +5 -2
- package/dist/src/core/build-prepare.js +34 -6
- 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 +1 -19
- 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 +12 -0
- package/dist/src/core/config-validate-file-size.js +65 -0
- 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 +20 -3
- package/dist/src/core/config.d.ts +2 -2
- package/dist/src/core/config.js +11 -15
- package/dist/src/core/coverage-extend.js +4 -4
- package/dist/src/core/discard-baseline.js +7 -7
- package/dist/src/core/engine-precondition.d.ts +1 -9
- package/dist/src/core/engine-precondition.js +3 -8
- package/dist/src/core/engine-session-lock.js +13 -17
- package/dist/src/core/export-moved-code-shape.js +2 -2
- 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 +2 -7
- package/dist/src/core/file-lock.js +40 -91
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +59 -34
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +37 -21
- package/dist/src/core/firefox-extract.d.ts +6 -5
- package/dist/src/core/firefox-extract.js +36 -18
- package/dist/src/core/firefox.d.ts +30 -32
- package/dist/src/core/firefox.js +5 -36
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +1 -7
- package/dist/src/core/furnace-apply-helpers.d.ts +0 -11
- package/dist/src/core/furnace-apply-helpers.js +8 -19
- package/dist/src/core/furnace-apply-overwrite-warn.js +4 -2
- package/dist/src/core/furnace-apply.d.ts +1 -1
- package/dist/src/core/furnace-apply.js +30 -10
- package/dist/src/core/furnace-config.d.ts +1 -1
- package/dist/src/core/furnace-config.js +23 -36
- package/dist/src/core/furnace-constants.js +3 -2
- 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-operation.d.ts +2 -0
- package/dist/src/core/furnace-operation.js +3 -1
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +3 -6
- package/dist/src/core/furnace-registration-ast.d.ts +0 -1
- package/dist/src/core/furnace-registration-ast.js +0 -3
- package/dist/src/core/furnace-registration.d.ts +2 -1
- package/dist/src/core/furnace-registration.js +22 -29
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-state-persist.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +5 -7
- package/dist/src/core/git-base.d.ts +3 -1
- package/dist/src/core/git-base.js +25 -3
- 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 +9 -9
- package/dist/src/core/git-diff.js +88 -157
- package/dist/src/core/git-file-ops.d.ts +0 -7
- package/dist/src/core/git-file-ops.js +4 -28
- package/dist/src/core/git-readonly-index.d.ts +0 -2
- package/dist/src/core/git-readonly-index.js +0 -4
- package/dist/src/core/git-status.d.ts +7 -0
- package/dist/src/core/git-status.js +21 -9
- package/dist/src/core/git.d.ts +0 -6
- package/dist/src/core/git.js +14 -43
- package/dist/src/core/harness-orphans.d.ts +73 -0
- package/dist/src/core/harness-orphans.js +187 -0
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/mach-error-hints.d.ts +0 -5
- package/dist/src/core/mach-error-hints.js +1 -1
- package/dist/src/core/mach-known-noise-filter.d.ts +25 -3
- package/dist/src/core/mach-known-noise-filter.js +31 -10
- package/dist/src/core/mach-mozconfig.js +2 -1
- package/dist/src/core/mach-python.d.ts +2 -0
- package/dist/src/core/mach-python.js +12 -7
- package/dist/src/core/mach-resource-shim.d.ts +13 -1
- package/dist/src/core/mach-resource-shim.js +112 -9
- package/dist/src/core/mach.d.ts +46 -53
- package/dist/src/core/mach.js +31 -83
- package/dist/src/core/marionette-port.d.ts +0 -17
- package/dist/src/core/marionette-port.js +12 -58
- package/dist/src/core/marionette-preflight.js +9 -27
- package/dist/src/core/mochitest-server-port.js +3 -3
- package/dist/src/core/moz-manifest-rules.js +37 -33
- package/dist/src/core/patch-apply-fuzz.js +4 -4
- package/dist/src/core/patch-apply.d.ts +4 -5
- package/dist/src/core/patch-apply.js +55 -32
- 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 +18 -1
- package/dist/src/core/patch-export-update.js +4 -3
- package/dist/src/core/patch-export.d.ts +11 -21
- package/dist/src/core/patch-export.js +44 -66
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-lint-binary.d.ts +6 -12
- package/dist/src/core/patch-lint-cache.d.ts +17 -1
- package/dist/src/core/patch-lint-cache.js +3 -6
- package/dist/src/core/patch-lint-checkjs.d.ts +33 -16
- package/dist/src/core/patch-lint-checkjs.js +43 -25
- package/dist/src/core/patch-lint-creators.d.ts +2 -6
- package/dist/src/core/patch-lint-cross.d.ts +16 -8
- package/dist/src/core/patch-lint-cross.js +49 -92
- package/dist/src/core/patch-lint-css.js +10 -6
- package/dist/src/core/patch-lint-file-size.d.ts +52 -0
- package/dist/src/core/patch-lint-file-size.js +53 -0
- 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.js +36 -36
- package/dist/src/core/patch-lint-module-registration.d.ts +2 -8
- package/dist/src/core/patch-lint-prettier.d.ts +36 -0
- package/dist/src/core/patch-lint-prettier.js +126 -0
- 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 +106 -0
- package/dist/src/core/patch-lint-unmanaged-companion.js +214 -0
- package/dist/src/core/patch-lint.d.ts +14 -9
- package/dist/src/core/patch-lint.js +27 -27
- package/dist/src/core/patch-lock.js +3 -3
- package/dist/src/core/patch-manifest-io.js +8 -7
- package/dist/src/core/patch-parse.d.ts +19 -8
- package/dist/src/core/patch-parse.js +25 -0
- package/dist/src/core/patch-policy.js +15 -27
- 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 +21 -8
- package/dist/src/core/patch-transform.js +38 -10
- package/dist/src/core/process-cpu-time.js +1 -1
- package/dist/src/core/rebase-session.d.ts +2 -8
- package/dist/src/core/rebase-session.js +5 -17
- 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-scaffold.js +5 -4
- package/dist/src/core/register-shared-css.js +2 -1
- 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 +13 -2
- package/dist/src/core/run-log.js +67 -18
- package/dist/src/core/signal-critical.js +2 -4
- package/dist/src/core/smoke-patterns.d.ts +0 -1
- package/dist/src/core/smoke-patterns.js +18 -11
- package/dist/src/core/state-file.d.ts +12 -1
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-classify.js +2 -1
- package/dist/src/core/test-changed-prefs.js +26 -11
- package/dist/src/core/test-harness-crash.js +61 -48
- package/dist/src/core/test-harness-verdict-notes.d.ts +55 -0
- package/dist/src/core/test-harness-verdict-notes.js +48 -0
- package/dist/src/core/test-stale-check.d.ts +23 -8
- package/dist/src/core/test-stale-check.js +77 -4
- package/dist/src/core/test-stall-triage.js +37 -19
- 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 +33 -0
- package/dist/src/core/token-category.js +56 -48
- package/dist/src/core/token-dark-mode.js +2 -14
- 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 +1 -1
- package/dist/src/core/token-manager.js +1 -1
- package/dist/src/core/token-variant.js +21 -22
- package/dist/src/core/toolchain-preflight.js +1 -1
- package/dist/src/core/tree-cow.d.ts +0 -2
- package/dist/src/core/tree-cow.js +2 -2
- package/dist/src/core/tree-store.js +4 -5
- package/dist/src/core/typecheck.js +2 -2
- package/dist/src/core/wire-dom-fragment.js +6 -17
- package/dist/src/core/wire-utils.js +5 -17
- package/dist/src/core/xpcshell-appdir.js +2 -4
- package/dist/src/errors/base.d.ts +53 -1
- package/dist/src/errors/base.js +79 -11
- package/dist/src/errors/build.d.ts +28 -0
- package/dist/src/errors/build.js +51 -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.js +8 -9
- package/dist/src/errors/git.d.ts +8 -8
- package/dist/src/errors/git.js +20 -30
- package/dist/src/errors/patch.js +8 -10
- package/dist/src/errors/rebase.js +7 -7
- package/dist/src/types/commands/options.d.ts +96 -123
- package/dist/src/types/commands/patches.d.ts +17 -6
- package/dist/src/types/config.d.ts +75 -2
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/utils/assert.d.ts +3 -15
- package/dist/src/utils/assert.js +1 -18
- package/dist/src/utils/build-info.d.ts +1 -1
- package/dist/src/utils/child-env.d.ts +2 -1
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/fs.d.ts +4 -2
- package/dist/src/utils/fs.js +11 -14
- 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/options.d.ts +1 -7
- package/dist/src/utils/options.js +6 -7
- package/dist/src/utils/package-root.js +3 -12
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +2 -1
- package/dist/src/utils/process-group.js +20 -19
- package/dist/src/utils/process.d.ts +40 -26
- package/dist/src/utils/process.js +115 -166
- package/dist/src/utils/ps-duration.js +3 -3
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/validation.d.ts +2 -38
- package/dist/src/utils/validation.js +7 -16
- package/docs/configuration.md +136 -1
- package/docs/exit-codes.md +34 -20
- package/docs/lifecycle-invariants.md +18 -12
- package/docs/machine-output.md +31 -8
- package/docs/patch-workflow.md +2 -1
- package/docs/run-logs.md +44 -4
- package/docs/testing.md +70 -11
- package/package.json +8 -7
- 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
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Policy-aware checks for export placement plans.
|
|
4
4
|
*/
|
|
5
|
+
import { formatOrderRange, formatPatchOrder } from '../core/patch-parse.js';
|
|
5
6
|
import { InvalidArgumentError } from '../errors/base.js';
|
|
6
|
-
function reservedRangeLabel(range) {
|
|
7
|
-
return `${String(range.from).padStart(3, '0')}-${String(range.to).padStart(3, '0')}`;
|
|
8
|
-
}
|
|
9
7
|
function findReservedRange(config, order) {
|
|
10
8
|
return (config.patchPolicy?.reservedRanges?.find((range) => order >= range.from && order <= range.to) ??
|
|
11
9
|
null);
|
|
@@ -42,11 +40,11 @@ export function assertPlacementAvoidsReservedRanges(plan, manifestPatches, confi
|
|
|
42
40
|
(oldOrder !== undefined ? findReservedRange(config, oldOrder) : null);
|
|
43
41
|
if (reserved === null)
|
|
44
42
|
continue;
|
|
45
|
-
const label =
|
|
43
|
+
const label = formatOrderRange(reserved);
|
|
46
44
|
const freeOrder = firstFreeOrderBelowReservedRange(manifestPatches, reserved);
|
|
47
45
|
if (freeOrder !== null) {
|
|
48
46
|
throw new InvalidArgumentError(`Positional insert would renumber the reserved range ${label}; ` +
|
|
49
|
-
`pass --order ${
|
|
47
|
+
`pass --order ${formatPatchOrder(freeOrder)} (first free order below the ` +
|
|
50
48
|
'reserved block) to place the new patch without renumbering reserved patches.', 'export placement');
|
|
51
49
|
}
|
|
52
50
|
throw new InvalidArgumentError(`Positional insert would renumber the reserved range ${label}; ` +
|
|
@@ -2,29 +2,43 @@ import type { PatchesManifest, PatchLintIssue } from '../types/commands/index.js
|
|
|
2
2
|
import type { ExportOptions, PatchCategory } from '../types/commands/index.js';
|
|
3
3
|
import type { FireForgeConfig } from '../types/config.js';
|
|
4
4
|
import type { SpinnerHandle } from '../utils/logger.js';
|
|
5
|
+
export interface RunPatchLintOptions {
|
|
6
|
+
/** Engine root directory. */
|
|
7
|
+
engineDir: string;
|
|
8
|
+
/** Files touched by the patch. */
|
|
9
|
+
filesAffected: string[];
|
|
10
|
+
/** Raw unified diff string. */
|
|
11
|
+
diffContent: string;
|
|
12
|
+
/** Project configuration. */
|
|
13
|
+
config: FireForgeConfig;
|
|
14
|
+
/** If true, downgrade errors to warnings. */
|
|
15
|
+
skipLint?: boolean | undefined;
|
|
16
|
+
/** Optional cross-patch context for ownership resolution. */
|
|
17
|
+
patchQueueCtx?: import('../core/patch-lint-cross.js').PatchQueueContext | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Optional per-patch set of `check` IDs to suppress (threaded from
|
|
20
|
+
* `PatchMetadata.lintIgnore`). Surgical alternative to `--skip-lint` when
|
|
21
|
+
* exactly one advisory rule does not apply to a specific patch — e.g.
|
|
22
|
+
* `large-patch-lines` on a cohesive branding bundle that genuinely cannot
|
|
23
|
+
* be split.
|
|
24
|
+
*/
|
|
25
|
+
ignoreChecks?: ReadonlySet<string> | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Optional explicit tier override (threaded from `PatchMetadata.tier`).
|
|
28
|
+
* Forces the branding-tier thresholds when set, independent of the
|
|
29
|
+
* auto-detect allowlist. When the branding tier is applied, a single
|
|
30
|
+
* `info()` line surfaces the choice so the tier decision is visible rather
|
|
31
|
+
* than silent.
|
|
32
|
+
*/
|
|
33
|
+
patchTier?: 'branding' | undefined;
|
|
34
|
+
}
|
|
5
35
|
/**
|
|
6
36
|
* Runs the full patch lint pipeline and reports results. Warnings are always
|
|
7
37
|
* displayed. Errors block the export unless skipLint is true.
|
|
8
38
|
*
|
|
9
|
-
* @param
|
|
10
|
-
* @param filesAffected - Files touched by the patch
|
|
11
|
-
* @param diffContent - Raw unified diff string
|
|
12
|
-
* @param config - Project configuration
|
|
13
|
-
* @param skipLint - If true, downgrade errors to warnings
|
|
14
|
-
* @param patchQueueCtx - Optional cross-patch context for ownership
|
|
15
|
-
* resolution
|
|
16
|
-
* @param ignoreChecks - Optional per-patch set of `check` IDs to suppress
|
|
17
|
-
* (threaded from `PatchMetadata.lintIgnore`). Surgical alternative to
|
|
18
|
-
* `--skip-lint` when exactly one advisory rule does not apply to a
|
|
19
|
-
* specific patch — e.g. `large-patch-lines` on a cohesive branding bundle
|
|
20
|
-
* that genuinely cannot be split.
|
|
21
|
-
* @param patchTier - Optional explicit tier override (threaded from
|
|
22
|
-
* `PatchMetadata.tier`). Forces the branding-tier thresholds when set,
|
|
23
|
-
* independent of the auto-detect allowlist. When the branding tier is
|
|
24
|
-
* applied, a single `info()` line surfaces the choice so the tier decision
|
|
25
|
-
* is visible rather than silent.
|
|
39
|
+
* @param options - See {@link RunPatchLintOptions}
|
|
26
40
|
*/
|
|
27
|
-
export declare function runPatchLint(
|
|
41
|
+
export declare function runPatchLint(options: RunPatchLintOptions): Promise<void>;
|
|
28
42
|
/**
|
|
29
43
|
* Prints a patch-lint issue list with `runPatchLint`'s exact severity
|
|
30
44
|
* buckets and skip-lint semantics, throwing on errors unless `skipLint`.
|
|
@@ -32,17 +46,22 @@ export declare function runPatchLint(engineDir: string, filesAffected: string[],
|
|
|
32
46
|
* stored issues through the identical reporter without re-linting.
|
|
33
47
|
*/
|
|
34
48
|
export declare function reportPatchLintOutcome(issues: PatchLintIssue[], skipLint?: boolean): void;
|
|
49
|
+
/** Patch identity resolved for an export, from flags or interactive prompts. */
|
|
50
|
+
export interface ExportPatchMetadata {
|
|
51
|
+
/** Normalized patch name (without order prefix or extension). */
|
|
52
|
+
patchName: string;
|
|
53
|
+
/** Category the patch is filed under. */
|
|
54
|
+
selectedCategory: PatchCategory;
|
|
55
|
+
/** Human-readable patch description. */
|
|
56
|
+
description: string;
|
|
57
|
+
}
|
|
35
58
|
/**
|
|
36
59
|
* Resolves patch metadata interactively or from flags, with shared validation.
|
|
37
60
|
* @param options - Export command options
|
|
38
61
|
* @param isInteractive - Whether interactive prompts are allowed
|
|
39
62
|
* @param commandName - Command name for error/help text
|
|
40
63
|
*/
|
|
41
|
-
export declare function promptExportPatchMetadata(options: ExportOptions, isInteractive: boolean, commandName: 'export' | 'export-all', config?: FireForgeConfig): Promise<
|
|
42
|
-
patchName: string;
|
|
43
|
-
selectedCategory: PatchCategory;
|
|
44
|
-
description: string;
|
|
45
|
-
} | null>;
|
|
64
|
+
export declare function promptExportPatchMetadata(options: ExportOptions, isInteractive: boolean, commandName: 'export' | 'export-all', config?: FireForgeConfig): Promise<ExportPatchMetadata | null>;
|
|
46
65
|
/**
|
|
47
66
|
* Confirms whether an export may supersede existing patches.
|
|
48
67
|
* @param patchesDir - Patches directory
|
|
@@ -15,25 +15,10 @@ import { describePatchNameProblem, normalizePatchDisplayName, PATCH_CATEGORIES,
|
|
|
15
15
|
* Runs the full patch lint pipeline and reports results. Warnings are always
|
|
16
16
|
* displayed. Errors block the export unless skipLint is true.
|
|
17
17
|
*
|
|
18
|
-
* @param
|
|
19
|
-
* @param filesAffected - Files touched by the patch
|
|
20
|
-
* @param diffContent - Raw unified diff string
|
|
21
|
-
* @param config - Project configuration
|
|
22
|
-
* @param skipLint - If true, downgrade errors to warnings
|
|
23
|
-
* @param patchQueueCtx - Optional cross-patch context for ownership
|
|
24
|
-
* resolution
|
|
25
|
-
* @param ignoreChecks - Optional per-patch set of `check` IDs to suppress
|
|
26
|
-
* (threaded from `PatchMetadata.lintIgnore`). Surgical alternative to
|
|
27
|
-
* `--skip-lint` when exactly one advisory rule does not apply to a
|
|
28
|
-
* specific patch — e.g. `large-patch-lines` on a cohesive branding bundle
|
|
29
|
-
* that genuinely cannot be split.
|
|
30
|
-
* @param patchTier - Optional explicit tier override (threaded from
|
|
31
|
-
* `PatchMetadata.tier`). Forces the branding-tier thresholds when set,
|
|
32
|
-
* independent of the auto-detect allowlist. When the branding tier is
|
|
33
|
-
* applied, a single `info()` line surfaces the choice so the tier decision
|
|
34
|
-
* is visible rather than silent.
|
|
18
|
+
* @param options - See {@link RunPatchLintOptions}
|
|
35
19
|
*/
|
|
36
|
-
export async function runPatchLint(
|
|
20
|
+
export async function runPatchLint(options) {
|
|
21
|
+
const { engineDir, filesAffected, diffContent, config, skipLint, patchQueueCtx, ignoreChecks, patchTier, } = options;
|
|
37
22
|
// Compute the tier decision independently of the lint pipeline so it can
|
|
38
23
|
// be surfaced even when the rule body emitted no issues — a branding patch
|
|
39
24
|
// under the soft threshold still benefits from operators knowing which
|
|
@@ -353,7 +338,7 @@ export async function guardOwnershipOverlap(args) {
|
|
|
353
338
|
return true;
|
|
354
339
|
s.stop();
|
|
355
340
|
const entries = [...overlap.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
356
|
-
warn(`This export would create cross-patch ownership overlap on ${
|
|
341
|
+
warn(`This export would create cross-patch ownership overlap on ${entries.length} file${entries.length === 1 ? '' : 's'}:`);
|
|
357
342
|
for (const [file, owners] of entries) {
|
|
358
343
|
warn(` - ${file} already claimed by: ${owners.join(', ')}`);
|
|
359
344
|
}
|
|
@@ -258,7 +258,16 @@ export async function exportCommand(projectRoot, files, options) {
|
|
|
258
258
|
const patchQueueCtx = (await pathExists(paths.patches))
|
|
259
259
|
? await buildPatchQueueContext(paths.patches)
|
|
260
260
|
: undefined;
|
|
261
|
-
await runPatchLint(
|
|
261
|
+
await runPatchLint({
|
|
262
|
+
engineDir: paths.engine,
|
|
263
|
+
filesAffected,
|
|
264
|
+
diffContent: diff,
|
|
265
|
+
config,
|
|
266
|
+
skipLint: options.skipLint,
|
|
267
|
+
patchQueueCtx,
|
|
268
|
+
ignoreChecks: exportIgnoreChecks,
|
|
269
|
+
patchTier: options.tier,
|
|
270
|
+
});
|
|
262
271
|
// Resolve placement (if any flag was given). Placement is mutually
|
|
263
272
|
// exclusive with supersede — the semantics overlap confusingly.
|
|
264
273
|
let placementPlan = null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FurnaceConfig } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Loads `furnace.json` for an authoring command, defaulting to an empty
|
|
4
|
+
* configuration when the project has none yet.
|
|
5
|
+
*
|
|
6
|
+
* `furnace create` and `furnace override` both need this: they are the two
|
|
7
|
+
* commands that may run before any furnace configuration exists, and both must
|
|
8
|
+
* treat "no file" as "nothing registered yet" rather than an error. They had a
|
|
9
|
+
* byte-identical private copy each.
|
|
10
|
+
* @param projectRoot - Project root to load from.
|
|
11
|
+
* @returns The parsed configuration, or a fresh default.
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadAuthoringFurnaceConfig(projectRoot: string): Promise<FurnaceConfig>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { createDefaultFurnaceConfig, furnaceConfigExists, loadFurnaceConfig, } from '../../core/furnace-config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Loads `furnace.json` for an authoring command, defaulting to an empty
|
|
5
|
+
* configuration when the project has none yet.
|
|
6
|
+
*
|
|
7
|
+
* `furnace create` and `furnace override` both need this: they are the two
|
|
8
|
+
* commands that may run before any furnace configuration exists, and both must
|
|
9
|
+
* treat "no file" as "nothing registered yet" rather than an error. They had a
|
|
10
|
+
* byte-identical private copy each.
|
|
11
|
+
* @param projectRoot - Project root to load from.
|
|
12
|
+
* @returns The parsed configuration, or a fresh default.
|
|
13
|
+
*/
|
|
14
|
+
export async function loadAuthoringFurnaceConfig(projectRoot) {
|
|
15
|
+
if (await furnaceConfigExists(projectRoot)) {
|
|
16
|
+
return loadFurnaceConfig(projectRoot);
|
|
17
|
+
}
|
|
18
|
+
return createDefaultFurnaceConfig();
|
|
19
|
+
}
|
|
@@ -10,7 +10,7 @@ import { loadConfig } from '../../core/config.js';
|
|
|
10
10
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
11
11
|
import { completeJournalRollback, runFurnaceMutation, } from '../../core/furnace-operation.js';
|
|
12
12
|
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
13
|
-
import { createRollbackJournal, snapshotDir, snapshotFile } from '../../core/furnace-rollback.js';
|
|
13
|
+
import { createRollbackJournal, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
14
14
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
15
15
|
import { pathExists, readText, removeDir, removeFile, writeText } from '../../utils/fs.js';
|
|
16
16
|
import { cancel, info, intro, isCancel, note, outro } from '../../utils/logger.js';
|
|
@@ -16,6 +16,7 @@ import { toError } from '../../utils/errors.js';
|
|
|
16
16
|
import { ensureDir, pathExists, readText, writeText } from '../../utils/fs.js';
|
|
17
17
|
import { info, success, warn } from '../../utils/logger.js';
|
|
18
18
|
import { stripEnginePrefix } from '../../utils/paths.js';
|
|
19
|
+
import { browserTestFileName, deriveTestStem } from './test-file-name.js';
|
|
19
20
|
/**
|
|
20
21
|
* Validates the `--test-dir` option against the resolved test style before
|
|
21
22
|
* any writes. Mochikit lives in the upstream toolkit/content/tests/widgets
|
|
@@ -65,15 +66,9 @@ export function resolveTestDirOverride(raw) {
|
|
|
65
66
|
* the harness will try to run.
|
|
66
67
|
*/
|
|
67
68
|
export async function scaffoldTestFiles(componentName, license, forgeConfig, paths, journal, testDirOverride) {
|
|
68
|
-
const strippedName = componentName.startsWith('moz-') ? componentName.slice(4) : componentName;
|
|
69
|
-
// Avoid double-prefixing: strip binaryName prefix since the default test
|
|
70
|
-
// dir name already uses it
|
|
71
69
|
const binaryName = forgeConfig.binaryName;
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
: strippedName;
|
|
75
|
-
const underscored = withoutBinaryPrefix.replace(/-/g, '_');
|
|
76
|
-
const testFileName = `browser_${binaryName}_${underscored}.js`;
|
|
70
|
+
const underscored = deriveTestStem(componentName, binaryName);
|
|
71
|
+
const testFileName = browserTestFileName(componentName, binaryName);
|
|
77
72
|
// --test-dir redirects the scaffold: the hardcoded
|
|
78
73
|
// `.../test/<binaryName>/` target can collide with a test suite owned by a
|
|
79
74
|
// different patch. The manifest-registration name is the path below
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* independently of the mutation plumbing.
|
|
9
9
|
*/
|
|
10
10
|
import { BROWSER_TEST_SCAFFOLD_ROOT, resolveBrowserChromeTestDir, resolveXpcshellTestDir, } from '../../core/furnace-constants.js';
|
|
11
|
+
import { deriveTestStem } from './test-file-name.js';
|
|
11
12
|
/**
|
|
12
13
|
* Builds the test-section fragment of the dry-run plan for a given
|
|
13
14
|
* harness choice. Kept separate from the top-level formatter so the
|
|
@@ -18,11 +19,7 @@ function formatTestSection(args) {
|
|
|
18
19
|
const { testStyle, componentName, binaryName, testDir } = args;
|
|
19
20
|
if (testStyle === 'none')
|
|
20
21
|
return '';
|
|
21
|
-
const
|
|
22
|
-
const withoutBinaryPrefix = strippedName.startsWith(binaryName + '-')
|
|
23
|
-
? strippedName.slice(binaryName.length + 1)
|
|
24
|
-
: strippedName;
|
|
25
|
-
const underscored = withoutBinaryPrefix.replace(/-/g, '_');
|
|
22
|
+
const underscored = deriveTestStem(componentName, binaryName);
|
|
26
23
|
if (testStyle === 'browser-chrome') {
|
|
27
24
|
// Same resolver as scaffoldTestFiles: the registration name is the
|
|
28
25
|
// path below browser/base/content/test/, which under --test-dir is
|
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
* command entrypoint so the generator is unit-testable in isolation and the
|
|
4
4
|
* command file stays under the per-file LOC budget.
|
|
5
5
|
*/
|
|
6
|
+
export interface GenerateMjsContentOptions {
|
|
7
|
+
/** Custom element tag name. */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Generated component class name. */
|
|
10
|
+
className: string;
|
|
11
|
+
/** Human-readable component description. */
|
|
12
|
+
description: string;
|
|
13
|
+
/** Whether to emit the Fluent wiring. */
|
|
14
|
+
localized: boolean;
|
|
15
|
+
/** License header prepended to the module. */
|
|
16
|
+
header: string;
|
|
17
|
+
/** chrome:// sub-path for the generated FTL reference, when localized. */
|
|
18
|
+
ftlChromeSubPath: string | undefined;
|
|
19
|
+
/** Explicit shared FTL path, used verbatim when supplied. */
|
|
20
|
+
sharedFtl: string | undefined;
|
|
21
|
+
}
|
|
6
22
|
/**
|
|
7
23
|
* Generates the .mjs file content for a custom component.
|
|
8
24
|
*
|
|
@@ -23,7 +39,7 @@
|
|
|
23
39
|
* matching the locale jar.mn entry that `furnace apply` writes.
|
|
24
40
|
* 3. `<name>.ftl` — fallback when no chrome sub-path was resolvable.
|
|
25
41
|
*/
|
|
26
|
-
export declare function generateMjsContent(
|
|
42
|
+
export declare function generateMjsContent(options: GenerateMjsContentOptions): string;
|
|
27
43
|
/** Generates the .css file content for a custom component. */
|
|
28
44
|
export declare function generateCssContent(header: string): string;
|
|
29
45
|
/** Generates the .ftl file content for a custom component. */
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
* matching the locale jar.mn entry that `furnace apply` writes.
|
|
25
25
|
* 3. `<name>.ftl` — fallback when no chrome sub-path was resolvable.
|
|
26
26
|
*/
|
|
27
|
-
export function generateMjsContent(
|
|
27
|
+
export function generateMjsContent(options) {
|
|
28
|
+
const { name, className, description, localized, header, ftlChromeSubPath, sharedFtl } = options;
|
|
28
29
|
// A `*/` in the operator-supplied description would close the JSDoc block
|
|
29
30
|
// early and leave the remainder as stray code. Escaped here rather than
|
|
30
31
|
// rejected at input, because the same text is also rendered by
|
|
@@ -3,7 +3,7 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { text } from '@clack/prompts';
|
|
4
4
|
import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
5
5
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getFurnacePaths, writeFurnaceConfig } from '../../core/furnace-config.js';
|
|
7
7
|
import { resolveFtlChromeSubPath, tagNameToClassName, WIDGETS_DIR, } from '../../core/furnace-constants.js';
|
|
8
8
|
import { completeJournalRollback, runFurnaceMutation, } from '../../core/furnace-operation.js';
|
|
9
9
|
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, describeTagNameProblem, } from '../../core/furnace-registration-validate.js';
|
|
@@ -15,6 +15,7 @@ import { InvalidArgumentError } from '../../errors/base.js';
|
|
|
15
15
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
16
16
|
import { ensureDir, pathExists, writeText } from '../../utils/fs.js';
|
|
17
17
|
import { cancel, intro, isCancel, note, outro } from '../../utils/logger.js';
|
|
18
|
+
import { loadAuthoringFurnaceConfig } from './authoring-config.js';
|
|
18
19
|
import { resolveValidatedTestDir, scaffoldTestFiles } from './create-browser-test.js';
|
|
19
20
|
import { formatDryRunPlan, formatSuccessNote } from './create-dry-run.js';
|
|
20
21
|
import { resolveCreateFeatures } from './create-features.js';
|
|
@@ -23,12 +24,6 @@ import { assertCustomEntryPersisted } from './create-readback.js';
|
|
|
23
24
|
import { generateCssContent, generateFtlContent, generateMjsContent } from './create-templates.js';
|
|
24
25
|
import { validateCreateAgainstConfig } from './create-validation.js';
|
|
25
26
|
import { scaffoldXpcshellTestFiles } from './create-xpcshell.js';
|
|
26
|
-
async function loadAuthoringFurnaceConfig(projectRoot) {
|
|
27
|
-
if (await furnaceConfigExists(projectRoot)) {
|
|
28
|
-
return loadFurnaceConfig(projectRoot);
|
|
29
|
-
}
|
|
30
|
-
return createDefaultFurnaceConfig();
|
|
31
|
-
}
|
|
32
27
|
function knownComponentSet(config) {
|
|
33
28
|
return new Set([
|
|
34
29
|
...config.stock,
|
|
@@ -64,24 +59,25 @@ function validateTagName(name) {
|
|
|
64
59
|
}
|
|
65
60
|
/**
|
|
66
61
|
* Writes the scaffolded component source files to disk.
|
|
67
|
-
* @param
|
|
68
|
-
* @param componentName - Custom element tag name
|
|
69
|
-
* @param className - Generated component class name
|
|
70
|
-
* @param description - Human-readable component description
|
|
71
|
-
* @param localized - Whether to include a Fluent file
|
|
72
|
-
* @param license - Project license used for generated headers
|
|
73
|
-
* @param ftlChromeSubPath - chrome:// sub-path for the generated FTL reference, when localized
|
|
74
|
-
* @param sharedFtl - Explicit shared FTL path from `--shared-ftl`, when supplied
|
|
75
|
-
* @param journal - Optional rollback journal that snapshots files before writes
|
|
62
|
+
* @param options - See {@link WriteComponentFilesOptions}
|
|
76
63
|
* @returns Relative filenames written for the component
|
|
77
64
|
*/
|
|
78
|
-
async function writeComponentFiles(
|
|
65
|
+
async function writeComponentFiles(options) {
|
|
66
|
+
const { componentDir, componentName, className, description, localized, license, ftlChromeSubPath, sharedFtl, journal, } = options;
|
|
79
67
|
await ensureDir(componentDir);
|
|
80
68
|
const files = [`${componentName}.mjs`, `${componentName}.css`];
|
|
81
69
|
const mjsPath = join(componentDir, `${componentName}.mjs`);
|
|
82
70
|
if (journal)
|
|
83
71
|
await snapshotFile(journal, mjsPath);
|
|
84
|
-
const mjsContent = generateMjsContent(
|
|
72
|
+
const mjsContent = generateMjsContent({
|
|
73
|
+
name: componentName,
|
|
74
|
+
className,
|
|
75
|
+
description,
|
|
76
|
+
localized,
|
|
77
|
+
header: getLicenseHeader(license, 'js'),
|
|
78
|
+
ftlChromeSubPath,
|
|
79
|
+
sharedFtl,
|
|
80
|
+
});
|
|
85
81
|
await writeText(mjsPath, mjsContent);
|
|
86
82
|
const cssPath = join(componentDir, `${componentName}.css`);
|
|
87
83
|
if (journal)
|
|
@@ -165,7 +161,17 @@ async function performCreateMutations(args) {
|
|
|
165
161
|
// so signal-driven rollback can clean it up even if writeComponentFiles
|
|
166
162
|
// is interrupted mid-ensureDir.
|
|
167
163
|
recordCreatedDir(journal, args.componentDir);
|
|
168
|
-
files = await writeComponentFiles(
|
|
164
|
+
files = await writeComponentFiles({
|
|
165
|
+
componentDir: args.componentDir,
|
|
166
|
+
componentName: args.componentName,
|
|
167
|
+
className: args.className,
|
|
168
|
+
description: args.description,
|
|
169
|
+
localized: args.localized,
|
|
170
|
+
license: args.license,
|
|
171
|
+
ftlChromeSubPath: resolveFtlChromeSubPath(freshConfig.ftlBasePath),
|
|
172
|
+
sharedFtl: args.sharedFtl,
|
|
173
|
+
journal,
|
|
174
|
+
});
|
|
169
175
|
const customEntry = {
|
|
170
176
|
description: args.description,
|
|
171
177
|
targetPath: `${WIDGETS_DIR}/${args.componentName}`,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { loadConfig } from '../../core/config.js';
|
|
3
3
|
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
4
4
|
import { logApplyResult } from '../../core/furnace-apply-output.js';
|
|
5
|
-
import { getFurnacePaths
|
|
5
|
+
import { getFurnacePaths } from '../../core/furnace-config.js';
|
|
6
6
|
import { reportJsconfigPathsSync } from '../../core/furnace-jsconfig.js';
|
|
7
7
|
import { runFurnaceMutation, waitLockMutationOptions, } from '../../core/furnace-operation.js';
|
|
8
8
|
import { assertFurnaceReady } from '../../core/furnace-precondition.js';
|
|
@@ -203,7 +203,16 @@ export async function furnaceDeployCommand(projectRoot, name, options = {}) {
|
|
|
203
203
|
}
|
|
204
204
|
const validateSpinner = spinner(isDryRun ? 'Validating (read-only)...' : 'Validating...');
|
|
205
205
|
const failedComponents = getFailedComponentNames(result);
|
|
206
|
-
const validation = await runDeployValidation(
|
|
206
|
+
const validation = await runDeployValidation({
|
|
207
|
+
validateSpinner,
|
|
208
|
+
name,
|
|
209
|
+
config,
|
|
210
|
+
furnacePaths,
|
|
211
|
+
failedComponents,
|
|
212
|
+
isDryRun,
|
|
213
|
+
projectRoot,
|
|
214
|
+
dryRunActions: result.actions,
|
|
215
|
+
});
|
|
207
216
|
if (validation.done)
|
|
208
217
|
return;
|
|
209
218
|
const { totalErrors, totalWarnings, componentCount, skippedValidationCount } = validation;
|
|
@@ -13,6 +13,7 @@ import { FurnaceError } from '../../errors/furnace.js';
|
|
|
13
13
|
import { getNodeErrorCode, toError } from '../../utils/errors.js';
|
|
14
14
|
import { ensureDir, pathExists, writeText } from '../../utils/fs.js';
|
|
15
15
|
import { cancel, info, intro, isCancel, note, outro, success, warn } from '../../utils/logger.js';
|
|
16
|
+
import { normalizePathSlashes } from '../../utils/paths.js';
|
|
16
17
|
/**
|
|
17
18
|
* File extensions that are definitely FTL resources (not locale
|
|
18
19
|
* directories). A value ending in one of these is almost certainly the
|
|
@@ -64,7 +65,7 @@ async function validateFtlBasePath(value, engineDir) {
|
|
|
64
65
|
// Normalize with the POSIX rules regardless of host: `normalize` on Windows
|
|
65
66
|
// emits backslashes, so a `../`-prefix test against the platform `normalize`
|
|
66
67
|
// silently passes every traversal attempt there.
|
|
67
|
-
const normalized = posix.normalize(value
|
|
68
|
+
const normalized = posix.normalize(normalizePathSlashes(value));
|
|
68
69
|
if (normalized === '..' || normalized.startsWith('../')) {
|
|
69
70
|
throw new FurnaceError(`ftlBasePath "${value}" must not escape the engine checkout via parent-directory segments.`);
|
|
70
71
|
}
|
|
@@ -4,7 +4,7 @@ import { dirname, join } from 'node:path';
|
|
|
4
4
|
import { select, text } from '@clack/prompts';
|
|
5
5
|
import { getProjectPaths, loadConfig, loadState } from '../../core/config.js';
|
|
6
6
|
import { stdioIsInteractive } from '../../core/destructive.js';
|
|
7
|
-
import {
|
|
7
|
+
import { getFurnacePaths, writeFurnaceConfig } from '../../core/furnace-config.js';
|
|
8
8
|
import { resolveFtlDir } from '../../core/furnace-constants.js';
|
|
9
9
|
import { completeJournalRollback, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
10
10
|
import { assertFurnaceEngineReady } from '../../core/furnace-precondition.js';
|
|
@@ -16,25 +16,14 @@ import { FurnaceError } from '../../errors/furnace.js';
|
|
|
16
16
|
import { toError } from '../../utils/errors.js';
|
|
17
17
|
import { copyFile, ensureDir, pathExists, writeJson } from '../../utils/fs.js';
|
|
18
18
|
import { cancel, info, intro, isCancel, note, outro, warn } from '../../utils/logger.js';
|
|
19
|
-
|
|
20
|
-
if (await furnaceConfigExists(projectRoot)) {
|
|
21
|
-
return loadFurnaceConfig(projectRoot);
|
|
22
|
-
}
|
|
23
|
-
return createDefaultFurnaceConfig();
|
|
24
|
-
}
|
|
19
|
+
import { loadAuthoringFurnaceConfig } from './authoring-config.js';
|
|
25
20
|
/**
|
|
26
21
|
* Copies the source files needed for a new override into the workspace.
|
|
27
|
-
* @param
|
|
28
|
-
* @param srcDir - Original component directory in the engine checkout
|
|
29
|
-
* @param destDir - Destination override directory in the workspace
|
|
30
|
-
* @param componentName - Custom element tag name being overridden
|
|
31
|
-
* @param hasFTL - Whether the component ships a localized `.ftl` file
|
|
32
|
-
* @param overrideType - Requested override mode
|
|
33
|
-
* @param ftlDir - Engine-relative directory the shared `.ftl` deploys into
|
|
34
|
-
* @param journal - Rollback journal every write is recorded in
|
|
22
|
+
* @param options - See {@link CopyOverrideFilesOptions}
|
|
35
23
|
* @returns Filenames copied into the override directory
|
|
36
24
|
*/
|
|
37
|
-
async function copyOverrideFiles(
|
|
25
|
+
async function copyOverrideFiles(options) {
|
|
26
|
+
const { engineDir, srcDir, destDir, componentName, hasFTL, overrideType, ftlDir, journal } = options;
|
|
38
27
|
await ensureDir(destDir);
|
|
39
28
|
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
40
29
|
const copiedFiles = [];
|
|
@@ -93,7 +82,8 @@ async function copyOverrideFiles(engineDir, srcDir, destDir, componentName, hasF
|
|
|
93
82
|
* cycles into a single surviving entry — otherwise both report success and
|
|
94
83
|
* furnace.json keeps only the second writer's.
|
|
95
84
|
*/
|
|
96
|
-
async function saveOverrideConfig(
|
|
85
|
+
async function saveOverrideConfig(options) {
|
|
86
|
+
const { projectRoot, destDir, componentName, overrideType, description, details, firefoxVersion, journal, baseCommit, } = options;
|
|
97
87
|
const overrideJson = {
|
|
98
88
|
type: overrideType,
|
|
99
89
|
description,
|
|
@@ -138,9 +128,28 @@ async function performOverrideMutations(args) {
|
|
|
138
128
|
ctx.registerJournal(journal);
|
|
139
129
|
recordCreatedDir(journal, args.destDir);
|
|
140
130
|
try {
|
|
141
|
-
const filesCopied = await copyOverrideFiles(
|
|
131
|
+
const filesCopied = await copyOverrideFiles({
|
|
132
|
+
engineDir: args.engineDir,
|
|
133
|
+
srcDir: args.srcDir,
|
|
134
|
+
destDir: args.destDir,
|
|
135
|
+
componentName: args.componentName,
|
|
136
|
+
hasFTL: args.details.hasFTL,
|
|
137
|
+
overrideType: args.overrideType,
|
|
138
|
+
ftlDir: args.ftlDir,
|
|
139
|
+
journal,
|
|
140
|
+
});
|
|
142
141
|
await snapshotFile(journal, args.furnacePaths.furnaceConfig);
|
|
143
|
-
await saveOverrideConfig(
|
|
142
|
+
await saveOverrideConfig({
|
|
143
|
+
projectRoot: args.projectRoot,
|
|
144
|
+
destDir: args.destDir,
|
|
145
|
+
componentName: args.componentName,
|
|
146
|
+
overrideType: args.overrideType,
|
|
147
|
+
description: args.description,
|
|
148
|
+
details: args.details,
|
|
149
|
+
firefoxVersion: args.firefoxVersion,
|
|
150
|
+
journal,
|
|
151
|
+
baseCommit: args.baseCommit,
|
|
152
|
+
});
|
|
144
153
|
return filesCopied;
|
|
145
154
|
}
|
|
146
155
|
catch (error) {
|
|
@@ -126,7 +126,15 @@ async function refreshSingleOverride(projectRoot, name, options = {}) {
|
|
|
126
126
|
for (const entry of overrideFiles) {
|
|
127
127
|
const overridePath = join(overrideDir, entry.name);
|
|
128
128
|
const engineRelPath = getOverrideEngineTargetPath(paths.engine, overrideConfig, entry.name, ftlDir).slice(paths.engine.length + 1);
|
|
129
|
-
const result = await refreshOverrideFile(
|
|
129
|
+
const result = await refreshOverrideFile({
|
|
130
|
+
engineDir: paths.engine,
|
|
131
|
+
overridePath,
|
|
132
|
+
engineRelPath,
|
|
133
|
+
baseCommit,
|
|
134
|
+
fileName: entry.name,
|
|
135
|
+
dryRun,
|
|
136
|
+
strategy,
|
|
137
|
+
});
|
|
130
138
|
fileResults.push(result);
|
|
131
139
|
}
|
|
132
140
|
// Update baseVersion and baseCommit on clean merge (not dry-run, no conflicts)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { getFurnacePaths } from '../../core/furnace-config.js';
|
|
1
|
+
import type { FurnacePaths } from '../../core/furnace-config.js';
|
|
3
2
|
import type { RollbackJournal } from '../../core/furnace-rollback.js';
|
|
4
|
-
import type { FurnaceState } from '../../types/furnace.js';
|
|
3
|
+
import type { FurnaceConfig, FurnaceState } from '../../types/furnace.js';
|
|
5
4
|
/**
|
|
6
5
|
* Engine-side and workspace-side removal for an OVERRIDE component.
|
|
7
6
|
*
|
|
@@ -14,8 +13,8 @@ export declare function performOverrideRemovalMutations(args: {
|
|
|
14
13
|
paths: {
|
|
15
14
|
engine: string;
|
|
16
15
|
};
|
|
17
|
-
furnacePaths:
|
|
18
|
-
freshConfig:
|
|
16
|
+
furnacePaths: FurnacePaths;
|
|
17
|
+
freshConfig: FurnaceConfig;
|
|
19
18
|
freshState: FurnaceState;
|
|
20
19
|
ftlDir: string;
|
|
21
20
|
journal: RollbackJournal;
|
|
@@ -30,8 +29,8 @@ export declare function performCustomRemovalMutations(args: {
|
|
|
30
29
|
paths: {
|
|
31
30
|
engine: string;
|
|
32
31
|
};
|
|
33
|
-
furnacePaths:
|
|
34
|
-
freshConfig:
|
|
32
|
+
furnacePaths: FurnacePaths;
|
|
33
|
+
freshConfig: FurnaceConfig;
|
|
35
34
|
ftlDir: string;
|
|
36
35
|
journal: RollbackJournal;
|
|
37
36
|
}): Promise<void>;
|
|
@@ -16,7 +16,6 @@ import { join } from 'node:path';
|
|
|
16
16
|
import { removeCustomFtlJarMnEntry } from '../../core/furnace-apply-ftl.js';
|
|
17
17
|
import { getOverrideEngineTargetPath, isOverrideCopyCandidate, restoreOverrideFileToBaseline, } from '../../core/furnace-apply-helpers.js';
|
|
18
18
|
import { extractComponentChecksums } from '../../core/furnace-checksum-utils.js';
|
|
19
|
-
import { getFurnacePaths } from '../../core/furnace-config.js';
|
|
20
19
|
import { removeCustomElementRegistration, removeJarMnEntries, } from '../../core/furnace-registration.js';
|
|
21
20
|
import { snapshotDir, snapshotFile } from '../../core/furnace-rollback.js';
|
|
22
21
|
import { isGitRepository } from '../../core/git.js';
|
|
@@ -16,6 +16,7 @@ import { pathExists, readText, removeDir, writeText } from '../../utils/fs.js';
|
|
|
16
16
|
import { cancel, info, intro, isCancel, outro, warn } from '../../utils/logger.js';
|
|
17
17
|
import { performCustomRemovalMutations, performOverrideRemovalMutations, } from './remove-mutations.js';
|
|
18
18
|
import { dropChecksumsByPrefix } from './remove-state.js';
|
|
19
|
+
import { browserTestFileName } from './test-file-name.js';
|
|
19
20
|
/**
|
|
20
21
|
* Removes an entire TOML section (header + body lines) for a given test file.
|
|
21
22
|
* Matches from `["filename"]` up to the next section header `[` or end-of-file,
|
|
@@ -94,12 +95,7 @@ async function cleanupCustomTestFiles(name, projectRoot, journal) {
|
|
|
94
95
|
}
|
|
95
96
|
const paths = getProjectPaths(projectRoot);
|
|
96
97
|
const binaryName = forgeConfig.binaryName;
|
|
97
|
-
const
|
|
98
|
-
const withoutBinaryPrefix = strippedName.startsWith(binaryName + '-')
|
|
99
|
-
? strippedName.slice(binaryName.length + 1)
|
|
100
|
-
: strippedName;
|
|
101
|
-
const underscored = withoutBinaryPrefix.replace(/-/g, '_');
|
|
102
|
-
const testFileName = `browser_${binaryName}_${underscored}.js`;
|
|
98
|
+
const testFileName = browserTestFileName(name, binaryName);
|
|
103
99
|
const testDir = join(paths.engine, 'browser/base/content/test', binaryName);
|
|
104
100
|
if (!(await pathExists(testDir)))
|
|
105
101
|
return { partialFailures };
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { tagNameToClassName } from '../../core/furnace-constants.js';
|
|
3
3
|
import { escapeRegex } from '../../utils/regex.js';
|
|
4
|
-
|
|
5
|
-
const strippedName = componentName.startsWith('moz-') ? componentName.slice(4) : componentName;
|
|
6
|
-
const withoutBinaryPrefix = strippedName.startsWith(binaryName + '-')
|
|
7
|
-
? strippedName.slice(binaryName.length + 1)
|
|
8
|
-
: strippedName;
|
|
9
|
-
return withoutBinaryPrefix.replace(/-/g, '_');
|
|
10
|
-
}
|
|
4
|
+
import { deriveTestStem } from './test-file-name.js';
|
|
11
5
|
/** Rewrites scaffolded browser-chrome test literals after a component rename. */
|
|
12
6
|
export function updateBrowserChromeTestContent(content, oldName, newName, binaryName) {
|
|
13
7
|
const oldClassName = tagNameToClassName(oldName);
|