@hominis/fireforge 0.35.0 → 0.37.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 +42 -0
- package/README.md +34 -9
- package/dist/bin/fireforge.js +21 -6
- package/dist/src/cli.js +22 -5
- package/dist/src/commands/bootstrap-checks.js +0 -1
- package/dist/src/commands/bootstrap.d.ts +2 -1
- package/dist/src/commands/bootstrap.js +16 -7
- package/dist/src/commands/build.js +5 -4
- package/dist/src/commands/config.js +30 -10
- package/dist/src/commands/discard.js +18 -3
- package/dist/src/commands/doctor/post-rebase-audit.js +0 -1
- package/dist/src/commands/doctor-check-core.js +0 -1
- package/dist/src/commands/doctor-external-toolchains.d.ts +3 -0
- package/dist/src/commands/doctor-external-toolchains.js +54 -0
- package/dist/src/commands/doctor-furnace-jar.js +0 -1
- package/dist/src/commands/doctor-furnace-manifest-sync.js +0 -1
- package/dist/src/commands/doctor-furnace.js +2 -2
- package/dist/src/commands/doctor-orphaned-harness.d.ts +52 -0
- package/dist/src/commands/doctor-orphaned-harness.js +132 -0
- package/dist/src/commands/doctor-working-tree.js +0 -1
- package/dist/src/commands/doctor.js +6 -1
- package/dist/src/commands/download.js +28 -13
- package/dist/src/commands/export-all.js +5 -3
- package/dist/src/commands/export-flow.js +12 -7
- package/dist/src/commands/export-placement-gate.js +0 -1
- package/dist/src/commands/export-placement-policy.js +0 -1
- package/dist/src/commands/export-shared.d.ts +5 -1
- package/dist/src/commands/export-shared.js +18 -6
- package/dist/src/commands/export.js +22 -10
- package/dist/src/commands/furnace/apply.js +22 -6
- package/dist/src/commands/furnace/chrome-doc-remove.js +0 -1
- package/dist/src/commands/furnace/chrome-doc-templates.js +0 -1
- package/dist/src/commands/furnace/chrome-doc-tests.js +0 -1
- package/dist/src/commands/furnace/chrome-doc.js +0 -1
- package/dist/src/commands/furnace/create-browser-test.js +0 -1
- package/dist/src/commands/furnace/create-dry-run.js +0 -1
- package/dist/src/commands/furnace/create-features.js +0 -1
- package/dist/src/commands/furnace/create-mochikit.js +0 -1
- package/dist/src/commands/furnace/create-readback.js +0 -1
- package/dist/src/commands/furnace/create-templates.js +0 -1
- package/dist/src/commands/furnace/create-validation.js +0 -1
- package/dist/src/commands/furnace/create-xpcshell.js +0 -1
- package/dist/src/commands/furnace/create.js +0 -1
- package/dist/src/commands/furnace/deploy.js +7 -83
- package/dist/src/commands/furnace/diff.js +0 -1
- package/dist/src/commands/furnace/index.js +59 -25
- package/dist/src/commands/furnace/init.js +0 -1
- package/dist/src/commands/furnace/list.js +0 -1
- package/dist/src/commands/furnace/override.js +0 -1
- package/dist/src/commands/furnace/preview.js +3 -3
- package/dist/src/commands/furnace/refresh.js +0 -1
- package/dist/src/commands/furnace/remove-state.d.ts +15 -0
- package/dist/src/commands/furnace/remove-state.js +47 -1
- package/dist/src/commands/furnace/remove.js +3 -9
- package/dist/src/commands/furnace/rename-browser-test.js +1 -5
- package/dist/src/commands/furnace/rename-helpers.d.ts +6 -0
- package/dist/src/commands/furnace/rename-helpers.js +30 -1
- package/dist/src/commands/furnace/rename-xpcshell.js +7 -6
- package/dist/src/commands/furnace/rename.js +15 -36
- package/dist/src/commands/furnace/scan.js +0 -1
- package/dist/src/commands/furnace/status.js +0 -1
- package/dist/src/commands/furnace/sync.js +76 -4
- package/dist/src/commands/furnace/validate.js +0 -1
- package/dist/src/commands/furnace/validation-output.js +0 -1
- package/dist/src/commands/import.js +35 -9
- package/dist/src/commands/lint-per-patch.js +19 -7
- package/dist/src/commands/lint.js +13 -3
- package/dist/src/commands/manifest.js +1 -2
- package/dist/src/commands/package.js +2 -1
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +1 -1
- package/dist/src/commands/patch/index.js +1 -1
- package/dist/src/commands/patch/lint-ignore.js +21 -6
- package/dist/src/commands/patch/move-files.js +1 -1
- package/dist/src/commands/patch/patch-context.js +0 -1
- package/dist/src/commands/patch/rename.js +4 -4
- package/dist/src/commands/patch/reorder.js +3 -4
- package/dist/src/commands/patch/split-plan.js +2 -1
- package/dist/src/commands/patch/split.js +4 -4
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +114 -52
- package/dist/src/commands/patch/tier.js +18 -5
- package/dist/src/commands/re-export-bulk-scan.js +0 -1
- package/dist/src/commands/re-export-files.js +5 -1
- package/dist/src/commands/re-export-options.js +0 -1
- package/dist/src/commands/re-export-scan.js +0 -1
- package/dist/src/commands/re-export.js +14 -4
- package/dist/src/commands/rebase/abort.js +2 -9
- package/dist/src/commands/rebase/confirm.js +0 -1
- package/dist/src/commands/rebase/conflict-summary.js +0 -1
- package/dist/src/commands/rebase/continue.js +0 -1
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +10 -15
- package/dist/src/commands/rebase/patch-loop.js +38 -7
- package/dist/src/commands/rebase/summary.js +2 -3
- package/dist/src/commands/rebase.js +0 -1
- package/dist/src/commands/register.js +1 -1
- package/dist/src/commands/reset.js +16 -9
- package/dist/src/commands/resolve.js +2 -2
- package/dist/src/commands/run.js +4 -4
- package/dist/src/commands/setup-support.js +0 -1
- package/dist/src/commands/setup.js +1 -2
- package/dist/src/commands/source.js +1 -2
- package/dist/src/commands/status-output.js +1 -12
- package/dist/src/commands/status.js +147 -133
- package/dist/src/commands/test-appdir.js +0 -1
- package/dist/src/commands/test-diagnose.js +38 -3
- package/dist/src/commands/test-modes.d.ts +15 -0
- package/dist/src/commands/test-modes.js +61 -0
- package/dist/src/commands/test-register.d.ts +4 -0
- package/dist/src/commands/test-register.js +64 -0
- package/dist/src/commands/test-run.d.ts +23 -7
- package/dist/src/commands/test-run.js +15 -14
- package/dist/src/commands/test.d.ts +0 -4
- package/dist/src/commands/test.js +147 -96
- package/dist/src/commands/token-coverage.js +0 -1
- package/dist/src/commands/token.js +1 -2
- package/dist/src/commands/typecheck.js +1 -1
- package/dist/src/commands/verify.js +3 -9
- package/dist/src/commands/watch.js +5 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/ast-utils.js +0 -1
- package/dist/src/core/brand-validation.js +0 -1
- package/dist/src/core/branding.js +0 -1
- package/dist/src/core/browser-wire.js +0 -1
- package/dist/src/core/build-audit-platform.js +0 -1
- package/dist/src/core/build-audit-registration.js +0 -1
- package/dist/src/core/build-audit-resolve.js +0 -1
- package/dist/src/core/build-audit-transforms.js +0 -1
- package/dist/src/core/build-audit.js +0 -1
- package/dist/src/core/build-baseline-types.d.ts +24 -0
- package/dist/src/core/build-baseline-types.js +0 -1
- package/dist/src/core/build-baseline.d.ts +5 -2
- package/dist/src/core/build-baseline.js +5 -2
- package/dist/src/core/build-prepare.js +2 -2
- package/dist/src/core/config-mutate.js +0 -1
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +6 -1
- package/dist/src/core/config-state.js +0 -1
- package/dist/src/core/config-validate-patch-policy.js +0 -1
- package/dist/src/core/config-validate-test-toolchains.d.ts +8 -0
- package/dist/src/core/config-validate-test-toolchains.js +105 -0
- package/dist/src/core/config-validate.js +3 -1
- package/dist/src/core/config.js +0 -1
- package/dist/src/core/destructive.js +0 -1
- package/dist/src/core/diff-hunks.js +13 -7
- package/dist/src/core/engine-changes.js +0 -1
- package/dist/src/core/engine-session-lock.d.ts +12 -0
- package/dist/src/core/engine-session-lock.js +45 -0
- package/dist/src/core/file-lock.d.ts +8 -0
- package/dist/src/core/file-lock.js +157 -48
- package/dist/src/core/firefox-archive.d.ts +4 -0
- package/dist/src/core/firefox-archive.js +6 -1
- package/dist/src/core/firefox-cache.js +60 -4
- package/dist/src/core/firefox-download.js +0 -1
- package/dist/src/core/firefox-extract.js +75 -16
- package/dist/src/core/firefox-ignorefile.js +0 -1
- package/dist/src/core/firefox.d.ts +12 -0
- package/dist/src/core/firefox.js +64 -2
- package/dist/src/core/furnace-apply-dry-run.js +0 -1
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -3
- package/dist/src/core/furnace-apply-ftl.js +10 -5
- package/dist/src/core/furnace-apply-helpers.js +0 -1
- package/dist/src/core/furnace-apply-output.js +2 -2
- package/dist/src/core/furnace-apply.d.ts +7 -1
- package/dist/src/core/furnace-apply.js +47 -13
- package/dist/src/core/furnace-checksum-utils.js +0 -1
- package/dist/src/core/furnace-config-array-utils.js +0 -1
- package/dist/src/core/furnace-config-custom.js +10 -1
- package/dist/src/core/furnace-config-order.js +0 -1
- package/dist/src/core/furnace-config-tokens.js +0 -1
- package/dist/src/core/furnace-config-validate.js +0 -1
- package/dist/src/core/furnace-config.d.ts +11 -0
- package/dist/src/core/furnace-config.js +37 -1
- package/dist/src/core/furnace-constants.js +0 -1
- package/dist/src/core/furnace-css-fragments.js +0 -1
- package/dist/src/core/furnace-graph-utils.js +0 -1
- package/dist/src/core/furnace-jsconfig.d.ts +2 -3
- package/dist/src/core/furnace-jsconfig.js +25 -18
- package/dist/src/core/furnace-marker.js +0 -1
- package/dist/src/core/furnace-operation.js +0 -1
- package/dist/src/core/furnace-refresh.js +0 -1
- package/dist/src/core/furnace-registration-ast.d.ts +14 -0
- package/dist/src/core/furnace-registration-ast.js +1 -2
- package/dist/src/core/furnace-registration-remove.js +0 -1
- package/dist/src/core/furnace-registration-validate.js +1 -5
- package/dist/src/core/furnace-registration.js +0 -1
- package/dist/src/core/furnace-rollback.js +0 -1
- package/dist/src/core/furnace-scanner.js +0 -1
- package/dist/src/core/furnace-stale-export.d.ts +59 -0
- package/dist/src/core/furnace-stale-export.js +123 -0
- package/dist/src/core/furnace-staleness.js +0 -1
- package/dist/src/core/furnace-state-persist.d.ts +72 -0
- package/dist/src/core/furnace-state-persist.js +118 -0
- package/dist/src/core/furnace-step-errors.d.ts +23 -0
- package/dist/src/core/furnace-step-errors.js +25 -0
- package/dist/src/core/furnace-stories.js +0 -1
- package/dist/src/core/furnace-validate-accessibility.js +0 -1
- package/dist/src/core/furnace-validate-checks.js +0 -1
- package/dist/src/core/furnace-validate-compatibility.js +9 -3
- package/dist/src/core/furnace-validate-helpers.js +0 -1
- package/dist/src/core/furnace-validate-registration.js +7 -7
- package/dist/src/core/furnace-validate-structure.d.ts +8 -0
- package/dist/src/core/furnace-validate-structure.js +14 -4
- package/dist/src/core/furnace-validate.js +0 -1
- package/dist/src/core/furnace-version-drift.d.ts +6 -3
- package/dist/src/core/furnace-version-drift.js +6 -4
- package/dist/src/core/git-base.js +0 -1
- package/dist/src/core/git-diff.js +0 -1
- package/dist/src/core/git-file-ops.js +0 -1
- package/dist/src/core/git-status.d.ts +13 -0
- package/dist/src/core/git-status.js +32 -2
- package/dist/src/core/git.d.ts +10 -1
- package/dist/src/core/git.js +63 -6
- package/dist/src/core/license-headers.js +0 -1
- package/dist/src/core/lint-cache.js +0 -1
- package/dist/src/core/lint-projection.js +0 -1
- package/dist/src/core/mach-build-artifacts.js +0 -1
- package/dist/src/core/mach-error-hints.js +0 -1
- package/dist/src/core/mach-known-noise-filter.d.ts +60 -0
- package/dist/src/core/mach-known-noise-filter.js +193 -0
- package/dist/src/core/mach-mozconfig.js +0 -1
- package/dist/src/core/mach-python.js +0 -1
- package/dist/src/core/mach-resource-shim.js +0 -1
- package/dist/src/core/mach.d.ts +8 -0
- package/dist/src/core/mach.js +36 -4
- package/dist/src/core/manifest-helpers.js +0 -1
- package/dist/src/core/manifest-register.js +0 -1
- package/dist/src/core/manifest-rules.js +0 -1
- package/dist/src/core/manifest-tokenizers.js +0 -1
- package/dist/src/core/marionette-port.d.ts +8 -0
- package/dist/src/core/marionette-port.js +34 -3
- package/dist/src/core/marionette-preflight.js +0 -1
- package/dist/src/core/markdown-table.js +0 -1
- package/dist/src/core/ownership-table.js +2 -9
- package/dist/src/core/parser-fallback.js +0 -1
- package/dist/src/core/patch-apply-fuzz.d.ts +27 -9
- package/dist/src/core/patch-apply-fuzz.js +71 -34
- package/dist/src/core/patch-apply.d.ts +30 -0
- package/dist/src/core/patch-apply.js +101 -18
- package/dist/src/core/patch-artifact-normalize.d.ts +18 -5
- package/dist/src/core/patch-artifact-normalize.js +19 -15
- package/dist/src/core/patch-export-coverage.js +0 -1
- package/dist/src/core/patch-export-metadata.js +0 -1
- package/dist/src/core/patch-export-update.js +2 -3
- package/dist/src/core/patch-export.d.ts +2 -6
- package/dist/src/core/patch-export.js +24 -48
- package/dist/src/core/patch-files.js +0 -1
- package/dist/src/core/patch-identifier-suggest.js +0 -1
- package/dist/src/core/patch-lint-checkjs.js +0 -1
- package/dist/src/core/patch-lint-chrome-jsdoc.js +0 -1
- package/dist/src/core/patch-lint-cross.js +80 -3
- package/dist/src/core/patch-lint-css.js +0 -1
- package/dist/src/core/patch-lint-diff-tag.js +0 -1
- package/dist/src/core/patch-lint-diff.d.ts +2 -1
- package/dist/src/core/patch-lint-diff.js +17 -32
- package/dist/src/core/patch-lint-imports.js +0 -1
- package/dist/src/core/patch-lint-jsdoc.js +0 -1
- package/dist/src/core/patch-lint-observer.js +0 -1
- package/dist/src/core/patch-lint-ownership.js +0 -1
- package/dist/src/core/patch-lint-reexports.js +0 -1
- package/dist/src/core/patch-lint.d.ts +37 -2
- package/dist/src/core/patch-lint.js +47 -34
- package/dist/src/core/patch-lock.js +0 -1
- package/dist/src/core/patch-manifest-consistency.js +9 -1
- package/dist/src/core/patch-manifest-io.d.ts +19 -2
- package/dist/src/core/patch-manifest-io.js +57 -21
- package/dist/src/core/patch-manifest-query.js +18 -10
- package/dist/src/core/patch-manifest-resolve.js +0 -1
- package/dist/src/core/patch-manifest-validate.js +24 -1
- package/dist/src/core/patch-manifest.d.ts +1 -1
- package/dist/src/core/patch-manifest.js +1 -2
- package/dist/src/core/patch-parse.d.ts +59 -0
- package/dist/src/core/patch-parse.js +209 -92
- package/dist/src/core/patch-policy.js +0 -1
- package/dist/src/core/patch-registration-refs.js +16 -26
- package/dist/src/core/patch-source-metadata.js +0 -1
- package/dist/src/core/patch-transform.d.ts +4 -0
- package/dist/src/core/patch-transform.js +30 -38
- package/dist/src/core/rebase-session.js +0 -1
- package/dist/src/core/register-browser-content.js +0 -1
- package/dist/src/core/register-module.js +0 -1
- package/dist/src/core/register-result.js +0 -1
- package/dist/src/core/register-scaffold.js +0 -1
- package/dist/src/core/register-shared-css.js +0 -1
- package/dist/src/core/register-test-manifest.js +0 -1
- package/dist/src/core/register-xpcshell-test.js +0 -1
- package/dist/src/core/shared-ftl.js +0 -1
- package/dist/src/core/signal-critical.js +0 -1
- package/dist/src/core/smoke-patterns.js +0 -1
- package/dist/src/core/state-file.js +0 -1
- package/dist/src/core/status-classify.d.ts +16 -0
- package/dist/src/core/status-classify.js +24 -16
- package/dist/src/core/test-harness-crash.d.ts +80 -7
- package/dist/src/core/test-harness-crash.js +251 -15
- package/dist/src/core/test-harness-output.js +0 -1
- package/dist/src/core/test-path-scope.d.ts +21 -13
- package/dist/src/core/test-path-scope.js +43 -28
- package/dist/src/core/test-stale-check.d.ts +29 -1
- package/dist/src/core/test-stale-check.js +59 -1
- package/dist/src/core/test-stale-symlink.js +0 -1
- package/dist/src/core/test-xpcshell-retry.js +0 -1
- package/dist/src/core/token-coverage.js +0 -1
- package/dist/src/core/token-dark-mode.js +0 -1
- package/dist/src/core/token-docs.js +0 -1
- package/dist/src/core/token-manager.js +0 -1
- package/dist/src/core/token-scaffold.js +0 -1
- package/dist/src/core/token-variant.js +0 -1
- package/dist/src/core/toolchain-preflight.d.ts +31 -10
- package/dist/src/core/toolchain-preflight.js +97 -36
- package/dist/src/core/typecheck-shim.js +13 -1
- package/dist/src/core/typecheck.js +0 -1
- package/dist/src/core/wire-destroy.js +0 -1
- package/dist/src/core/wire-dom-fragment.js +0 -1
- package/dist/src/core/wire-init.js +0 -1
- package/dist/src/core/wire-subscript.js +0 -1
- package/dist/src/core/wire-targets.js +0 -1
- package/dist/src/core/wire-utils.js +0 -1
- package/dist/src/core/xpcshell-appdir.js +1 -4
- package/dist/src/errors/base.d.ts +29 -0
- package/dist/src/errors/base.js +35 -1
- package/dist/src/errors/build.js +0 -1
- package/dist/src/errors/codes.d.ts +6 -0
- package/dist/src/errors/codes.js +6 -1
- package/dist/src/errors/config.js +0 -1
- package/dist/src/errors/download.js +0 -1
- package/dist/src/errors/furnace.d.ts +11 -1
- package/dist/src/errors/furnace.js +6 -5
- package/dist/src/errors/git.js +0 -1
- package/dist/src/errors/patch.d.ts +17 -0
- package/dist/src/errors/patch.js +29 -1
- package/dist/src/errors/rebase.js +0 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.js +0 -1
- package/dist/src/types/cli.js +0 -1
- package/dist/src/types/commands/index.d.ts +1 -1
- package/dist/src/types/commands/index.js +0 -1
- package/dist/src/types/commands/options.d.ts +40 -9
- package/dist/src/types/commands/options.js +0 -1
- package/dist/src/types/commands/patches.d.ts +37 -0
- package/dist/src/types/commands/patches.js +0 -1
- package/dist/src/types/commands/project.d.ts +11 -2
- package/dist/src/types/commands/project.js +0 -1
- package/dist/src/types/config.d.ts +32 -0
- package/dist/src/types/config.js +0 -1
- package/dist/src/types/furnace.d.ts +23 -0
- package/dist/src/types/furnace.js +0 -1
- package/dist/src/types/index.js +0 -1
- package/dist/src/types/typecheck.js +0 -1
- package/dist/src/utils/elapsed.js +0 -1
- package/dist/src/utils/errors.js +0 -1
- package/dist/src/utils/fs.js +37 -5
- package/dist/src/utils/logger.d.ts +7 -0
- package/dist/src/utils/logger.js +85 -3
- package/dist/src/utils/options.d.ts +15 -0
- package/dist/src/utils/options.js +25 -1
- package/dist/src/utils/package-root.js +11 -4
- package/dist/src/utils/parse.js +0 -1
- package/dist/src/utils/paths.js +0 -1
- package/dist/src/utils/platform.js +0 -1
- package/dist/src/utils/process-group.d.ts +33 -0
- package/dist/src/utils/process-group.js +161 -0
- package/dist/src/utils/process.d.ts +48 -4
- package/dist/src/utils/process.js +258 -59
- package/dist/src/utils/regex.d.ts +13 -3
- package/dist/src/utils/regex.js +53 -4
- package/dist/src/utils/validation.d.ts +0 -12
- package/dist/src/utils/validation.js +13 -26
- package/package.json +9 -8
|
@@ -2,25 +2,22 @@
|
|
|
2
2
|
import { readdir } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
5
|
-
import { getFurnacePaths, loadFurnaceConfig,
|
|
5
|
+
import { getFurnacePaths, loadFurnaceConfig, writeFurnaceConfig, } from '../../core/furnace-config.js';
|
|
6
6
|
import { isComponentSourceFile, resolveFtlChromeSubPath, resolveFtlDir, resolveFtlLocaleJarMnPath, tagNameToClassName, } from '../../core/furnace-constants.js';
|
|
7
7
|
import { recordFurnaceRollbackFailure, runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
8
8
|
import { addCustomElementRegistration, addJarMnEntries, addLocaleFtlJarMnEntry, removeCustomElementRegistration, removeJarMnEntries, removeLocaleFtlJarMnEntry, } from '../../core/furnace-registration.js';
|
|
9
9
|
import { CUSTOM_ELEMENT_TAG_PATTERN, CUSTOM_ELEMENT_TAG_RULES, } from '../../core/furnace-registration-validate.js';
|
|
10
|
-
import { createRollbackJournal, restoreRollbackJournalOrThrow, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
10
|
+
import { createRollbackJournal, recordCreatedDir, restoreRollbackJournalOrThrow, snapshotDir, snapshotFile, } from '../../core/furnace-rollback.js';
|
|
11
11
|
import { getStoriesDir } from '../../core/furnace-stories.js';
|
|
12
12
|
import { InvalidArgumentError } from '../../errors/base.js';
|
|
13
13
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
14
14
|
import { toError } from '../../utils/errors.js';
|
|
15
15
|
import { copyFile, ensureDir, pathExists, readText, removeDir, removeFile, writeText, } from '../../utils/fs.js';
|
|
16
16
|
import { info, intro, note, outro, warn } from '../../utils/logger.js';
|
|
17
|
+
import { escapeRegex } from '../../utils/regex.js';
|
|
17
18
|
import { updateBrowserChromeTestContent } from './rename-browser-test.js';
|
|
18
|
-
import { renameComponentFileName, updateConfigForCustomRename, updateConfigForOverrideRename, } from './rename-helpers.js';
|
|
19
|
+
import { rekeyStateChecksums, renameComponentFileName, updateConfigForCustomRename, updateConfigForOverrideRename, } from './rename-helpers.js';
|
|
19
20
|
import { renameXpcshellTestFiles } from './rename-xpcshell.js';
|
|
20
|
-
/** Escapes regex metacharacters so a user-supplied name is literal inside a RegExp. */
|
|
21
|
-
function escapeRegex(input) {
|
|
22
|
-
return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
23
|
-
}
|
|
24
21
|
/**
|
|
25
22
|
* Derives the test file name for a component, matching the convention used by
|
|
26
23
|
* `furnace create --with-tests`.
|
|
@@ -58,6 +55,7 @@ async function renameTestFiles(engineDir, projectRoot, oldName, newName, journal
|
|
|
58
55
|
if (await pathExists(oldTestPath)) {
|
|
59
56
|
try {
|
|
60
57
|
await snapshotFile(journal, oldTestPath);
|
|
58
|
+
await snapshotFile(journal, newTestPath);
|
|
61
59
|
const content = await readText(oldTestPath);
|
|
62
60
|
await writeText(newTestPath, updateBrowserChromeTestContent(content, oldName, newName, binaryName));
|
|
63
61
|
await removeFile(oldTestPath);
|
|
@@ -144,6 +142,7 @@ async function renameMochikitTestFiles(engineDir, oldName, newName, journal) {
|
|
|
144
142
|
.replace(new RegExp(`Test the ${escapeRegex(oldName)} `, 'g'), `Test the ${newName} `)
|
|
145
143
|
.replace(new RegExp(`add_task\\(async function test_${escapeRegex(oldName.replace(/-/g, '_'))}_defined\\(`, 'g'), `add_task(async function test_${newName.replace(/-/g, '_')}_defined(`)
|
|
146
144
|
.replace(new RegExp(`"${escapeRegex(oldName)} custom element`, 'g'), `"${newName} custom element`);
|
|
145
|
+
await snapshotFile(journal, newTestPath);
|
|
147
146
|
await writeText(newTestPath, updatedContent);
|
|
148
147
|
await removeFile(oldTestPath);
|
|
149
148
|
info(`Renamed mochikit test: ${oldTestFileName} → ${newTestFileName}`);
|
|
@@ -209,7 +208,14 @@ async function performRenameMutations(args) {
|
|
|
209
208
|
}
|
|
210
209
|
await snapshotDir(journal, oldDir);
|
|
211
210
|
await snapshotFile(journal, args.furnaceConfigPath);
|
|
211
|
+
// Journal the state file BEFORE step 4 re-keys its checksums, plus
|
|
212
|
+
// the new dir and every new-name destination below (a snapshot of a
|
|
213
|
+
// missing path records {existed: false} → rollback DELETES it).
|
|
214
|
+
// Without these, a failed or SIGINT'd rename stranded the new-name
|
|
215
|
+
// scaffold and kept re-keyed state for a nonexistent component.
|
|
216
|
+
await snapshotFile(journal, getFurnacePaths(projectRoot).furnaceState);
|
|
212
217
|
// 1. Create new directory with renamed files and updated content
|
|
218
|
+
recordCreatedDir(journal, newDir);
|
|
213
219
|
await ensureDir(newDir);
|
|
214
220
|
const entries = await readdir(oldDir, { withFileTypes: true });
|
|
215
221
|
for (const entry of entries) {
|
|
@@ -227,6 +233,7 @@ async function performRenameMutations(args) {
|
|
|
227
233
|
const newFileName = renameComponentFileName(oldFileName, oldName, newName);
|
|
228
234
|
const oldPath = join(oldDir, oldFileName);
|
|
229
235
|
const newPath = join(newDir, newFileName);
|
|
236
|
+
await snapshotFile(journal, newPath);
|
|
230
237
|
if (isComponentSourceFile(oldFileName)) {
|
|
231
238
|
let content = await readText(oldPath);
|
|
232
239
|
// Use word-boundary-aware patterns so substrings in other
|
|
@@ -320,34 +327,6 @@ async function performRenameMutations(args) {
|
|
|
320
327
|
}
|
|
321
328
|
});
|
|
322
329
|
}
|
|
323
|
-
/**
|
|
324
|
-
* Re-keys checksum entries in furnace-state.json from the old component name
|
|
325
|
-
* to the new name so that `doctor` doesn't flag stale entries and the next
|
|
326
|
-
* `apply` can correctly detect whether the renamed component has changed.
|
|
327
|
-
*/
|
|
328
|
-
async function rekeyStateChecksums(projectRoot, componentType, oldName, newName) {
|
|
329
|
-
const oldPrefix = `${componentType}/${oldName}/`;
|
|
330
|
-
const newPrefix = `${componentType}/${newName}/`;
|
|
331
|
-
await updateFurnaceState(projectRoot, (state) => {
|
|
332
|
-
const result = { ...state };
|
|
333
|
-
for (const field of ['appliedChecksums', 'engineChecksums']) {
|
|
334
|
-
const checksums = state[field];
|
|
335
|
-
if (!checksums)
|
|
336
|
-
continue;
|
|
337
|
-
const updated = {};
|
|
338
|
-
for (const [key, value] of Object.entries(checksums)) {
|
|
339
|
-
if (key.startsWith(oldPrefix)) {
|
|
340
|
-
updated[newPrefix + key.slice(oldPrefix.length)] = value;
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
updated[key] = value;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
result[field] = updated;
|
|
347
|
-
}
|
|
348
|
-
return result;
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
330
|
async function updateEngineRegistrations(engineDir, oldName, newName, newDir, ftlDir, isLocalized, journal) {
|
|
352
331
|
const customElementsPath = join(engineDir, 'toolkit/content/customElements.js');
|
|
353
332
|
const jarMnPath = join(engineDir, 'toolkit/content/jar.mn');
|
|
@@ -372,6 +351,7 @@ async function updateEngineRegistrations(engineDir, oldName, newName, newDir, ft
|
|
|
372
351
|
const newFtlPath = join(ftlDirPath, `${newName}.ftl`);
|
|
373
352
|
if (await pathExists(oldFtlPath)) {
|
|
374
353
|
await snapshotFile(journal, oldFtlPath);
|
|
354
|
+
await snapshotFile(journal, newFtlPath);
|
|
375
355
|
const ftlContent = await readText(oldFtlPath);
|
|
376
356
|
await writeText(newFtlPath, ftlContent);
|
|
377
357
|
await removeFile(oldFtlPath);
|
|
@@ -463,4 +443,3 @@ export async function furnaceRenameCommand(projectRoot, oldName, newName) {
|
|
|
463
443
|
' 3. Run "fireforge furnace apply" to update the engine', newName);
|
|
464
444
|
outro('Rename complete');
|
|
465
445
|
}
|
|
466
|
-
//# sourceMappingURL=rename.js.map
|
|
@@ -199,4 +199,3 @@ export async function furnaceStatusCommand(projectRoot, name) {
|
|
|
199
199
|
info('Tip: run `fireforge furnace status <name>` for detailed component info, or `fireforge furnace --help` for all subcommands.');
|
|
200
200
|
outro('Status complete');
|
|
201
201
|
}
|
|
202
|
-
//# sourceMappingURL=status.js.map
|
|
@@ -1,15 +1,56 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
3
5
|
import { applyAllComponents } from '../../core/furnace-apply.js';
|
|
4
6
|
import { logApplyResult } from '../../core/furnace-apply-output.js';
|
|
5
|
-
import { furnaceConfigExists, loadFurnaceConfig } from '../../core/furnace-config.js';
|
|
7
|
+
import { furnaceConfigExists, getFurnacePaths, loadFurnaceConfig, } from '../../core/furnace-config.js';
|
|
6
8
|
import { reportJsconfigPathsSync } from '../../core/furnace-jsconfig.js';
|
|
7
9
|
import { runFurnaceMutation } from '../../core/furnace-operation.js';
|
|
10
|
+
import { countEntriesWithBlockingStepErrors } from '../../core/furnace-step-errors.js';
|
|
11
|
+
import { containsMergeConflictMarkers } from '../../core/furnace-validate-structure.js';
|
|
8
12
|
import { findOverrideBaseVersionDrift, formatOverrideBaseVersionDriftWarning, } from '../../core/furnace-version-drift.js';
|
|
9
13
|
import { FurnaceError } from '../../errors/furnace.js';
|
|
10
|
-
import { pathExists } from '../../utils/fs.js';
|
|
14
|
+
import { pathExists, readText } from '../../utils/fs.js';
|
|
11
15
|
import { info, intro, outro, spinner, warn } from '../../utils/logger.js';
|
|
12
16
|
import { furnaceRefreshCommand } from './refresh.js';
|
|
17
|
+
/**
|
|
18
|
+
* Scans every configured override/custom component workspace for files
|
|
19
|
+
* carrying unresolved merge conflict markers. Returns the component names
|
|
20
|
+
* (sorted, unique) that must be resolved before an apply may run.
|
|
21
|
+
*/
|
|
22
|
+
async function findComponentsWithConflictMarkers(furnacePaths, config) {
|
|
23
|
+
const conflicted = new Set();
|
|
24
|
+
const componentDirs = [
|
|
25
|
+
...Object.keys(config.overrides).map((name) => ({
|
|
26
|
+
name,
|
|
27
|
+
dir: join(furnacePaths.overridesDir, name),
|
|
28
|
+
})),
|
|
29
|
+
...Object.keys(config.custom).map((name) => ({
|
|
30
|
+
name,
|
|
31
|
+
dir: join(furnacePaths.customDir, name),
|
|
32
|
+
})),
|
|
33
|
+
];
|
|
34
|
+
for (const { name, dir } of componentDirs) {
|
|
35
|
+
if (!(await pathExists(dir)))
|
|
36
|
+
continue;
|
|
37
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
if (!entry.isFile())
|
|
40
|
+
continue;
|
|
41
|
+
if (!entry.name.endsWith('.mjs') &&
|
|
42
|
+
!entry.name.endsWith('.css') &&
|
|
43
|
+
!entry.name.endsWith('.ftl')) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (containsMergeConflictMarkers(await readText(join(dir, entry.name)))) {
|
|
47
|
+
conflicted.add(name);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return [...conflicted].sort();
|
|
53
|
+
}
|
|
13
54
|
/**
|
|
14
55
|
* Runs the furnace sync command: detects overrides with baseVersion drift,
|
|
15
56
|
* refreshes them (three-way merge), and re-applies all components.
|
|
@@ -57,6 +98,38 @@ export async function furnaceSyncCommand(projectRoot, options = {}) {
|
|
|
57
98
|
else {
|
|
58
99
|
info('All overrides are up-to-date with the current Firefox version.');
|
|
59
100
|
}
|
|
101
|
+
// Phase 2.5: post-refresh gates. Refresh deliberately leaves conflict
|
|
102
|
+
// markers in workspace files and does NOT bump baseVersion on conflict —
|
|
103
|
+
// so before this gate existed, sync would warn about conflicts and then
|
|
104
|
+
// copy the marker-laden files straight into the engine via Phase 3,
|
|
105
|
+
// producing a broken build from the one command whose whole purpose is a
|
|
106
|
+
// safe upgrade. Apply/deploy both enforce a drift gate; sync must not be
|
|
107
|
+
// the back door around it.
|
|
108
|
+
if (!options.dryRun) {
|
|
109
|
+
const refreshedConfig = await loadFurnaceConfig(projectRoot);
|
|
110
|
+
const furnacePaths = getFurnacePaths(projectRoot);
|
|
111
|
+
const conflicted = await findComponentsWithConflictMarkers(furnacePaths, refreshedConfig);
|
|
112
|
+
const remainingDrift = findOverrideBaseVersionDrift(refreshedConfig, forgeConfig.firefox.version);
|
|
113
|
+
if (conflicted.length > 0 || remainingDrift.length > 0) {
|
|
114
|
+
if (conflicted.length > 0) {
|
|
115
|
+
warn(`Unresolved merge conflicts in: ${conflicted.join(', ')}`);
|
|
116
|
+
}
|
|
117
|
+
for (const entry of remainingDrift) {
|
|
118
|
+
warn(formatOverrideBaseVersionDriftWarning(entry));
|
|
119
|
+
}
|
|
120
|
+
throw new FurnaceError('Sync stopped before applying: ' +
|
|
121
|
+
(conflicted.length > 0
|
|
122
|
+
? `${conflicted.length} component(s) contain unresolved merge conflict markers` +
|
|
123
|
+
(remainingDrift.length > 0 ? ' and ' : '')
|
|
124
|
+
: '') +
|
|
125
|
+
(remainingDrift.length > 0
|
|
126
|
+
? `${remainingDrift.length} override(s) still have baseVersion drift`
|
|
127
|
+
: '') +
|
|
128
|
+
'. Resolve the conflicts in the component workspace files, re-run ' +
|
|
129
|
+
'"fireforge furnace refresh <name>" to update baseVersion, then run ' +
|
|
130
|
+
'"fireforge furnace sync" again. Nothing was applied to the engine.');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
60
133
|
// Phase 3: Re-apply all components to the engine
|
|
61
134
|
if (!options.dryRun) {
|
|
62
135
|
info('\nApplying all components to engine...');
|
|
@@ -64,7 +137,7 @@ export async function furnaceSyncCommand(projectRoot, options = {}) {
|
|
|
64
137
|
const result = await runFurnaceMutation(projectRoot, 'apply-rollback', (ctx) => applyAllComponents(projectRoot, false, { operationContext: ctx }), { dryRun: false });
|
|
65
138
|
applySpinner.stop('Components applied');
|
|
66
139
|
logApplyResult(result, false);
|
|
67
|
-
const appliedWithStepErrorsCount = result.applied
|
|
140
|
+
const appliedWithStepErrorsCount = countEntriesWithBlockingStepErrors(result.applied);
|
|
68
141
|
const totalFailures = result.errors.length + appliedWithStepErrorsCount;
|
|
69
142
|
if (totalFailures > 0) {
|
|
70
143
|
throw new FurnaceError(`${totalFailures} component${totalFailures === 1 ? '' : 's'} failed to apply cleanly`);
|
|
@@ -76,4 +149,3 @@ export async function furnaceSyncCommand(projectRoot, options = {}) {
|
|
|
76
149
|
outro('Dry run complete');
|
|
77
150
|
}
|
|
78
151
|
}
|
|
79
|
-
//# sourceMappingURL=sync.js.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { confirm } from '@clack/prompts';
|
|
4
|
+
import { Command } from 'commander';
|
|
4
5
|
import { getProjectPaths, loadConfig, loadState, updateState } from '../core/config.js';
|
|
5
6
|
import { getHead } from '../core/git.js';
|
|
6
7
|
import { getDirtyFiles } from '../core/git-status.js';
|
|
7
|
-
import { applyPatchesWithContinue,
|
|
8
|
+
import { applyPatchesWithContinue, countPatches, createPatchedContentComputer, discoverPatches, extractAffectedFiles, matchesUntilFilename, PatchError, } from '../core/patch-apply.js';
|
|
8
9
|
import { checkVersionCompatibility, loadPatchesManifest, validatePatchesManifestConsistency, validatePatchIntegrity, } from '../core/patch-manifest.js';
|
|
9
10
|
import { getPatchSourceVersion } from '../core/patch-source-metadata.js';
|
|
10
11
|
import { GeneralError } from '../errors/base.js';
|
|
@@ -25,11 +26,17 @@ function isSafeIoFallback(error) {
|
|
|
25
26
|
const code = error?.code;
|
|
26
27
|
return typeof code === 'string' && SAFE_IO_FALLBACK_CODES.has(code);
|
|
27
28
|
}
|
|
29
|
+
/** Concurrency bound for per-file classification (each call spawns git). */
|
|
30
|
+
const UNMANAGED_CLASSIFY_CONCURRENCY = 8;
|
|
28
31
|
async function getUnmanagedDirtyFiles(engineDir, patchesDir, dirtyFiles) {
|
|
29
|
-
|
|
32
|
+
// One manifest+patch-discovery load for the whole batch (the per-call
|
|
33
|
+
// computePatchedContent re-read everything for every file), and bounded
|
|
34
|
+
// concurrency instead of an unbounded Promise.all over git spawns.
|
|
35
|
+
const computeExpected = await createPatchedContentComputer(patchesDir, engineDir);
|
|
36
|
+
const classifications = await mapWithConcurrency(dirtyFiles, UNMANAGED_CLASSIFY_CONCURRENCY, async (file) => {
|
|
30
37
|
try {
|
|
31
38
|
const [expected, exists] = await Promise.all([
|
|
32
|
-
|
|
39
|
+
computeExpected(file),
|
|
33
40
|
pathExists(join(engineDir, file)),
|
|
34
41
|
]);
|
|
35
42
|
const actual = exists ? await readText(join(engineDir, file)) : null;
|
|
@@ -51,9 +58,24 @@ async function getUnmanagedDirtyFiles(engineDir, patchesDir, dirtyFiles) {
|
|
|
51
58
|
verbose(`Treating ${file} as unmanaged because patched-content classification failed with IO error: ${toError(error).message}`);
|
|
52
59
|
return file;
|
|
53
60
|
}
|
|
54
|
-
})
|
|
61
|
+
});
|
|
55
62
|
return classifications.filter((file) => file !== null).sort();
|
|
56
63
|
}
|
|
64
|
+
/** Maps items with at most `limit` in-flight promises. Preserves order. */
|
|
65
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
66
|
+
const results = new Array(items.length);
|
|
67
|
+
let next = 0;
|
|
68
|
+
const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
69
|
+
for (;;) {
|
|
70
|
+
const index = next++;
|
|
71
|
+
if (index >= items.length)
|
|
72
|
+
return;
|
|
73
|
+
results[index] = await fn(items[index]);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
await Promise.all(workers);
|
|
77
|
+
return results;
|
|
78
|
+
}
|
|
57
79
|
function reportForcedOverwriteRisk(unmanagedDirtyFiles) {
|
|
58
80
|
warn(`--force will overwrite ${unmanagedDirtyFiles.length} unmanaged change${unmanagedDirtyFiles.length === 1 ? '' : 's'} in patch-touched file${unmanagedDirtyFiles.length === 1 ? '' : 's'}:`);
|
|
59
81
|
for (const file of unmanagedDirtyFiles) {
|
|
@@ -150,7 +172,7 @@ async function checkEngineDrift(engineDir, baseCommit, forceImport) {
|
|
|
150
172
|
const currentHead = await getHead(engineDir);
|
|
151
173
|
if (currentHead === baseCommit)
|
|
152
174
|
return true;
|
|
153
|
-
if (!process.stdin.isTTY) {
|
|
175
|
+
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
154
176
|
if (!forceImport) {
|
|
155
177
|
throw new GeneralError('Engine HEAD has drifted from base commit. Re-run with --force to bypass drift check.');
|
|
156
178
|
}
|
|
@@ -189,8 +211,13 @@ function buildUntilFilenameSet(patches, until) {
|
|
|
189
211
|
const set = new Set();
|
|
190
212
|
if (until === undefined)
|
|
191
213
|
return set;
|
|
192
|
-
|
|
193
|
-
|
|
214
|
+
// Resolve the identifier with the SAME matcher the apply loop uses
|
|
215
|
+
// (`matchesUntilFilename` accepts filenames, extension-less names, AND
|
|
216
|
+
// bare ordinals). The previous filename-only match meant
|
|
217
|
+
// `import --until 5` produced an EMPTY scope set — the UI previewed
|
|
218
|
+
// "0 patches", the integrity gates filtered every in-range issue away —
|
|
219
|
+
// and then the apply loop happily applied patches 1..5 anyway.
|
|
220
|
+
const target = patches.find((p) => matchesUntilFilename(p.filename, until));
|
|
194
221
|
if (!target)
|
|
195
222
|
return set;
|
|
196
223
|
for (const patch of patches) {
|
|
@@ -266,7 +293,7 @@ async function gateImportIntegrity(paths, untilFilenameSet, until, forceImport)
|
|
|
266
293
|
if (forceImport) {
|
|
267
294
|
warn('Continuing because --force was provided. Integrity issues were not resolved.\n');
|
|
268
295
|
}
|
|
269
|
-
else if (!process.stdin.isTTY) {
|
|
296
|
+
else if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
270
297
|
throw new GeneralError(`Refusing to import while ${integrityIssues.length} patch integrity issue(s) are unresolved. ` +
|
|
271
298
|
`Fix the issues reported above (see "fireforge doctor") or re-run with --force to continue anyway.`);
|
|
272
299
|
}
|
|
@@ -421,4 +448,3 @@ export function registerImport(program, { getProjectRoot, withErrorHandling }) {
|
|
|
421
448
|
await importCommand(getProjectRoot(), pickDefined(merged));
|
|
422
449
|
}));
|
|
423
450
|
}
|
|
424
|
-
//# sourceMappingURL=import.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { loadConfig } from '../core/config.js';
|
|
3
|
+
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
4
4
|
import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
5
5
|
import { buildPerPatchLintCacheKey, getCachedPerPatchLintIssues, getPerPatchLintCacheHeadSha, loadPerPatchLintCache, savePerPatchLintCache, setCachedPerPatchLintIssues, } from '../core/lint-cache.js';
|
|
6
6
|
import { buildPatchQueueContext, lintExportedPatch, lintPatchQueue, resolvePatchSizeTier, } from '../core/patch-lint.js';
|
|
@@ -215,13 +215,26 @@ function reportPerPatchOutcome(issues, linted, skipped, options) {
|
|
|
215
215
|
* than silently linting nothing.
|
|
216
216
|
*/
|
|
217
217
|
function selectPatchSubset(manifest, requested) {
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
218
|
+
const normalizedRequests = requested
|
|
219
|
+
.flatMap((entry) => entry.split(','))
|
|
220
|
+
.map((entry) => entry.trim())
|
|
221
|
+
.filter((entry) => entry.length > 0);
|
|
222
|
+
const patchAliases = (p) => {
|
|
223
|
+
const aliases = new Set([p.filename, p.filename.replace(/\.patch$/, ''), p.name]);
|
|
224
|
+
const match = /^(\d+)-([a-z]+)-(.+)\.patch$/.exec(p.filename);
|
|
225
|
+
if (match?.[2] && match[3]) {
|
|
226
|
+
aliases.add(`${match[2]}-${match[3]}`);
|
|
227
|
+
aliases.add(match[3]);
|
|
228
|
+
}
|
|
229
|
+
return aliases;
|
|
230
|
+
};
|
|
231
|
+
const matches = (p, name) => {
|
|
232
|
+
const stem = name.replace(/\.patch$/, '');
|
|
233
|
+
return (patchAliases(p).has(name) || patchAliases(p).has(stem) || patchAliases(p).has(`${stem}.patch`));
|
|
234
|
+
};
|
|
222
235
|
const selected = [];
|
|
223
236
|
const seen = new Set();
|
|
224
|
-
for (const name of
|
|
237
|
+
for (const name of normalizedRequests) {
|
|
225
238
|
const found = manifest.patches.filter((p) => matches(p, name));
|
|
226
239
|
if (found.length === 0) {
|
|
227
240
|
const available = manifest.patches.map((p) => p.filename).join(', ');
|
|
@@ -340,4 +353,3 @@ export async function lintPerPatch(projectRoot, paths, options = {}) {
|
|
|
340
353
|
}
|
|
341
354
|
reportPerPatchOutcome(issues, linted, skipped, options);
|
|
342
355
|
}
|
|
343
|
-
//# sourceMappingURL=lint-per-patch.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { stat } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { Command } from 'commander';
|
|
4
5
|
import { isBrandingManagedPath } from '../core/branding.js';
|
|
5
6
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
6
7
|
import { collectFurnaceManagedPrefixes } from '../core/furnace-config.js';
|
|
@@ -510,7 +511,7 @@ export function registerLint(program, { getProjectRoot, withErrorHandling }) {
|
|
|
510
511
|
.option('--since <git-rev>', 'Tag issues as [introduced] or [cumulative] based on whether the file changed since <git-rev> (e.g. HEAD, a branch, a SHA)')
|
|
511
512
|
.option('--only-introduced', 'Fail only on issues tagged [introduced] (requires --since). Cumulative errors still print but do not set a non-zero exit.')
|
|
512
513
|
.option('--per-patch', "Lint each patch in the queue as its own isolated diff. Rescopes patch-size rules so they fire against individual patches rather than the aggregate. Honours each patch's `lintIgnore` entries.")
|
|
513
|
-
.option('--patches <names...>', 'With --per-patch, lint only the named patches
|
|
514
|
+
.option('--patches <names...>', 'With --per-patch, lint only the named patches. Accepts repeated flags, comma lists, full filenames/stems, manifest names, category-prefixed slugs, or bare slugs.')
|
|
514
515
|
.option('--max-warnings <n>', 'Fail when lint reports more than <n> warning(s); use 0 for warning-clean release gates.')
|
|
515
516
|
.option('--no-cache', 'Bypass per-patch lint result cache reads and writes.')
|
|
516
517
|
.action(withErrorHandling(async (paths, options) => {
|
|
@@ -539,9 +540,19 @@ export function registerLint(program, { getProjectRoot, withErrorHandling }) {
|
|
|
539
540
|
}
|
|
540
541
|
await lintCommand(getProjectRoot(), paths, lintOptions);
|
|
541
542
|
}));
|
|
542
|
-
lint
|
|
543
|
+
const lintCache = lint
|
|
543
544
|
.command('cache')
|
|
544
545
|
.description('Manage the per-patch lint result cache')
|
|
546
|
+
// Commander routes `fireforge lint cache` here even when the operator
|
|
547
|
+
// meant to lint an engine directory literally named `cache`. A bare
|
|
548
|
+
// `lint cache` (no subcommand) used to silently do nothing — make the
|
|
549
|
+
// ambiguity explicit instead of doing the wrong operation quietly.
|
|
550
|
+
.action(withErrorHandling(() => {
|
|
551
|
+
info('Nothing to do: "lint cache" manages the lint result cache (try "lint cache clear"). ' +
|
|
552
|
+
'To lint a directory named cache/, disambiguate with a trailing slash: "fireforge lint cache/".');
|
|
553
|
+
return Promise.resolve();
|
|
554
|
+
}));
|
|
555
|
+
lintCache
|
|
545
556
|
.command('clear')
|
|
546
557
|
.description('Clear cached per-patch lint results')
|
|
547
558
|
.action(withErrorHandling(async () => {
|
|
@@ -551,4 +562,3 @@ export function registerLint(program, { getProjectRoot, withErrorHandling }) {
|
|
|
551
562
|
outro('Lint cache cleared');
|
|
552
563
|
}));
|
|
553
564
|
}
|
|
554
|
-
//# sourceMappingURL=lint.js.map
|
|
@@ -20,7 +20,7 @@ import { registerRun } from './run.js';
|
|
|
20
20
|
import { registerSetup } from './setup.js';
|
|
21
21
|
import { registerSource } from './source.js';
|
|
22
22
|
import { registerStatus } from './status.js';
|
|
23
|
-
import { registerTest } from './test.js';
|
|
23
|
+
import { registerTest } from './test-register.js';
|
|
24
24
|
import { registerToken } from './token.js';
|
|
25
25
|
import { registerTypecheck } from './typecheck.js';
|
|
26
26
|
import { registerVerify } from './verify.js';
|
|
@@ -60,4 +60,3 @@ export const COMMAND_MANIFEST = [
|
|
|
60
60
|
{ name: 'verify', group: 'diagnostics', register: registerVerify },
|
|
61
61
|
{ name: 'furnace', group: 'components', register: registerFurnace },
|
|
62
62
|
];
|
|
63
|
-
//# sourceMappingURL=manifest.js.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { Command } from 'commander';
|
|
1
3
|
import { validateBrandOverride } from '../core/brand-validation.js';
|
|
2
4
|
import { prepareBuildEnvironment } from '../core/build-prepare.js';
|
|
3
5
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
@@ -88,4 +90,3 @@ export function registerPackage(program, { getProjectRoot, withErrorHandling })
|
|
|
88
90
|
await packageCommand(getProjectRoot(), pickDefined(options));
|
|
89
91
|
}));
|
|
90
92
|
}
|
|
91
|
-
//# sourceMappingURL=package.js.map
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* compaction is range-aware (each category range compacts independently,
|
|
10
10
|
* reserved ranges and out-of-range strays are left untouched).
|
|
11
11
|
*/
|
|
12
|
+
import { Command } from 'commander';
|
|
12
13
|
import { loadConfig } from '../../core/config.js';
|
|
13
14
|
import { appendHistory, confirmDestructive } from '../../core/destructive.js';
|
|
14
15
|
import { withPatchDirectoryLock } from '../../core/patch-lock.js';
|
|
@@ -206,4 +207,3 @@ export function registerPatchCompact(parent, context) {
|
|
|
206
207
|
await patchCompactCommand(getProjectRoot(), pickDefined(options));
|
|
207
208
|
}));
|
|
208
209
|
}
|
|
209
|
-
//# sourceMappingURL=compact.js.map
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* `--dry-run`, and appends to `patches/.fireforge-history.jsonl` on success.
|
|
9
9
|
*/
|
|
10
10
|
import { basename } from 'node:path';
|
|
11
|
+
import { Command } from 'commander';
|
|
11
12
|
import { appendHistory, confirmDestructive } from '../../core/destructive.js';
|
|
12
13
|
import { buildPatchQueueContext, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, isForwardImportableFile, } from '../../core/patch-lint.js';
|
|
13
14
|
import { withPatchDirectoryLock } from '../../core/patch-lock.js';
|
|
@@ -202,4 +203,3 @@ export function registerPatchDelete(parent, context) {
|
|
|
202
203
|
await patchDeleteCommand(getProjectRoot(), name, pickDefined(options));
|
|
203
204
|
}));
|
|
204
205
|
}
|
|
205
|
-
//# sourceMappingURL=delete.js.map
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Queue-level verbs like `lint`, `export`, `verify`, and `status` stay
|
|
8
8
|
* flat.
|
|
9
9
|
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
10
11
|
import { registerPatchCompact } from './compact.js';
|
|
11
12
|
import { registerPatchDelete } from './delete.js';
|
|
12
13
|
import { registerPatchLintIgnore } from './lint-ignore.js';
|
|
@@ -45,4 +46,3 @@ export function registerPatch(program, context) {
|
|
|
45
46
|
registerPatchStagedDependency(patch, context);
|
|
46
47
|
registerPatchTier(patch, context);
|
|
47
48
|
}
|
|
48
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
* write — important when an operator scripts repeated invocations or
|
|
20
20
|
* runs `--add` and `--remove` back-to-back.
|
|
21
21
|
*/
|
|
22
|
-
import {
|
|
22
|
+
import { Command } from 'commander';
|
|
23
|
+
import { appendHistory, confirmDestructive } from '../../core/destructive.js';
|
|
23
24
|
import { mutatePatchMetadata } from '../../core/patch-export.js';
|
|
24
25
|
import { GeneralError, InvalidArgumentError } from '../../errors/base.js';
|
|
25
26
|
import { toError } from '../../utils/errors.js';
|
|
@@ -107,13 +108,28 @@ export async function patchLintIgnoreCommand(projectRoot, identifier, options =
|
|
|
107
108
|
const values = mode === 'add' ? (options.add ?? []) : mode === 'remove' ? (options.remove ?? []) : [];
|
|
108
109
|
const { paths, manifest } = await requirePatchQueue(projectRoot);
|
|
109
110
|
const target = requirePatchTarget(identifier, manifest.patches);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
// Destructive-operation contract (docs/lifecycle-invariants.md): manifest
|
|
112
|
+
// metadata mutations get summary + dry-run + confirmation/--yes + history
|
|
113
|
+
// uniformly. This command used to accept --yes without ever prompting, so
|
|
114
|
+
// the flag only appeared in the history record — and suppressing lint
|
|
115
|
+
// findings is precisely the mutation an operator should consciously
|
|
116
|
+
// approve.
|
|
117
|
+
const projectedSummary = describeChange(target.lintIgnore ?? [], applyMode(target.lintIgnore ?? [], mode, values) ?? [], mode, values);
|
|
118
|
+
const decision = await confirmDestructive({
|
|
119
|
+
operation: 'patch-lint-ignore',
|
|
120
|
+
title: `Patch lint-ignore: ${target.filename}`,
|
|
121
|
+
summary: [`${target.filename}: ${projectedSummary}`],
|
|
122
|
+
yes: options.yes === true,
|
|
123
|
+
dryRun: isDryRun,
|
|
124
|
+
});
|
|
125
|
+
if (decision === 'dry-run') {
|
|
114
126
|
outro('Dry run complete — no changes made');
|
|
115
127
|
return;
|
|
116
128
|
}
|
|
129
|
+
if (decision === 'cancelled') {
|
|
130
|
+
outro('Cancelled — no changes made');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
117
133
|
const result = await mutatePatchMetadata(paths.patches, target.filename, (existing) => {
|
|
118
134
|
const next = applyMode(existing.lintIgnore ?? [], mode, values);
|
|
119
135
|
// Either set the new list when non-empty or unset the field
|
|
@@ -186,4 +202,3 @@ export function registerPatchLintIgnore(parent, context) {
|
|
|
186
202
|
await patchLintIgnoreCommand(getProjectRoot(), name, normalized);
|
|
187
203
|
}));
|
|
188
204
|
}
|
|
189
|
-
//# sourceMappingURL=lint-ignore.js.map
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* re-export choreography needed to move file ownership between two patches.
|
|
5
5
|
*/
|
|
6
6
|
import { relative } from 'node:path';
|
|
7
|
+
import { Command } from 'commander';
|
|
7
8
|
import { getProjectPaths } from '../../core/config.js';
|
|
8
9
|
import { formatPatchNotFoundError } from '../../core/patch-identifier-suggest.js';
|
|
9
10
|
import { loadPatchesManifest, resolvePatchIdentifier } from '../../core/patch-manifest.js';
|
|
@@ -136,4 +137,3 @@ export function registerPatchMoveFiles(parent, context) {
|
|
|
136
137
|
await patchMoveFilesCommand(getProjectRoot(), from, to, options);
|
|
137
138
|
}));
|
|
138
139
|
}
|
|
139
|
-
//# sourceMappingURL=move-files.js.map
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { rename as fsRename } from 'node:fs/promises';
|
|
20
20
|
import { join } from 'node:path';
|
|
21
|
+
import { Command } from 'commander';
|
|
21
22
|
import { loadConfig } from '../../core/config.js';
|
|
22
23
|
import { appendHistory, confirmDestructive } from '../../core/destructive.js';
|
|
23
|
-
import {
|
|
24
|
+
import { patchNameSlug } from '../../core/patch-export.js';
|
|
24
25
|
import { withPatchDirectoryLock } from '../../core/patch-lock.js';
|
|
25
26
|
import { loadPatchesManifest, rewriteStagedDependencyOwners, savePatchesManifest, } from '../../core/patch-manifest.js';
|
|
26
27
|
import { buildProjectedManifest, enforcePatchPolicy } from '../../core/patch-policy.js';
|
|
@@ -163,7 +164,7 @@ export async function patchRenameCommand(projectRoot, identifier, options = {})
|
|
|
163
164
|
if (!split) {
|
|
164
165
|
throw new GeneralError(`Cannot rename ${target.filename}: filename does not match the expected {ordinal}-{category}-{slug}.patch convention. Re-export the patch instead.`);
|
|
165
166
|
}
|
|
166
|
-
const newSlug =
|
|
167
|
+
const newSlug = patchNameSlug(options.to, split.category);
|
|
167
168
|
if (newSlug === '') {
|
|
168
169
|
throw new InvalidArgumentError('--to must contain at least one alphanumeric character after sanitisation.', 'patch rename');
|
|
169
170
|
}
|
|
@@ -258,7 +259,7 @@ export function registerPatchRename(parent, context) {
|
|
|
258
259
|
parent
|
|
259
260
|
.command('rename <name>')
|
|
260
261
|
.description('Rename a patch: filename + manifest name (and optional description) update without rewriting the .patch body.')
|
|
261
|
-
.requiredOption('--to <new-name>', 'New human-readable name (
|
|
262
|
+
.requiredOption('--to <new-name>', 'New human-readable name, category-prefixed slug, or full filename stem (normalised into the filename slug)')
|
|
262
263
|
.option('--description <text>', 'Replacement description (omit to leave description unchanged)')
|
|
263
264
|
.option('--dry-run', 'Show what would change without writing')
|
|
264
265
|
.option('-y, --yes', 'Skip confirmation prompt (required for non-TTY)')
|
|
@@ -267,4 +268,3 @@ export function registerPatchRename(parent, context) {
|
|
|
267
268
|
await patchRenameCommand(getProjectRoot(), name, pickDefined(options));
|
|
268
269
|
}));
|
|
269
270
|
}
|
|
270
|
-
//# sourceMappingURL=rename.js.map
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* `lintPatchQueue` so reorders that would introduce a forward-import fail
|
|
9
9
|
* before any bytes move.
|
|
10
10
|
*/
|
|
11
|
-
import { Option } from 'commander';
|
|
11
|
+
import { Command, Option } from 'commander';
|
|
12
12
|
import { loadConfig } from '../../core/config.js';
|
|
13
13
|
import { appendHistory, confirmDestructive, } from '../../core/destructive.js';
|
|
14
14
|
import { buildPatchQueueContext, lintPatchQueue, } from '../../core/patch-lint.js';
|
|
@@ -18,7 +18,7 @@ import { applyRenameMapToManifest, enforcePatchPolicy } from '../../core/patch-p
|
|
|
18
18
|
import { GeneralError, InvalidArgumentError } from '../../errors/base.js';
|
|
19
19
|
import { toError } from '../../utils/errors.js';
|
|
20
20
|
import { info, intro, outro, warn } from '../../utils/logger.js';
|
|
21
|
-
import { pickDefined } from '../../utils/options.js';
|
|
21
|
+
import { commanderArgParser, pickDefined } from '../../utils/options.js';
|
|
22
22
|
import { parsePositiveIntegerFlag } from '../../utils/validation.js';
|
|
23
23
|
import { requirePatchQueue, requirePatchTarget } from './patch-context.js';
|
|
24
24
|
/** Zero-pads an ordinal number to the given width. */
|
|
@@ -372,7 +372,7 @@ export function registerPatchReorder(parent, context) {
|
|
|
372
372
|
parent
|
|
373
373
|
.command('reorder <name>')
|
|
374
374
|
.description('Move a patch to a different position in the queue (destructive)')
|
|
375
|
-
.addOption(new Option('--to <order>', 'Destination ordinal').argParser((v) => parsePositiveIntegerFlag('--to', v)))
|
|
375
|
+
.addOption(new Option('--to <order>', 'Destination ordinal').argParser(commanderArgParser((v) => parsePositiveIntegerFlag('--to', v))))
|
|
376
376
|
.option('--before <anchor>', 'Place the patch immediately before <anchor>')
|
|
377
377
|
.option('--after <anchor>', 'Place the patch immediately after <anchor>')
|
|
378
378
|
.option('--dry-run', 'Show what would happen without writing')
|
|
@@ -382,4 +382,3 @@ export function registerPatchReorder(parent, context) {
|
|
|
382
382
|
await patchReorderCommand(getProjectRoot(), name, pickDefined(options));
|
|
383
383
|
}));
|
|
384
384
|
}
|
|
385
|
-
//# sourceMappingURL=reorder.js.map
|