@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
|
@@ -13,6 +13,22 @@ export interface UpdatePatchPolicyGate {
|
|
|
13
13
|
command: string;
|
|
14
14
|
forceUnsafe?: boolean;
|
|
15
15
|
}
|
|
16
|
+
export interface UpdatePatchAndMetadataOptions {
|
|
17
|
+
/** Patch directory holding the body and `patches.json`. */
|
|
18
|
+
patchesDir: string;
|
|
19
|
+
/** Patch file to rewrite. */
|
|
20
|
+
filename: string;
|
|
21
|
+
/** New patch body; an identical body skips the write. */
|
|
22
|
+
newContent: string;
|
|
23
|
+
/** Manifest-row fields to merge into the patch's metadata. */
|
|
24
|
+
updates: Partial<PatchMetadata>;
|
|
25
|
+
/** Hook run under the lock after the mutation succeeds. */
|
|
26
|
+
onCommitted?: UpdatePatchCommittedHook | undefined;
|
|
27
|
+
/** Policy gate run against the under-lock projected manifest. */
|
|
28
|
+
policyGate?: UpdatePatchPolicyGate | undefined;
|
|
29
|
+
/** Wait budget and command name for the patch directory lock. */
|
|
30
|
+
lockOptions?: PatchDirectoryLockOptions | undefined;
|
|
31
|
+
}
|
|
16
32
|
/**
|
|
17
33
|
* Updates a patch file body and its manifest row under the same patch
|
|
18
34
|
* directory lock. Intended for commands like `re-export --files` where the
|
|
@@ -26,7 +42,8 @@ export interface UpdatePatchPolicyGate {
|
|
|
26
42
|
* unexpected rewrite in `git status`. Metadata still moves either way — only
|
|
27
43
|
* the redundant byte-for-byte write is elided.
|
|
28
44
|
*
|
|
45
|
+
* @param options - See {@link UpdatePatchAndMetadataOptions}
|
|
29
46
|
* @returns True when the patch body on disk changed, false when it was
|
|
30
47
|
* already byte-identical to the new content.
|
|
31
48
|
*/
|
|
32
|
-
export declare function updatePatchAndMetadata(
|
|
49
|
+
export declare function updatePatchAndMetadata(options: UpdatePatchAndMetadataOptions): Promise<boolean>;
|
|
@@ -5,7 +5,6 @@ import { toError } from '../utils/errors.js';
|
|
|
5
5
|
import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
6
6
|
import { warn } from '../utils/logger.js';
|
|
7
7
|
import { withPatchDirectoryLock } from './patch-apply.js';
|
|
8
|
-
import { normalizePatchArtifact } from './patch-artifact-normalize.js';
|
|
9
8
|
import { loadPatchesManifestForWrite, mutatePatchRowsInManifest } from './patch-manifest.js';
|
|
10
9
|
import { buildProjectedManifest, enforcePatchPolicy } from './patch-policy.js';
|
|
11
10
|
/**
|
|
@@ -21,10 +20,12 @@ import { buildProjectedManifest, enforcePatchPolicy } from './patch-policy.js';
|
|
|
21
20
|
* unexpected rewrite in `git status`. Metadata still moves either way — only
|
|
22
21
|
* the redundant byte-for-byte write is elided.
|
|
23
22
|
*
|
|
23
|
+
* @param options - See {@link UpdatePatchAndMetadataOptions}
|
|
24
24
|
* @returns True when the patch body on disk changed, false when it was
|
|
25
25
|
* already byte-identical to the new content.
|
|
26
26
|
*/
|
|
27
|
-
export async function updatePatchAndMetadata(
|
|
27
|
+
export async function updatePatchAndMetadata(options) {
|
|
28
|
+
const { patchesDir, filename, newContent, updates, onCommitted, policyGate, lockOptions = {}, } = options;
|
|
28
29
|
return withPatchDirectoryLock(patchesDir, async () => {
|
|
29
30
|
const manifest = await loadPatchesManifestForWrite(patchesDir);
|
|
30
31
|
if (!manifest) {
|
|
@@ -49,7 +50,7 @@ export async function updatePatchAndMetadata(patchesDir, filename, newContent, u
|
|
|
49
50
|
forceUnsafe: policyGate.forceUnsafe === true,
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
|
-
const normalized =
|
|
53
|
+
const normalized = newContent;
|
|
53
54
|
const bodyChanged = normalized !== originalContent;
|
|
54
55
|
let patchWritten = false;
|
|
55
56
|
try {
|
|
@@ -2,9 +2,19 @@ import type { PatchCategory, PatchesManifest, PatchInfo, PatchMetadata } from '.
|
|
|
2
2
|
import type { FireForgeConfig } from '../types/config.js';
|
|
3
3
|
import { type SupersedeCoverageDetail } from './patch-export-coverage.js';
|
|
4
4
|
import type { PatchDirectoryLockOptions } from './patch-lock.js';
|
|
5
|
-
export { findAllPatchesForFiles, findAllPatchesForFilesWithDetails,
|
|
5
|
+
export { findAllPatchesForFiles, findAllPatchesForFilesWithDetails, } from './patch-export-coverage.js';
|
|
6
6
|
export { mutatePatchMetadata, updatePatchMetadata } from './patch-export-metadata.js';
|
|
7
7
|
export { updatePatchAndMetadata } from './patch-export-update.js';
|
|
8
|
+
/**
|
|
9
|
+
* Projects the planning subset out of a wider export input (commit input,
|
|
10
|
+
* dry-run preview input) — the fields `planExport` /
|
|
11
|
+
* `computeExportPlanUnderLock` read. Optional fields are copied only when
|
|
12
|
+
* present so the plan input never carries explicit `undefined` keys, which
|
|
13
|
+
* would otherwise leak into the written metadata via spread. The commit
|
|
14
|
+
* path and the dry-run preview both go through this one projection so
|
|
15
|
+
* they cannot drift field by field.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildPlanExportInput(input: PlanExportInput): PlanExportInput;
|
|
8
18
|
/**
|
|
9
19
|
* Gets the next patch number for a new patch.
|
|
10
20
|
* @param patchesDir - Path to the patches directory
|
|
@@ -91,26 +101,6 @@ export interface CommitExportedPatchResult {
|
|
|
91
101
|
* to filename allocation or supersede detection lands in both automatically.
|
|
92
102
|
*/
|
|
93
103
|
export declare function commitExportedPatch(input: CommitExportedPatchInput): Promise<CommitExportedPatchResult>;
|
|
94
|
-
/**
|
|
95
|
-
* Parses a patch filename to extract order, category, and name.
|
|
96
|
-
* Supports both new format (001-category-name.patch) and legacy (001-name.patch).
|
|
97
|
-
*/
|
|
98
|
-
export declare function parseFilename(filename: string): {
|
|
99
|
-
order: number;
|
|
100
|
-
category: PatchCategory | null;
|
|
101
|
-
name: string;
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Finds an existing patch that contains the specified file.
|
|
105
|
-
* Returns the most recent (highest order) patch if multiple exist.
|
|
106
|
-
* @param patchesDir - Path to the patches directory
|
|
107
|
-
* @param filePath - File path to search for
|
|
108
|
-
* @returns The patch info and metadata, or null if not found
|
|
109
|
-
*/
|
|
110
|
-
export declare function findExistingPatchForFile(patchesDir: string, filePath: string): Promise<{
|
|
111
|
-
patch: PatchInfo;
|
|
112
|
-
metadata: PatchMetadata;
|
|
113
|
-
} | null>;
|
|
114
104
|
/**
|
|
115
105
|
* Updates the content of a patch file.
|
|
116
106
|
* @param patchPath - Path to the patch file
|
|
@@ -3,17 +3,39 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { toError } from '../utils/errors.js';
|
|
4
4
|
import { pathExists, readText, removeFile, writeText } from '../utils/fs.js';
|
|
5
5
|
import { warn } from '../utils/logger.js';
|
|
6
|
-
import { PATCH_CATEGORIES } from '../utils/validation.js';
|
|
7
6
|
import { discoverPatches, withPatchDirectoryLock } from './patch-apply.js';
|
|
8
|
-
import { normalizePatchArtifact } from './patch-artifact-normalize.js';
|
|
9
7
|
import { findAllPatchesForFilesWithDetails, } from './patch-export-coverage.js';
|
|
10
|
-
import { addPatchToManifest,
|
|
11
|
-
import { requirePatchOrder } from './patch-parse.js';
|
|
8
|
+
import { addPatchToManifest, loadPatchesManifestForWrite, PATCHES_MANIFEST, savePatchesManifest, } from './patch-manifest.js';
|
|
9
|
+
import { formatPatchOrder, requirePatchOrder } from './patch-parse.js';
|
|
12
10
|
import { allocatePolicyOrder, enforcePatchPolicy } from './patch-policy.js';
|
|
13
|
-
export { findAllPatchesForFiles, findAllPatchesForFilesWithDetails,
|
|
11
|
+
export { findAllPatchesForFiles, findAllPatchesForFilesWithDetails, } from './patch-export-coverage.js';
|
|
14
12
|
import { escapeRegex } from '../utils/regex.js';
|
|
15
13
|
export { mutatePatchMetadata, updatePatchMetadata } from './patch-export-metadata.js';
|
|
16
14
|
export { updatePatchAndMetadata } from './patch-export-update.js';
|
|
15
|
+
/**
|
|
16
|
+
* Projects the planning subset out of a wider export input (commit input,
|
|
17
|
+
* dry-run preview input) — the fields `planExport` /
|
|
18
|
+
* `computeExportPlanUnderLock` read. Optional fields are copied only when
|
|
19
|
+
* present so the plan input never carries explicit `undefined` keys, which
|
|
20
|
+
* would otherwise leak into the written metadata via spread. The commit
|
|
21
|
+
* path and the dry-run preview both go through this one projection so
|
|
22
|
+
* they cannot drift field by field.
|
|
23
|
+
*/
|
|
24
|
+
export function buildPlanExportInput(input) {
|
|
25
|
+
return {
|
|
26
|
+
patchesDir: input.patchesDir,
|
|
27
|
+
category: input.category,
|
|
28
|
+
name: input.name,
|
|
29
|
+
description: input.description,
|
|
30
|
+
filesAffected: input.filesAffected,
|
|
31
|
+
sourceEsrVersion: input.sourceEsrVersion,
|
|
32
|
+
...(input.sourceProduct !== undefined ? { sourceProduct: input.sourceProduct } : {}),
|
|
33
|
+
...(input.sourceVersion !== undefined ? { sourceVersion: input.sourceVersion } : {}),
|
|
34
|
+
...(input.tier !== undefined ? { tier: input.tier } : {}),
|
|
35
|
+
...(input.lintIgnore !== undefined ? { lintIgnore: input.lintIgnore } : {}),
|
|
36
|
+
...(input.config !== undefined ? { config: input.config } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
17
39
|
/**
|
|
18
40
|
* Gets the next patch number for a new patch.
|
|
19
41
|
* @param patchesDir - Path to the patches directory
|
|
@@ -110,19 +132,7 @@ export async function getNextPatchFilename(patchesDir, category, name) {
|
|
|
110
132
|
*/
|
|
111
133
|
export async function commitExportedPatch(input) {
|
|
112
134
|
return withPatchDirectoryLock(input.patchesDir, async () => {
|
|
113
|
-
const plan = await computeExportPlanUnderLock(
|
|
114
|
-
patchesDir: input.patchesDir,
|
|
115
|
-
category: input.category,
|
|
116
|
-
name: input.name,
|
|
117
|
-
description: input.description,
|
|
118
|
-
filesAffected: input.filesAffected,
|
|
119
|
-
sourceEsrVersion: input.sourceEsrVersion,
|
|
120
|
-
...(input.sourceProduct !== undefined ? { sourceProduct: input.sourceProduct } : {}),
|
|
121
|
-
...(input.sourceVersion !== undefined ? { sourceVersion: input.sourceVersion } : {}),
|
|
122
|
-
...(input.tier !== undefined ? { tier: input.tier } : {}),
|
|
123
|
-
...(input.lintIgnore !== undefined ? { lintIgnore: input.lintIgnore } : {}),
|
|
124
|
-
...(input.config !== undefined ? { config: input.config } : {}),
|
|
125
|
-
});
|
|
135
|
+
const plan = await computeExportPlanUnderLock(buildPlanExportInput(input));
|
|
126
136
|
if (input.config !== undefined) {
|
|
127
137
|
enforcePatchPolicy({
|
|
128
138
|
config: input.config,
|
|
@@ -140,7 +150,20 @@ export async function commitExportedPatch(input) {
|
|
|
140
150
|
}
|
|
141
151
|
}
|
|
142
152
|
try {
|
|
143
|
-
|
|
153
|
+
// Patch bodies are written byte-for-byte as git produced them, including the
|
|
154
|
+
// single-space rendering of a blank context line.
|
|
155
|
+
//
|
|
156
|
+
// Do NOT add a whitespace-trimming pass here or at any other write site.
|
|
157
|
+
// Stripping marker lines whose payload is pure whitespace (`/^[ +-]\s+$/` →
|
|
158
|
+
// bare marker) corrupts real content: Firefox sources contain whitespace-only
|
|
159
|
+
// lines, so a ` `/`-` line whose payload was two spaces no longer matches the
|
|
160
|
+
// pristine tree and the freshly exported patch fails `git apply --check`,
|
|
161
|
+
// while a `+` line silently changes what the patch produces. The repository
|
|
162
|
+
// whitespace check already exempts `patches/*.patch`
|
|
163
|
+
// (scripts/check-worktree-whitespace.mjs), and the byte-fidelity contract is
|
|
164
|
+
// pinned end-to-end by `git-diff-latin1-roundtrip.test.ts` and
|
|
165
|
+
// `re-export.integration.test.ts`.
|
|
166
|
+
await writeText(patchPath, input.diff);
|
|
144
167
|
await addPatchToManifest(input.patchesDir, plan.metadata, plan.supersededPatches.map((p) => p.filename));
|
|
145
168
|
for (const oldPatch of plan.supersededPatches) {
|
|
146
169
|
await removeFile(oldPatch.path);
|
|
@@ -188,58 +211,13 @@ export async function commitExportedPatch(input) {
|
|
|
188
211
|
};
|
|
189
212
|
}, input.lockOptions ?? {});
|
|
190
213
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Parses a patch filename to extract order, category, and name.
|
|
193
|
-
* Supports both new format (001-category-name.patch) and legacy (001-name.patch).
|
|
194
|
-
*/
|
|
195
|
-
export function parseFilename(filename) {
|
|
196
|
-
// New format: 001-ui-sidebar.patch
|
|
197
|
-
const newMatch = /^(\d+)-([a-z]+)-(.+)\.patch$/.exec(filename);
|
|
198
|
-
if (newMatch?.[1] && newMatch[2] && newMatch[3]) {
|
|
199
|
-
const orderStr = newMatch[1];
|
|
200
|
-
const category = newMatch[2];
|
|
201
|
-
const name = newMatch[3];
|
|
202
|
-
if (PATCH_CATEGORIES.includes(category)) {
|
|
203
|
-
return {
|
|
204
|
-
order: parseInt(orderStr, 10),
|
|
205
|
-
category,
|
|
206
|
-
name,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
// Legacy format: 001-name.patch
|
|
211
|
-
const legacyMatch = /^(\d+)-(.+)\.patch$/.exec(filename);
|
|
212
|
-
if (legacyMatch?.[1] && legacyMatch[2]) {
|
|
213
|
-
return {
|
|
214
|
-
order: parseInt(legacyMatch[1], 10),
|
|
215
|
-
category: null,
|
|
216
|
-
name: legacyMatch[2],
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
return { order: Infinity, category: null, name: filename };
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Finds an existing patch that contains the specified file.
|
|
223
|
-
* Returns the most recent (highest order) patch if multiple exist.
|
|
224
|
-
* @param patchesDir - Path to the patches directory
|
|
225
|
-
* @param filePath - File path to search for
|
|
226
|
-
* @returns The patch info and metadata, or null if not found
|
|
227
|
-
*/
|
|
228
|
-
export async function findExistingPatchForFile(patchesDir, filePath) {
|
|
229
|
-
const affectingPatches = await findPatchesAffectingFile(patchesDir, filePath);
|
|
230
|
-
if (affectingPatches.length === 0) {
|
|
231
|
-
return null;
|
|
232
|
-
}
|
|
233
|
-
// Return the most recent (highest order) patch
|
|
234
|
-
return affectingPatches[affectingPatches.length - 1] ?? null;
|
|
235
|
-
}
|
|
236
214
|
/**
|
|
237
215
|
* Updates the content of a patch file.
|
|
238
216
|
* @param patchPath - Path to the patch file
|
|
239
217
|
* @param newContent - New patch content
|
|
240
218
|
*/
|
|
241
219
|
export async function updatePatch(patchPath, newContent) {
|
|
242
|
-
await writeText(patchPath,
|
|
220
|
+
await writeText(patchPath, newContent);
|
|
243
221
|
}
|
|
244
222
|
/**
|
|
245
223
|
* Internal planning helper. Does NOT take the patch directory lock — the
|
|
@@ -259,7 +237,7 @@ async function computeExportPlanUnderLock(input) {
|
|
|
259
237
|
? allocatePolicyOrder(input.config, manifestBefore?.patches ?? [], input.category)
|
|
260
238
|
: null;
|
|
261
239
|
const patchFilename = policyOrder !== null
|
|
262
|
-
? `${
|
|
240
|
+
? `${formatPatchOrder(policyOrder)}-${input.category}-${patchNameSlug(input.name, input.category)}.patch`
|
|
263
241
|
: await getNextPatchFilename(input.patchesDir, input.category, input.name);
|
|
264
242
|
const patchPath = join(input.patchesDir, patchFilename);
|
|
265
243
|
const metadata = {
|
|
@@ -3,10 +3,6 @@ import type { PatchInfo } from '../types/commands/index.js';
|
|
|
3
3
|
export declare function discoverPatches(patchesDir: string): Promise<PatchInfo[]>;
|
|
4
4
|
/** Counts the patch files currently present in a patch directory. */
|
|
5
5
|
export declare function countPatches(patchesDir: string): Promise<number>;
|
|
6
|
-
/** Checks whether a patch creates a new file rather than modifying an existing one. */
|
|
7
|
-
export declare function isNewFilePatch(patchPath: string): Promise<boolean>;
|
|
8
|
-
/** Returns the first target file path referenced by a patch, if any. */
|
|
9
|
-
export declare function getTargetFileFromPatch(patchPath: string): Promise<string | null>;
|
|
10
6
|
/**
|
|
11
7
|
* Returns all target file paths referenced by a multi-file patch.
|
|
12
8
|
*
|
|
@@ -24,17 +24,6 @@ export async function countPatches(patchesDir) {
|
|
|
24
24
|
const patches = await discoverPatches(patchesDir);
|
|
25
25
|
return patches.length;
|
|
26
26
|
}
|
|
27
|
-
/** Checks whether a patch creates a new file rather than modifying an existing one. */
|
|
28
|
-
export async function isNewFilePatch(patchPath) {
|
|
29
|
-
const content = await readText(patchPath);
|
|
30
|
-
return content.includes('new file mode') && content.includes('--- /dev/null');
|
|
31
|
-
}
|
|
32
|
-
/** Returns the first target file path referenced by a patch, if any. */
|
|
33
|
-
export async function getTargetFileFromPatch(patchPath) {
|
|
34
|
-
const content = await readText(patchPath);
|
|
35
|
-
const match = /^\+\+\+ b\/(.+)$/m.exec(content);
|
|
36
|
-
return match?.[1] ?? null;
|
|
37
|
-
}
|
|
38
27
|
/**
|
|
39
28
|
* Returns all target file paths referenced by a multi-file patch.
|
|
40
29
|
*
|
|
@@ -21,20 +21,14 @@
|
|
|
21
21
|
* cross-patch lint graph.
|
|
22
22
|
*/
|
|
23
23
|
import type { PatchLintIssue } from '../types/commands/index.js';
|
|
24
|
+
import type { PatchQueueBodyEntry, PatchQueueView } from './patch-lint-queue-types.js';
|
|
24
25
|
/**
|
|
25
|
-
*
|
|
26
|
-
* than importing `
|
|
27
|
-
* this module back — the
|
|
28
|
-
* `dpdm` clean
|
|
26
|
+
* Queue view accepted by {@link lintPatchQueueBinaryBodies}. Described
|
|
27
|
+
* structurally rather than by importing `PatchQueueContext` from
|
|
28
|
+
* `patch-lint-cross.ts`, which imports this module back — the shared leaf
|
|
29
|
+
* type keeps the dependency edge one-way and `dpdm` clean.
|
|
29
30
|
*/
|
|
30
|
-
|
|
31
|
-
filename: string;
|
|
32
|
-
diff: string;
|
|
33
|
-
}
|
|
34
|
-
/** Queue view accepted by {@link lintPatchQueueBinaryBodies}. */
|
|
35
|
-
interface BinaryBodyQueueContext {
|
|
36
|
-
entries: readonly BinaryBodyQueueEntry[];
|
|
37
|
-
}
|
|
31
|
+
type BinaryBodyQueueContext = PatchQueueView<PatchQueueBodyEntry>;
|
|
38
32
|
/** Lint check identifier emitted by {@link lintPatchQueueBinaryBodies}. */
|
|
39
33
|
export declare const BINARY_BODY_CHECK = "binary-body-not-reconstructable";
|
|
40
34
|
/**
|
|
@@ -58,5 +58,21 @@ export interface CachedPerPatchLint {
|
|
|
58
58
|
* is compared explicitly rather than trusted to the key.
|
|
59
59
|
*/
|
|
60
60
|
export declare function getCachedPerPatchLintIssues(cache: PerPatchLintCacheFile, patchFilename: string, key: string, lintIgnore?: Iterable<string>): CachedPerPatchLint | undefined;
|
|
61
|
+
export interface SetCachedPerPatchLintIssuesInput {
|
|
62
|
+
/** Cache file to mutate in place. */
|
|
63
|
+
cache: PerPatchLintCacheFile;
|
|
64
|
+
/** Patch the payload belongs to; also the cache entry key. */
|
|
65
|
+
patchFilename: string;
|
|
66
|
+
/** Fingerprint the payload is valid for. */
|
|
67
|
+
key: string;
|
|
68
|
+
/** Reported issues, stored as copies. */
|
|
69
|
+
issues: PatchLintIssue[];
|
|
70
|
+
/** Issues suppressed by `lintIgnore`, stored as copies. */
|
|
71
|
+
suppressed: PatchLintIssue[];
|
|
72
|
+
/** Line count the run measured. */
|
|
73
|
+
lineCount: number;
|
|
74
|
+
/** Suppression ids in force for the run, normalized on store. */
|
|
75
|
+
lintIgnore?: Iterable<string> | undefined;
|
|
76
|
+
}
|
|
61
77
|
/** Stores the per-patch lint payload after a successful lint calculation. */
|
|
62
|
-
export declare function setCachedPerPatchLintIssues(
|
|
78
|
+
export declare function setCachedPerPatchLintIssues(input: SetCachedPerPatchLintIssuesInput): void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
2
|
import { readFile } from 'node:fs/promises';
|
|
4
3
|
import { join, resolve } from 'node:path';
|
|
5
4
|
import { pathExists, readJson, writeJson } from '../utils/fs.js';
|
|
5
|
+
import { sha256Hex } from '../utils/hash.js';
|
|
6
6
|
import { getPackageVersion } from '../utils/package-root.js';
|
|
7
7
|
import { getFurnacePaths } from './furnace-config.js';
|
|
8
8
|
import { git } from './git-base.js';
|
|
@@ -42,10 +42,6 @@ function stableJson(value) {
|
|
|
42
42
|
.map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`)
|
|
43
43
|
.join(',')}}`;
|
|
44
44
|
}
|
|
45
|
-
/** Computes a SHA-256 hex digest for text or binary content. */
|
|
46
|
-
function sha256Hex(content) {
|
|
47
|
-
return createHash('sha256').update(content).digest('hex');
|
|
48
|
-
}
|
|
49
45
|
/** Computes a stable SHA-256 digest for JSON-compatible data. */
|
|
50
46
|
function stableHash(value) {
|
|
51
47
|
return sha256Hex(stableJson(value));
|
|
@@ -223,7 +219,8 @@ export function getCachedPerPatchLintIssues(cache, patchFilename, key, lintIgnor
|
|
|
223
219
|
};
|
|
224
220
|
}
|
|
225
221
|
/** Stores the per-patch lint payload after a successful lint calculation. */
|
|
226
|
-
export function setCachedPerPatchLintIssues(
|
|
222
|
+
export function setCachedPerPatchLintIssues(input) {
|
|
223
|
+
const { cache, patchFilename, key, issues, suppressed, lineCount, lintIgnore } = input;
|
|
227
224
|
cache.entries[patchFilename] = {
|
|
228
225
|
key,
|
|
229
226
|
patchFilename,
|
|
@@ -46,6 +46,37 @@ export interface GroupedCheckJsResult {
|
|
|
46
46
|
byFile: Map<string, PatchLintIssue[]>;
|
|
47
47
|
global: PatchLintIssue[];
|
|
48
48
|
}
|
|
49
|
+
/** Inputs for {@link runCheckJsGrouped}. */
|
|
50
|
+
export interface RunCheckJsGroupedInput {
|
|
51
|
+
/** Absolute engine (repository) directory. */
|
|
52
|
+
repoDir: string;
|
|
53
|
+
/**
|
|
54
|
+
* Patch-owned `.sys.mjs` paths (relative to `repoDir`) the program should
|
|
55
|
+
* see and resolve against.
|
|
56
|
+
*/
|
|
57
|
+
resolutionOwned: Set<string>;
|
|
58
|
+
/**
|
|
59
|
+
* Optional project-relative extra `.d.ts` appended to the built-in
|
|
60
|
+
* Firefox-globals shim (from `patchLint.checkJsExtraShim`).
|
|
61
|
+
*/
|
|
62
|
+
extraShimPath?: string;
|
|
63
|
+
/** Absolute project root for resolving `extraShimPath`. */
|
|
64
|
+
projectRoot?: string;
|
|
65
|
+
/** Strictness preset plus allowlisted compiler-option overrides. */
|
|
66
|
+
mode?: CheckJsMode;
|
|
67
|
+
/** Optional shim text appended AFTER the consumer shim. */
|
|
68
|
+
builtinShimSuffix?: string;
|
|
69
|
+
/**
|
|
70
|
+
* When set, only these repo-relative files become program ROOTS;
|
|
71
|
+
* resolution (and the host allowlist) still spans all of
|
|
72
|
+
* `resolutionOwned`, so a subset root's cross-patch imports type-check
|
|
73
|
+
* against the real owning sources while unrelated owned files are never
|
|
74
|
+
* parsed. `.mjs` files are module-scoped, so a root's diagnostics are
|
|
75
|
+
* identical whether other owned files are roots or mere resolution
|
|
76
|
+
* targets.
|
|
77
|
+
*/
|
|
78
|
+
rootScope?: ReadonlySet<string>;
|
|
79
|
+
}
|
|
49
80
|
/**
|
|
50
81
|
* Builds the checkJs program **once** over `resolutionOwned` and returns its
|
|
51
82
|
* diagnostics grouped by originating file. Callers slice the result by their
|
|
@@ -54,24 +85,10 @@ export interface GroupedCheckJsResult {
|
|
|
54
85
|
* every file in `resolutionOwned`, so cross-patch `resource:///`/`chrome://`
|
|
55
86
|
* imports resolve to real sources.
|
|
56
87
|
*
|
|
57
|
-
* @param
|
|
58
|
-
* @param resolutionOwned - Patch-owned `.sys.mjs` paths (relative to repoDir)
|
|
59
|
-
* the program should see and resolve against
|
|
60
|
-
* @param extraShimPath - Optional project-relative extra `.d.ts` appended to
|
|
61
|
-
* the built-in Firefox-globals shim (from `patchLint.checkJsExtraShim`)
|
|
62
|
-
* @param projectRoot - Absolute project root for resolving `extraShimPath`
|
|
63
|
-
* @param mode - Strictness preset plus allowlisted compiler-option overrides
|
|
64
|
-
* @param builtinShimSuffix - Optional shim text appended AFTER the consumer
|
|
65
|
-
* shim
|
|
66
|
-
* @param rootScope - When set, only these repo-relative files become program
|
|
67
|
-
* ROOTS; resolution (and the host allowlist) still spans all of
|
|
68
|
-
* `resolutionOwned`, so a subset root's cross-patch imports type-check
|
|
69
|
-
* against the real owning sources while unrelated owned files are never
|
|
70
|
-
* parsed. `.mjs` files are module-scoped, so a root's diagnostics are
|
|
71
|
-
* identical whether other owned files are roots or mere resolution targets.
|
|
88
|
+
* @param input - Program inputs; see {@link RunCheckJsGroupedInput}
|
|
72
89
|
* @returns Diagnostics grouped per owning file plus run-level errors
|
|
73
90
|
*/
|
|
74
|
-
export declare function runCheckJsGrouped(
|
|
91
|
+
export declare function runCheckJsGrouped(input: RunCheckJsGroupedInput): Promise<GroupedCheckJsResult>;
|
|
75
92
|
/**
|
|
76
93
|
* Flattens a {@link runCheckJsGrouped} run into a single issue list. When
|
|
77
94
|
* `reportScope` is supplied, only diagnostics from files in that set are
|
|
@@ -30,6 +30,7 @@ import { toError } from '../utils/errors.js';
|
|
|
30
30
|
import { pathExists } from '../utils/fs.js';
|
|
31
31
|
import { verbose } from '../utils/logger.js';
|
|
32
32
|
import { normalizePathSlashes } from '../utils/paths.js';
|
|
33
|
+
import { collectUnmanagedCompanions, retargetUnmanagedCompanionHints, } from './patch-lint-unmanaged-companion.js';
|
|
33
34
|
import { composeShimSource, SHIM_FILENAME, SUPPRESSED_DIAGNOSTIC_CODES, TEST_HARNESS_SHIM, UNDEFINED_IDENTIFIER_CODES, UNDEFINED_IDENTIFIER_HINT, } from './typecheck-shim.js';
|
|
34
35
|
// ---------------------------------------------------------------------------
|
|
35
36
|
// Public API
|
|
@@ -161,24 +162,11 @@ function createPathsResolver(ts, paths, baseDir, fileExists, onResolved) {
|
|
|
161
162
|
* every file in `resolutionOwned`, so cross-patch `resource:///`/`chrome://`
|
|
162
163
|
* imports resolve to real sources.
|
|
163
164
|
*
|
|
164
|
-
* @param
|
|
165
|
-
* @param resolutionOwned - Patch-owned `.sys.mjs` paths (relative to repoDir)
|
|
166
|
-
* the program should see and resolve against
|
|
167
|
-
* @param extraShimPath - Optional project-relative extra `.d.ts` appended to
|
|
168
|
-
* the built-in Firefox-globals shim (from `patchLint.checkJsExtraShim`)
|
|
169
|
-
* @param projectRoot - Absolute project root for resolving `extraShimPath`
|
|
170
|
-
* @param mode - Strictness preset plus allowlisted compiler-option overrides
|
|
171
|
-
* @param builtinShimSuffix - Optional shim text appended AFTER the consumer
|
|
172
|
-
* shim
|
|
173
|
-
* @param rootScope - When set, only these repo-relative files become program
|
|
174
|
-
* ROOTS; resolution (and the host allowlist) still spans all of
|
|
175
|
-
* `resolutionOwned`, so a subset root's cross-patch imports type-check
|
|
176
|
-
* against the real owning sources while unrelated owned files are never
|
|
177
|
-
* parsed. `.mjs` files are module-scoped, so a root's diagnostics are
|
|
178
|
-
* identical whether other owned files are roots or mere resolution targets.
|
|
165
|
+
* @param input - Program inputs; see {@link RunCheckJsGroupedInput}
|
|
179
166
|
* @returns Diagnostics grouped per owning file plus run-level errors
|
|
180
167
|
*/
|
|
181
|
-
export async function runCheckJsGrouped(
|
|
168
|
+
export async function runCheckJsGrouped(input) {
|
|
169
|
+
const { repoDir, resolutionOwned, extraShimPath, rootScope } = input;
|
|
182
170
|
const empty = { byFile: new Map(), global: [] };
|
|
183
171
|
if (resolutionOwned.size === 0)
|
|
184
172
|
return empty;
|
|
@@ -226,12 +214,14 @@ export async function runCheckJsGrouped(repoDir, resolutionOwned, extraShimPath,
|
|
|
226
214
|
// also undefined, so the resolution target is irrelevant.
|
|
227
215
|
let shimSource;
|
|
228
216
|
try {
|
|
229
|
-
const composed = await composeShimSource(projectRoot ?? repoDir, extraShimPath);
|
|
217
|
+
const composed = await composeShimSource(input.projectRoot ?? repoDir, extraShimPath);
|
|
230
218
|
// The suffix (e.g. the loose test-harness baseline) goes
|
|
231
219
|
// AFTER the consumer's extra shim: TypeScript resolves conflicting
|
|
232
220
|
// `declare var` redeclarations to the FIRST declaration, so a typed
|
|
233
221
|
// consumer declaration must precede the loose fallback to win.
|
|
234
|
-
shimSource =
|
|
222
|
+
shimSource = input.builtinShimSuffix
|
|
223
|
+
? `${composed.source}\n${input.builtinShimSuffix}`
|
|
224
|
+
: composed.source;
|
|
235
225
|
if (composed.extraShimAppended) {
|
|
236
226
|
verbose(`checkJs: extra shim ${extraShimPath ?? ''} appended to Firefox globals shim`);
|
|
237
227
|
}
|
|
@@ -251,7 +241,7 @@ export async function runCheckJsGrouped(repoDir, resolutionOwned, extraShimPath,
|
|
|
251
241
|
}
|
|
252
242
|
const shimPath = toTsPath(resolve(repoDir, SHIM_FILENAME));
|
|
253
243
|
rootFiles.push(shimPath);
|
|
254
|
-
const strict = mode?.strict === true;
|
|
244
|
+
const strict = input.mode?.strict === true;
|
|
255
245
|
const strictness = strict
|
|
256
246
|
? { strict: true, noImplicitAny: true }
|
|
257
247
|
: {
|
|
@@ -265,7 +255,7 @@ export async function runCheckJsGrouped(repoDir, resolutionOwned, extraShimPath,
|
|
|
265
255
|
// sources without a hand-generated ambient stub shim.
|
|
266
256
|
const overrides = {};
|
|
267
257
|
let pathsMapping;
|
|
268
|
-
const co = mode?.compilerOptions;
|
|
258
|
+
const co = input.mode?.compilerOptions;
|
|
269
259
|
if (co) {
|
|
270
260
|
for (const key of Object.keys(co)) {
|
|
271
261
|
const v = co[key];
|
|
@@ -350,7 +340,7 @@ export async function runCheckJsGrouped(repoDir, resolutionOwned, extraShimPath,
|
|
|
350
340
|
},
|
|
351
341
|
};
|
|
352
342
|
const program = ts.createProgram(rootFiles, options, host);
|
|
353
|
-
const byFile = groupOwnedDiagnostics(ts, [...program.getSemanticDiagnostics(), ...program.getSyntacticDiagnostics()], relByAbsolute, mode?.undefinedIdentifiers ?? 'warning');
|
|
343
|
+
const byFile = groupOwnedDiagnostics(ts, [...program.getSemanticDiagnostics(), ...program.getSyntacticDiagnostics()], relByAbsolute, input.mode?.undefinedIdentifiers ?? 'warning');
|
|
354
344
|
verbose(`checkJs: analyzed ${rootFiles.length - 1} file(s) across ${byFile.size} owning file(s)`);
|
|
355
345
|
return { byFile, global: [] };
|
|
356
346
|
}
|
|
@@ -416,7 +406,13 @@ function groupOwnedDiagnostics(ts, diagnostics, relByAbsolute, undefinedIdentifi
|
|
|
416
406
|
* @returns Array of lint issues from TS diagnostics
|
|
417
407
|
*/
|
|
418
408
|
export async function runCheckJs(repoDir, patchOwnedFiles, extraShimPath, projectRoot, mode, reportScope) {
|
|
419
|
-
const { byFile, global } = await runCheckJsGrouped(
|
|
409
|
+
const { byFile, global } = await runCheckJsGrouped({
|
|
410
|
+
repoDir,
|
|
411
|
+
resolutionOwned: patchOwnedFiles,
|
|
412
|
+
...(extraShimPath !== undefined ? { extraShimPath } : {}),
|
|
413
|
+
...(projectRoot !== undefined ? { projectRoot } : {}),
|
|
414
|
+
...(mode !== undefined ? { mode } : {}),
|
|
415
|
+
});
|
|
420
416
|
const issues = [...global];
|
|
421
417
|
for (const [rel, list] of byFile) {
|
|
422
418
|
if (reportScope && !reportScope.has(rel))
|
|
@@ -464,6 +460,7 @@ export async function runCheckJsTestFilesGrouped(repoDir, testFiles, patchLint,
|
|
|
464
460
|
const mode = modeFromPatchLintConfig(patchLint);
|
|
465
461
|
const seenGlobal = new Set();
|
|
466
462
|
const files = [...testFiles].sort((a, b) => a.localeCompare(b));
|
|
463
|
+
const companions = await collectUnmanagedCompanions(repoDir, files, testFiles);
|
|
467
464
|
for (const file of files) {
|
|
468
465
|
// Under a rootScope only the scoped files get their own program, but
|
|
469
466
|
// head.js helper discovery still spans the full owned set so a scoped
|
|
@@ -480,10 +477,22 @@ export async function runCheckJsTestFilesGrouped(repoDir, testFiles, patchLint,
|
|
|
480
477
|
roots.add(candidate);
|
|
481
478
|
}
|
|
482
479
|
}
|
|
483
|
-
const result = await runCheckJsGrouped(
|
|
480
|
+
const result = await runCheckJsGrouped({
|
|
481
|
+
repoDir,
|
|
482
|
+
resolutionOwned: roots,
|
|
483
|
+
...(patchLint.checkJsTestShim !== undefined
|
|
484
|
+
? { extraShimPath: patchLint.checkJsTestShim }
|
|
485
|
+
: {}),
|
|
486
|
+
projectRoot,
|
|
487
|
+
mode,
|
|
488
|
+
builtinShimSuffix: TEST_HARNESS_SHIM,
|
|
489
|
+
});
|
|
484
490
|
const own = result.byFile.get(file);
|
|
485
491
|
if (own && own.length > 0) {
|
|
486
|
-
merged.byFile.set(file, [
|
|
492
|
+
merged.byFile.set(file, [
|
|
493
|
+
...(merged.byFile.get(file) ?? []),
|
|
494
|
+
...retargetUnmanagedCompanionHints(own, companions),
|
|
495
|
+
]);
|
|
487
496
|
}
|
|
488
497
|
for (const globalIssue of result.global) {
|
|
489
498
|
if (seenGlobal.has(globalIssue.message))
|
|
@@ -522,7 +531,16 @@ function modeFromPatchLintConfig(patchLint) {
|
|
|
522
531
|
* (`--patches`); resolution still spans the whole queue
|
|
523
532
|
*/
|
|
524
533
|
export async function invokePatchLintCheckJsGrouped(repoDir, patchOwnedFiles, patchLint, projectRoot, rootScope) {
|
|
525
|
-
return runCheckJsGrouped(
|
|
534
|
+
return runCheckJsGrouped({
|
|
535
|
+
repoDir,
|
|
536
|
+
resolutionOwned: patchOwnedFiles,
|
|
537
|
+
...(patchLint.checkJsExtraShim !== undefined
|
|
538
|
+
? { extraShimPath: patchLint.checkJsExtraShim }
|
|
539
|
+
: {}),
|
|
540
|
+
projectRoot,
|
|
541
|
+
mode: modeFromPatchLintConfig(patchLint),
|
|
542
|
+
...(rootScope !== undefined ? { rootScope } : {}),
|
|
543
|
+
});
|
|
526
544
|
}
|
|
527
545
|
/**
|
|
528
546
|
* Cheap probe reproducing the only run-level ("global") checkJs findings the
|
|
@@ -10,13 +10,9 @@
|
|
|
10
10
|
* so a discarded context frees its map; a caller that mutates a context
|
|
11
11
|
* entry in place must call {@link invalidateNewFileCreatorsCache}.
|
|
12
12
|
*/
|
|
13
|
+
import type { PatchQueueBodyEntry, PatchQueueView } from './patch-lint-queue-types.js';
|
|
13
14
|
/** The slice of a queue context the creators map is derived from. */
|
|
14
|
-
|
|
15
|
-
entries: {
|
|
16
|
-
filename: string;
|
|
17
|
-
diff: string;
|
|
18
|
-
}[];
|
|
19
|
-
}
|
|
15
|
+
type CreatorsContext = PatchQueueView<PatchQueueBodyEntry>;
|
|
20
16
|
/** Drops the memoised creators map after an in-place context entry update. */
|
|
21
17
|
export declare function invalidateNewFileCreatorsCache(ctx: CreatorsContext): void;
|
|
22
18
|
/**
|
|
@@ -34,6 +34,17 @@ export interface PatchQueueEntry {
|
|
|
34
34
|
* are not indexed here.
|
|
35
35
|
*/
|
|
36
36
|
newFiles: Map<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Every path this patch CREATES, whatever the body kind — text, a
|
|
39
|
+
* reconstructable `GIT binary patch`, or a payload-less
|
|
40
|
+
* `Binary files … differ` stub. `newFiles` is text-only by design (a
|
|
41
|
+
* binary authors no imports, so the import rules gain nothing from it and
|
|
42
|
+
* `extractNewFileContent` correctly refuses to decode one), but "does a
|
|
43
|
+
* later patch create this path" is a question about existence after apply,
|
|
44
|
+
* not about content — and answering it from `newFiles` made every binary
|
|
45
|
+
* creation invisible to the staged-registration rules.
|
|
46
|
+
*/
|
|
47
|
+
createdFiles: Set<string>;
|
|
37
48
|
/**
|
|
38
49
|
* Map from existing-file path → concatenated added lines from the patch's
|
|
39
50
|
* hunks against that file (joined with `\n`). Populated for files the
|
|
@@ -109,13 +120,10 @@ export declare function isForwardImportableFile(path: string): boolean;
|
|
|
109
120
|
* Returns the raw specifier strings — callers should take the leaf basename
|
|
110
121
|
* to match against the newFileIndex, because we do not resolve `resource://`
|
|
111
122
|
* URLs to engine file paths.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
*
|
|
116
|
-
* (0-indexed) line number where each specifier was found. Used by the
|
|
117
|
-
* forward-import rule so it can correlate specifiers against the
|
|
118
|
-
* ignore-marker line set and skip suppressed matches.
|
|
123
|
+
*
|
|
124
|
+
* Also returns the (0-indexed) line number where each specifier was found, so
|
|
125
|
+
* the forward-import rule can correlate specifiers against the ignore-marker
|
|
126
|
+
* line set and skip suppressed matches.
|
|
119
127
|
*/
|
|
120
128
|
export interface ExtractedSpecifier {
|
|
121
129
|
specifier: string;
|
|
@@ -123,7 +131,7 @@ export interface ExtractedSpecifier {
|
|
|
123
131
|
}
|
|
124
132
|
/**
|
|
125
133
|
* Returns import specifiers plus 0-indexed line numbers, preserving the
|
|
126
|
-
* same matching behavior as {@link
|
|
134
|
+
* same matching behavior as {@link extractImportSpecifiersWithLines}.
|
|
127
135
|
*/
|
|
128
136
|
export declare function extractImportSpecifiersWithLines(source: string): ExtractedSpecifier[];
|
|
129
137
|
/**
|