@hominis/fireforge 0.34.2 → 0.36.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 +48 -0
- package/README.md +43 -5
- package/dist/bin/fireforge.d.ts +4 -0
- package/dist/bin/fireforge.js +25 -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 +17 -3
- package/dist/src/commands/config.js +30 -10
- package/dist/src/commands/discard.js +24 -5
- 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-working-tree.js +0 -1
- package/dist/src/commands/doctor.js +4 -1
- package/dist/src/commands/download.js +51 -15
- 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 +15 -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.js +1 -1
- 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 +1 -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 +6 -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 +18 -6
- 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 +18 -2
- 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 +95 -56
- 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.js +0 -1
- package/dist/src/core/build-baseline.js +0 -1
- package/dist/src/core/build-prepare.js +21 -7
- 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 +67 -8
- package/dist/src/core/firefox-download.js +0 -1
- package/dist/src/core/firefox-extract.d.ts +21 -1
- package/dist/src/core/firefox-extract.js +178 -9
- 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 +0 -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-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 +0 -1
- 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 +11 -2
- 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 +65 -8
- package/dist/src/core/license-headers.d.ts +16 -0
- package/dist/src/core/license-headers.js +19 -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 +27 -1
- 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.js +0 -1
- 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 +152 -39
- 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 +0 -1
- 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 +48 -24
- 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 +16 -0
- package/dist/src/core/patch-manifest-io.js +37 -12
- package/dist/src/core/patch-manifest-query.d.ts +6 -0
- package/dist/src/core/patch-manifest-query.js +27 -12
- package/dist/src/core/patch-manifest-resolve.js +0 -1
- package/dist/src/core/patch-manifest-validate.js +0 -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 +64 -7
- package/dist/src/core/test-harness-crash.js +196 -15
- package/dist/src/core/test-harness-output.js +0 -1
- package/dist/src/core/test-path-scope.d.ts +62 -0
- package/dist/src/core/test-path-scope.js +148 -0
- package/dist/src/core/test-stale-check.js +0 -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 +85 -0
- package/dist/src/core/toolchain-preflight.js +256 -0
- package/dist/src/core/typecheck-shim.d.ts +4 -1
- package/dist/src/core/typecheck-shim.js +61 -18
- 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 +2 -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.js +0 -1
- package/dist/src/types/commands/options.d.ts +20 -5
- package/dist/src/types/commands/options.js +0 -1
- package/dist/src/types/commands/patches.d.ts +8 -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 +10 -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.d.ts +33 -4
- package/dist/src/utils/process.js +183 -28
- 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 +8 -7
|
@@ -78,4 +78,3 @@ export async function withDryRunReExportLock(fireforgeDir, isDryRun, operation)
|
|
|
78
78
|
onStaleLockMessage: (ageMs) => `Removing stale FireForge re-export dry-run lock (age: ${Math.round(ageMs / 1000)}s). A previous dry-run process may have crashed.`,
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
|
-
//# sourceMappingURL=re-export-bulk-scan.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { getProjectPaths } from '../core/config.js';
|
|
3
4
|
import { appendHistory, confirmDestructive } from '../core/destructive.js';
|
|
4
5
|
import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
5
6
|
import { computeProjectedLintRegressions } from '../core/lint-projection.js';
|
|
@@ -260,4 +261,3 @@ export async function reExportFilesInPlace(paths, selectedPatches, options, conf
|
|
|
260
261
|
success(`Re-exported ${target.filename}`);
|
|
261
262
|
outro('Re-export complete');
|
|
262
263
|
}
|
|
263
|
-
//# sourceMappingURL=re-export-files.js.map
|
|
@@ -83,4 +83,3 @@ export function validateReExportOptionCombinations(patches, options) {
|
|
|
83
83
|
throw new InvalidArgumentError('--tier and --lint-ignore require explicit patch identifiers and cannot be combined with --all (different patches typically need different metadata).', '--all');
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
|
-
//# sourceMappingURL=re-export-options.js.map
|
|
@@ -144,4 +144,3 @@ export function assertScanFileAdditionsHaveDiffHunks(args) {
|
|
|
144
144
|
return;
|
|
145
145
|
throw new InvalidArgumentError(`Refusing to re-export ${patchFilename} with --scan-file because ${noDiffScanFiles.length} explicit added path${noDiffScanFiles.length === 1 ? '' : 's'} produced no diff hunks (${noDiffScanFiles.join(', ')}). Remove unchanged paths or modify them before retrying.`, '--scan-file');
|
|
146
146
|
}
|
|
147
|
-
//# sourceMappingURL=re-export-scan.js.map
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/* eslint-disable max-lines -- Re-export is at the guardrail; splitting register plumbing is unrelated to this fix. */
|
|
2
3
|
import { dirname, join } from 'node:path';
|
|
3
4
|
import { multiselect } from '@clack/prompts';
|
|
4
|
-
import { Option } from 'commander';
|
|
5
|
+
import { Command, Option } from 'commander';
|
|
5
6
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
7
|
+
import { withEngineSessionLock } from '../core/engine-session-lock.js';
|
|
6
8
|
import { isGitRepository } from '../core/git.js';
|
|
7
9
|
import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
8
10
|
import { getModifiedFilesInDir, getUntrackedFilesInDir } from '../core/git-status.js';
|
|
@@ -421,13 +423,13 @@ export function registerReExport(program, { getProjectRoot, withErrorHandling })
|
|
|
421
423
|
.option('--lint-ignore <check-id>', 'Append a lint check ID to the patch\'s PatchMetadata.lintIgnore (union, de-duped, repeatable). Mutually exclusive with --all. Use "fireforge patch lint-ignore" for --remove / --clear.', (value, prev) => [...prev, value], [])
|
|
422
424
|
.action(withErrorHandling(async (patches, options) => {
|
|
423
425
|
const { tier, lintIgnore, scanFile, scanFiles, ...rest } = options;
|
|
424
|
-
|
|
426
|
+
const projectRoot = getProjectRoot();
|
|
427
|
+
await withEngineSessionLock(projectRoot, 're-export', () => reExportCommand(projectRoot, patches, {
|
|
425
428
|
...pickDefined(rest),
|
|
426
429
|
...(scanFile !== undefined && scanFile.length > 0 ? { scanFiles: scanFile } : {}),
|
|
427
430
|
...(scanFiles !== undefined ? { scanFilesManifest: scanFiles } : {}),
|
|
428
431
|
...(tier !== undefined ? { tier: tier } : {}),
|
|
429
432
|
...(lintIgnore !== undefined && lintIgnore.length > 0 ? { lintIgnore } : {}),
|
|
430
|
-
});
|
|
433
|
+
}));
|
|
431
434
|
}));
|
|
432
435
|
}
|
|
433
|
-
//# sourceMappingURL=re-export.js.map
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
* Rebase abort flow.
|
|
4
4
|
*/
|
|
5
5
|
import { getProjectPaths, updateState } from '../../core/config.js';
|
|
6
|
-
import {
|
|
6
|
+
import { clearAppliedFurnaceState } from '../../core/furnace-config.js';
|
|
7
7
|
import { resetChanges } from '../../core/git.js';
|
|
8
8
|
import { clearRebaseSession, loadRebaseSession } from '../../core/rebase-session.js';
|
|
9
9
|
import { NoRebaseSessionError } from '../../errors/rebase.js';
|
|
10
|
-
import { pathExists } from '../../utils/fs.js';
|
|
11
10
|
import { intro, outro, spinner, success } from '../../utils/logger.js';
|
|
12
11
|
import { confirmDirtyEngineReset } from './confirm.js';
|
|
13
12
|
/**
|
|
@@ -47,12 +46,7 @@ export async function handleAbort(projectRoot, yes) {
|
|
|
47
46
|
// misleading now that reset already succeeded). The rebase session is
|
|
48
47
|
// still kept on disk so the user can retry the abort and let it
|
|
49
48
|
// idempotently re-clear furnace state.
|
|
50
|
-
|
|
51
|
-
if (await pathExists(furnacePaths.furnaceState)) {
|
|
52
|
-
await updateFurnaceState(projectRoot, (current) => ({
|
|
53
|
-
...(current.pendingRepair ? { pendingRepair: current.pendingRepair } : {}),
|
|
54
|
-
}));
|
|
55
|
-
}
|
|
49
|
+
await clearAppliedFurnaceState(projectRoot);
|
|
56
50
|
// Step 3: clear pending resolution transactionally.
|
|
57
51
|
await updateState(projectRoot, (current) => {
|
|
58
52
|
if (!current.pendingResolution)
|
|
@@ -67,4 +61,3 @@ export async function handleAbort(projectRoot, yes) {
|
|
|
67
61
|
success('Rebase aborted and session cleared.');
|
|
68
62
|
outro('Rebase aborted');
|
|
69
63
|
}
|
|
70
|
-
//# sourceMappingURL=abort.js.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Orchestrates the full patch-rebase workflow:
|
|
5
5
|
* 1. Reset engine to baseline
|
|
6
|
-
* 2. Apply each patch with escalating
|
|
6
|
+
* 2. Apply each patch with escalating context reduction (git apply -C<n>)
|
|
7
7
|
* 3. Pause on failures for manual resolution
|
|
8
8
|
* 4. Re-export successfully applied patches with the new version stamp
|
|
9
9
|
*
|
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Orchestrates the full patch-rebase workflow:
|
|
6
6
|
* 1. Reset engine to baseline
|
|
7
|
-
* 2. Apply each patch with escalating
|
|
7
|
+
* 2. Apply each patch with escalating context reduction (git apply -C<n>)
|
|
8
8
|
* 3. Pause on failures for manual resolution
|
|
9
9
|
* 4. Re-export successfully applied patches with the new version stamp
|
|
10
10
|
*
|
|
11
11
|
* Supports `--continue` (resume after manual fix) and `--abort` (cancel).
|
|
12
12
|
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
13
14
|
import { getProjectPaths, loadConfig } from '../../core/config.js';
|
|
14
|
-
import {
|
|
15
|
+
import { clearAppliedFurnaceState } from '../../core/furnace-config.js';
|
|
15
16
|
import { getHead, isGitRepository, isMissingHeadError, resetChanges } from '../../core/git.js';
|
|
16
17
|
import { discoverPatches } from '../../core/patch-files.js';
|
|
17
18
|
import { loadPatchesManifest } from '../../core/patch-manifest.js';
|
|
@@ -21,7 +22,8 @@ import { GeneralError } from '../../errors/base.js';
|
|
|
21
22
|
import { RebaseSessionExistsError } from '../../errors/rebase.js';
|
|
22
23
|
import { pathExists } from '../../utils/fs.js';
|
|
23
24
|
import { info, intro, outro, spinner } from '../../utils/logger.js';
|
|
24
|
-
import { pickDefined } from '../../utils/options.js';
|
|
25
|
+
import { commanderArgParser, pickDefined } from '../../utils/options.js';
|
|
26
|
+
import { parsePositiveIntegerFlag } from '../../utils/validation.js';
|
|
25
27
|
import { handleAbort } from './abort.js';
|
|
26
28
|
import { confirmDirtyEngineReset } from './confirm.js';
|
|
27
29
|
import { handleContinue } from './continue.js';
|
|
@@ -78,9 +80,9 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
78
80
|
}
|
|
79
81
|
info(`Rebasing patches: ${fromVersion} → ${currentVersion}`);
|
|
80
82
|
info(`Found ${manifest.patches.length} patch(es)`);
|
|
81
|
-
info(`Max fuzz
|
|
83
|
+
info(`Max context-reduction steps (fuzz-like): ${maxFuzz}`);
|
|
82
84
|
if (isDryRun) {
|
|
83
|
-
info('[dry-run] Would reset engine, apply patches with
|
|
85
|
+
info('[dry-run] Would reset engine, apply patches with context reduction, and re-export.');
|
|
84
86
|
outro('Dry run complete');
|
|
85
87
|
return;
|
|
86
88
|
}
|
|
@@ -102,13 +104,7 @@ async function handleFreshStart(projectRoot, options) {
|
|
|
102
104
|
await resetChanges(paths.engine);
|
|
103
105
|
resetSpinner.stop('Engine reset to baseline');
|
|
104
106
|
// Clear Furnace state — the engine no longer contains deployed components.
|
|
105
|
-
|
|
106
|
-
const furnacePaths = getFurnacePaths(projectRoot);
|
|
107
|
-
if (await pathExists(furnacePaths.furnaceState)) {
|
|
108
|
-
await updateFurnaceState(projectRoot, (current) => ({
|
|
109
|
-
...(current.pendingRepair ? { pendingRepair: current.pendingRepair } : {}),
|
|
110
|
-
}));
|
|
111
|
-
}
|
|
107
|
+
await clearAppliedFurnaceState(projectRoot);
|
|
112
108
|
// Create rebase session
|
|
113
109
|
const allPatches = await discoverPatches(paths.patches);
|
|
114
110
|
const session = {
|
|
@@ -147,14 +143,13 @@ export async function rebaseCommand(projectRoot, options = {}) {
|
|
|
147
143
|
export function registerRebase(program, { getProjectRoot, withErrorHandling }) {
|
|
148
144
|
program
|
|
149
145
|
.command('rebase')
|
|
150
|
-
.description('Semi-automated Firefox source version upgrade — apply patches with
|
|
146
|
+
.description('Semi-automated Firefox source version upgrade — apply patches with drift tolerance and re-export')
|
|
151
147
|
.option('--continue', 'Resume after manually resolving a failed patch')
|
|
152
148
|
.option('--abort', 'Cancel the rebase and restore engine to pre-rebase state')
|
|
153
149
|
.option('--dry-run', 'Show what would happen without modifying anything')
|
|
154
|
-
.option('--max-fuzz <n>', 'Maximum
|
|
150
|
+
.option('--max-fuzz <n>', 'Maximum context-reduction steps for git apply -C<n> (fuzz-like drift tolerance; default: 3)', commanderArgParser((v) => parsePositiveIntegerFlag('--max-fuzz', v)))
|
|
155
151
|
.option('-y, --yes', 'Skip dirty-tree confirmation prompt')
|
|
156
152
|
.action(withErrorHandling(async (options) => {
|
|
157
153
|
await rebaseCommand(getProjectRoot(), pickDefined(options));
|
|
158
154
|
}));
|
|
159
155
|
}
|
|
160
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -76,7 +76,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz) {
|
|
|
76
76
|
success(` ${entry.filename} — applied cleanly`);
|
|
77
77
|
}
|
|
78
78
|
else {
|
|
79
|
-
warn(` ${entry.filename} — applied with
|
|
79
|
+
warn(` ${entry.filename} — applied with context reduction (step ${result.fuzzFactor})`);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
else {
|
|
@@ -129,7 +129,7 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz) {
|
|
|
129
129
|
// patch was tested against if we proceeded to stamp. Refuse to claim
|
|
130
130
|
// success and leave the session in place so the user can recover via
|
|
131
131
|
// `fireforge rebase --continue` after fixing the underlying cause.
|
|
132
|
-
const reExportFailures = await reExportAppliedPatches(session, paths);
|
|
132
|
+
const { failures: reExportFailures, overlapSkipped } = await reExportAppliedPatches(session, paths);
|
|
133
133
|
if (reExportFailures.length > 0) {
|
|
134
134
|
for (const f of reExportFailures) {
|
|
135
135
|
error(` ${f.filename}: ${f.error}`);
|
|
@@ -138,10 +138,20 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz) {
|
|
|
138
138
|
`Versions were not stamped and the rebase session has been kept so you can retry. ` +
|
|
139
139
|
`Fix the underlying cause shown above, then re-run "fireforge rebase --continue".`);
|
|
140
140
|
}
|
|
141
|
-
|
|
141
|
+
if (overlapSkipped.length > 0) {
|
|
142
|
+
warn(`${overlapSkipped.length} patch(es) share files with other patches and were NOT ` +
|
|
143
|
+
`re-exported or version-stamped: ${overlapSkipped.join(', ')}. Their .patch files ` +
|
|
144
|
+
`still describe the pre-rebase source. Re-export them manually (e.g. ` +
|
|
145
|
+
`"fireforge re-export") and verify the overlapping hunks before the next import.`);
|
|
146
|
+
}
|
|
147
|
+
// Stamp versions — only for patches whose .patch file now actually
|
|
148
|
+
// reflects the new source (overlap-skipped ones keep their old stamp so
|
|
149
|
+
// the queue does not lie about what each patch was tested against).
|
|
150
|
+
const overlapSkippedSet = new Set(overlapSkipped);
|
|
142
151
|
const appliedFilenames = session.patches
|
|
143
152
|
.filter((p) => p.status === 'applied-clean' || p.status === 'applied-fuzz' || p.status === 'resolved')
|
|
144
|
-
.map((p) => p.filename)
|
|
153
|
+
.map((p) => p.filename)
|
|
154
|
+
.filter((filename) => !overlapSkippedSet.has(filename));
|
|
145
155
|
if (appliedFilenames.length > 0) {
|
|
146
156
|
await stampPatchVersions(paths.patches, appliedFilenames, session.toVersion, session.toProduct);
|
|
147
157
|
}
|
|
@@ -181,9 +191,24 @@ export async function runPatchLoop(projectRoot, session, paths, maxFuzz) {
|
|
|
181
191
|
}
|
|
182
192
|
async function reExportAppliedPatches(session, paths) {
|
|
183
193
|
const failures = [];
|
|
194
|
+
const overlapSkipped = [];
|
|
184
195
|
const manifest = await loadPatchesManifest(paths.patches);
|
|
185
196
|
if (!manifest)
|
|
186
|
-
return failures;
|
|
197
|
+
return { failures, overlapSkipped };
|
|
198
|
+
// Re-export writes `getDiffForFilesAgainstHead(files)` — the CUMULATIVE
|
|
199
|
+
// diff of those files. For a file claimed by two patches (a supported
|
|
200
|
+
// `--allow-overlap` queue), that diff contains BOTH patches' hunks, so
|
|
201
|
+
// rewriting each patch with it would duplicate the shared file's hunks
|
|
202
|
+
// into every owner: the very next import then fails or silently
|
|
203
|
+
// double-materialises. Refuse to auto-re-export any patch whose files
|
|
204
|
+
// overlap another patch; the operator re-exports those manually where
|
|
205
|
+
// per-patch attribution is possible.
|
|
206
|
+
const fileOwners = new Map();
|
|
207
|
+
for (const patch of manifest.patches) {
|
|
208
|
+
for (const file of patch.filesAffected) {
|
|
209
|
+
fileOwners.set(file, (fileOwners.get(file) ?? 0) + 1);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
187
212
|
const s = spinner('Re-exporting patches...');
|
|
188
213
|
const reExportable = session.patches.filter((entry) => entry.status === 'applied-clean' || entry.status === 'applied-fuzz');
|
|
189
214
|
const startedAt = Date.now();
|
|
@@ -191,6 +216,13 @@ async function reExportAppliedPatches(session, paths) {
|
|
|
191
216
|
const meta = manifest.patches.find((p) => p.filename === entry.filename);
|
|
192
217
|
if (!meta)
|
|
193
218
|
continue;
|
|
219
|
+
const sharedFiles = meta.filesAffected.filter((f) => (fileOwners.get(f) ?? 0) > 1);
|
|
220
|
+
if (sharedFiles.length > 0) {
|
|
221
|
+
overlapSkipped.push(entry.filename);
|
|
222
|
+
warn(`Skipping re-export of ${entry.filename}: file(s) shared with other patches ` +
|
|
223
|
+
`(${sharedFiles.join(', ')}). Re-export it manually once the overlap is resolved.`);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
194
226
|
const existingFiles = [];
|
|
195
227
|
for (const f of meta.filesAffected) {
|
|
196
228
|
if (await pathExists(join(paths.engine, f))) {
|
|
@@ -224,6 +256,5 @@ async function reExportAppliedPatches(session, paths) {
|
|
|
224
256
|
else {
|
|
225
257
|
s.stop('Patches re-exported');
|
|
226
258
|
}
|
|
227
|
-
return failures;
|
|
259
|
+
return { failures, overlapSkipped };
|
|
228
260
|
}
|
|
229
|
-
//# sourceMappingURL=patch-loop.js.map
|
|
@@ -11,7 +11,7 @@ function statusLabel(status, fuzzFactor) {
|
|
|
11
11
|
case 'applied-clean':
|
|
12
12
|
return 'applied cleanly';
|
|
13
13
|
case 'applied-fuzz':
|
|
14
|
-
return `applied with
|
|
14
|
+
return `applied with context reduction (step ${fuzzFactor ?? '?'})`;
|
|
15
15
|
case 'resolved':
|
|
16
16
|
return 'RESOLVED manually';
|
|
17
17
|
case 'failed':
|
|
@@ -43,6 +43,5 @@ export function printSummary(session) {
|
|
|
43
43
|
const failed = session.patches.filter((p) => p.status === 'failed').length;
|
|
44
44
|
const total = session.patches.length;
|
|
45
45
|
info('');
|
|
46
|
-
info(`Results: ${total} total: ${clean} clean, ${fuzz}
|
|
46
|
+
info(`Results: ${total} total: ${clean} clean, ${fuzz} context-reduced, ${resolved} manually resolved, ${failed} failed`);
|
|
47
47
|
}
|
|
48
|
-
//# sourceMappingURL=summary.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { Command } from 'commander';
|
|
3
4
|
import { getProjectPaths } from '../core/config.js';
|
|
4
5
|
import { registerFile } from '../core/manifest-rules.js';
|
|
5
6
|
import { InvalidArgumentError } from '../errors/base.js';
|
|
@@ -104,4 +105,3 @@ export function registerRegister(program, { getProjectRoot, withErrorHandling })
|
|
|
104
105
|
await registerCommand(getProjectRoot(), path, pickDefined(options));
|
|
105
106
|
}));
|
|
106
107
|
}
|
|
107
|
-
//# sourceMappingURL=register.js.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { confirm } from '@clack/prompts';
|
|
3
|
+
import { Command } from 'commander';
|
|
3
4
|
import { getProjectPaths } from '../core/config.js';
|
|
4
|
-
import {
|
|
5
|
-
import { hasChanges, isGitRepository, resetChanges } from '../core/git.js';
|
|
5
|
+
import { clearAppliedFurnaceState } from '../core/furnace-config.js';
|
|
6
|
+
import { getHead, hasChanges, isGitRepository, isMissingHeadError, resetChanges, } from '../core/git.js';
|
|
6
7
|
import { expandUntrackedDirectoryEntries, getWorkingTreeStatus } from '../core/git-status.js';
|
|
7
8
|
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
8
9
|
import { pathExists } from '../utils/fs.js';
|
|
@@ -24,6 +25,18 @@ export async function resetCommand(projectRoot, options) {
|
|
|
24
25
|
if (!(await isGitRepository(paths.engine))) {
|
|
25
26
|
throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
26
27
|
}
|
|
28
|
+
// Unborn-HEAD guard (mirrors status): an interrupted download leaves a
|
|
29
|
+
// repo with no baseline commit, where the entire ~300k-file tree reads
|
|
30
|
+
// as untracked — a reset against that state is never what the operator
|
|
31
|
+
// wants, and the guidance names the actual fix.
|
|
32
|
+
try {
|
|
33
|
+
await getHead(paths.engine);
|
|
34
|
+
}
|
|
35
|
+
catch (headError) {
|
|
36
|
+
if (!isMissingHeadError(headError))
|
|
37
|
+
throw headError;
|
|
38
|
+
throw new GeneralError('Engine repository has no baseline commit yet — a previous "fireforge download" was interrupted before git created the initial Firefox source commit. Re-run "fireforge download --force" to recreate the baseline repository cleanly.');
|
|
39
|
+
}
|
|
27
40
|
// Check for changes
|
|
28
41
|
const hasUncommittedChanges = await hasChanges(paths.engine);
|
|
29
42
|
if (!hasUncommittedChanges) {
|
|
@@ -71,12 +84,7 @@ export async function resetCommand(projectRoot, options) {
|
|
|
71
84
|
// consistent regardless of the drift oracle.) Preserve pendingRepair:
|
|
72
85
|
// authoring-side rollback markers are about the workspace/component
|
|
73
86
|
// tree, not the engine checkout, so reset must not silently forget them.
|
|
74
|
-
|
|
75
|
-
if (await pathExists(furnacePaths.furnaceState)) {
|
|
76
|
-
await updateFurnaceState(projectRoot, (current) => ({
|
|
77
|
-
...(current.pendingRepair ? { pendingRepair: current.pendingRepair } : {}),
|
|
78
|
-
}));
|
|
79
|
-
}
|
|
87
|
+
await clearAppliedFurnaceState(projectRoot);
|
|
80
88
|
s.stop('Changes reset');
|
|
81
89
|
outro('Working tree restored to clean state');
|
|
82
90
|
}
|
|
@@ -96,4 +104,3 @@ export function registerReset(program, { getProjectRoot, withErrorHandling }) {
|
|
|
96
104
|
await resetCommand(getProjectRoot(), pickDefined(options));
|
|
97
105
|
}));
|
|
98
106
|
}
|
|
99
|
-
//# sourceMappingURL=reset.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
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 { isGitRepository } from '../core/git.js';
|
|
6
7
|
import { getStagedDiffForFiles } from '../core/git-diff.js';
|
|
@@ -43,7 +44,7 @@ export async function resolveCommand(projectRoot, options = {}) {
|
|
|
43
44
|
// pipe / CI shell could otherwise commit whatever the engine
|
|
44
45
|
// currently contains. 2026-04-21 eval (Finding #18): a scripted
|
|
45
46
|
// recovery flow was dead-ended by the unconditional TTY refusal.
|
|
46
|
-
if (!process.stdin.isTTY && !options.yes) {
|
|
47
|
+
if (!(process.stdin.isTTY && process.stdout.isTTY) && !options.yes) {
|
|
47
48
|
throw new GeneralError('Cannot run "fireforge resolve" in non-interactive mode. Use a terminal with TTY support, or pass "--yes" to skip the interactive confirmation once the manual merge is complete.');
|
|
48
49
|
}
|
|
49
50
|
if (!options.yes) {
|
|
@@ -167,4 +168,3 @@ export function registerResolve(program, { getProjectRoot, withErrorHandling })
|
|
|
167
168
|
await resolveCommand(getProjectRoot(), options);
|
|
168
169
|
}));
|
|
169
170
|
}
|
|
170
|
-
//# sourceMappingURL=resolve.js.map
|
package/dist/src/commands/run.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { createWriteStream } from 'node:fs';
|
|
3
3
|
import { readdir, readFile } from 'node:fs/promises';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
|
+
import { Command } from 'commander';
|
|
5
6
|
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
6
7
|
import { warnIfFurnaceStale } from '../core/furnace-staleness.js';
|
|
7
8
|
import { buildArtifactMismatchMessage, hasBuildArtifacts, hasRunnableBundle, run, runMachSmoke, } from '../core/mach.js';
|
|
@@ -13,7 +14,7 @@ import { SmokeRunError } from '../errors/run.js';
|
|
|
13
14
|
import { toError } from '../utils/errors.js';
|
|
14
15
|
import { pathExists, removeDir, removeFile } from '../utils/fs.js';
|
|
15
16
|
import { info, intro, verbose, warn } from '../utils/logger.js';
|
|
16
|
-
import { pickDefined } from '../utils/options.js';
|
|
17
|
+
import { commanderArgParser, pickDefined } from '../utils/options.js';
|
|
17
18
|
/**
|
|
18
19
|
* Exit code returned by smoke-run mode when the captured console stream
|
|
19
20
|
* produced one or more error lines that did NOT match the operator's
|
|
@@ -124,7 +125,7 @@ export async function runCommand(projectRoot, options = {}) {
|
|
|
124
125
|
return;
|
|
125
126
|
}
|
|
126
127
|
info('Launching browser...\n');
|
|
127
|
-
const exitCode = await run(paths.engine);
|
|
128
|
+
const exitCode = await run(paths.engine, options.headless ? ['--headless'] : []);
|
|
128
129
|
// Exit-code whitelist:
|
|
129
130
|
// 0 — clean shutdown
|
|
130
131
|
// 130 — SIGINT (Ctrl+C), user-initiated termination
|
|
@@ -212,11 +213,22 @@ async function runSmokeExit(engineDir, options) {
|
|
|
212
213
|
}
|
|
213
214
|
findings.push({ stream, line });
|
|
214
215
|
};
|
|
216
|
+
// A headed smoke window on a developer desktop absorbs live input:
|
|
217
|
+
// during the drill a human interacted with the window mid-run, the
|
|
218
|
+
// password-manager import scan probed an unreadable Chrome profile
|
|
219
|
+
// dir, and the resulting console errors failed the smoke run looking
|
|
220
|
+
// like a product regression. CI hosts (CI env var set) are assumed
|
|
221
|
+
// display-free/unattended, so the notice stays quiet there.
|
|
222
|
+
if (!options.headless && !process.env['CI']) {
|
|
223
|
+
warn('Headed smoke window: keyboard/mouse input during the window will contaminate the ' +
|
|
224
|
+
'console capture and can fail the run. Pass --headless (or run on an unattended host) ' +
|
|
225
|
+
'for reliable smoke checks.');
|
|
226
|
+
}
|
|
215
227
|
info(`Launching browser (smoke-exit after ${String(smokeExit)}s)...\n`);
|
|
216
228
|
const startedAt = Date.now();
|
|
217
229
|
let result;
|
|
218
230
|
try {
|
|
219
|
-
result = await runMachSmoke(['run'], engineDir, {
|
|
231
|
+
result = await runMachSmoke(options.headless ? ['run', '--headless'] : ['run'], engineDir, {
|
|
220
232
|
smokeTimeoutMs,
|
|
221
233
|
onStdoutLine: (line) => {
|
|
222
234
|
handleLine('stdout', line);
|
|
@@ -319,21 +331,21 @@ export function registerRun(program, { getProjectRoot, withErrorHandling }) {
|
|
|
319
331
|
program
|
|
320
332
|
.command('run')
|
|
321
333
|
.description('Launch the built browser')
|
|
322
|
-
.option('--smoke-exit <seconds>', 'Smoke-run mode (POSIX only): launch, capture console, SIGTERM the process group after <seconds>. Exit 0 on a clean window, 12 on unallowed errors, 13 on launch failure.', (value) => {
|
|
334
|
+
.option('--smoke-exit <seconds>', 'Smoke-run mode (POSIX only): launch, capture console, SIGTERM the process group after <seconds>. Exit 0 on a clean window, 12 on unallowed errors, 13 on launch failure.', commanderArgParser((value) => {
|
|
323
335
|
const parsed = Number.parseInt(value, 10);
|
|
324
336
|
if (!Number.isFinite(parsed) || parsed < 1 || String(parsed) !== value.trim()) {
|
|
325
337
|
throw new Error(`--smoke-exit expects a positive integer number of seconds (got "${value}").`);
|
|
326
338
|
}
|
|
327
339
|
return parsed;
|
|
328
|
-
})
|
|
340
|
+
}))
|
|
329
341
|
.option('--console-allow <regex>', 'Allowlist regex (repeatable). Lines that match any entry do not count toward the smoke exit code.', (value, acc) => {
|
|
330
342
|
acc.push(value);
|
|
331
343
|
return acc;
|
|
332
344
|
}, [])
|
|
333
345
|
.option('--console-allow-file <path>', 'Newline-delimited allowlist regex file. Blank lines and # comments are ignored.')
|
|
334
346
|
.option('--capture-console <file>', 'Mirror captured console output to <file> for post-exit inspection.')
|
|
347
|
+
.option('--headless', 'Launch the browser with --headless. Recommended for --smoke-exit on a shared desktop: input into a headed smoke window contaminates the console capture.')
|
|
335
348
|
.action(withErrorHandling(async (options) => {
|
|
336
349
|
await runCommand(getProjectRoot(), pickDefined(options));
|
|
337
350
|
}));
|
|
338
351
|
}
|
|
339
|
-
//# sourceMappingURL=run.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { confirm } from '@clack/prompts';
|
|
4
|
-
import { Option } from 'commander';
|
|
4
|
+
import { Command, Option } from 'commander';
|
|
5
5
|
import { configExists } from '../core/config.js';
|
|
6
6
|
import { ConfigError } from '../errors/config.js';
|
|
7
7
|
import { cancel, intro, isCancel, note, outro, spinner } from '../utils/logger.js';
|
|
@@ -93,4 +93,3 @@ export function registerSetup(program, { withErrorHandling }) {
|
|
|
93
93
|
await setupCommand(resolve(process.cwd()), setupOptions);
|
|
94
94
|
}));
|
|
95
95
|
}
|
|
96
|
-
//# sourceMappingURL=setup.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { Option } from 'commander';
|
|
2
|
+
import { Command, Option } from 'commander';
|
|
3
3
|
import { configExists, loadRawConfigDocument, validateConfig, withConfigFileLock, writeConfigDocument, } from '../core/config.js';
|
|
4
4
|
import { resolveArchive } from '../core/firefox-archive.js';
|
|
5
5
|
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
@@ -92,4 +92,3 @@ export function registerSource(program, { getProjectRoot, withErrorHandling }) {
|
|
|
92
92
|
});
|
|
93
93
|
}));
|
|
94
94
|
}
|
|
95
|
-
//# sourceMappingURL=source.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { isFileRegistered, matchesRegistrablePattern } from '../core/manifest-rules.js';
|
|
3
|
+
import { getPrimaryStatusCode } from '../core/status-classify.js';
|
|
3
4
|
import { GeneralError } from '../errors/base.js';
|
|
4
5
|
import { info, outro, warn } from '../utils/logger.js';
|
|
5
6
|
const STATUS_DESCRIPTIONS = {
|
|
@@ -15,17 +16,6 @@ const STATUS_DESCRIPTIONS = {
|
|
|
15
16
|
function getStatusDescription(code) {
|
|
16
17
|
return STATUS_DESCRIPTIONS[code] ?? 'changed';
|
|
17
18
|
}
|
|
18
|
-
function getPrimaryStatusCode(status) {
|
|
19
|
-
if (status.includes('?'))
|
|
20
|
-
return '?';
|
|
21
|
-
if (status.includes('!'))
|
|
22
|
-
return '!';
|
|
23
|
-
for (const code of status) {
|
|
24
|
-
if (code !== ' ')
|
|
25
|
-
return code;
|
|
26
|
-
}
|
|
27
|
-
return status;
|
|
28
|
-
}
|
|
29
19
|
function isNewFileStatus(status) {
|
|
30
20
|
const code = getPrimaryStatusCode(status);
|
|
31
21
|
return code === '?' || code === 'A';
|
|
@@ -192,4 +182,3 @@ export async function renderDefaultStatus(totalModified, buckets, projectRoot, b
|
|
|
192
182
|
.map((section) => `${section.files.length} ${section.label}`);
|
|
193
183
|
outro(parts.join(', '));
|
|
194
184
|
}
|
|
195
|
-
//# sourceMappingURL=status-output.js.map
|