@hominis/fireforge 0.43.1 → 0.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +153 -0
- package/README.md +3 -3
- package/dist/bin/fireforge.d.ts +4 -9
- package/dist/bin/fireforge.js +42 -40
- package/dist/build-info.json +4 -4
- package/dist/src/cli.js +74 -8
- package/dist/src/commands/bootstrap.js +17 -20
- package/dist/src/commands/build.js +25 -32
- package/dist/src/commands/config.js +34 -41
- package/dist/src/commands/discard.js +8 -9
- package/dist/src/commands/doctor-check-core.d.ts +13 -18
- package/dist/src/commands/doctor-check-core.js +8 -35
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +18 -0
- package/dist/src/commands/{doctor-furnace-manifest-sync.js → doctor-furnace-config-sync.js} +27 -26
- package/dist/src/commands/doctor-furnace-jar.d.ts +7 -9
- package/dist/src/commands/doctor-furnace-jar.js +7 -9
- package/dist/src/commands/doctor-furnace.js +21 -24
- package/dist/src/commands/doctor-orphaned-harness.d.ts +16 -20
- package/dist/src/commands/doctor-orphaned-harness.js +18 -44
- package/dist/src/commands/doctor-patch-manifest.d.ts +8 -0
- package/dist/src/commands/doctor-patch-manifest.js +155 -0
- package/dist/src/commands/doctor-post-rebase-audit.d.ts +2 -0
- package/dist/src/commands/{doctor/post-rebase-audit.js → doctor-post-rebase-audit.js} +3 -3
- package/dist/src/commands/doctor-working-tree.d.ts +10 -12
- package/dist/src/commands/doctor-working-tree.js +11 -18
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +64 -96
- package/dist/src/commands/download.js +32 -48
- package/dist/src/commands/export-all.js +29 -33
- package/dist/src/commands/export-flow.js +6 -6
- package/dist/src/commands/export-placement-conflicts.js +10 -9
- package/dist/src/commands/export-placement-gate.js +5 -5
- package/dist/src/commands/export-shared.d.ts +30 -33
- package/dist/src/commands/export-shared.js +45 -43
- package/dist/src/commands/export.js +21 -27
- package/dist/src/commands/furnace/apply.js +14 -23
- package/dist/src/commands/furnace/chrome-doc-remove.js +14 -21
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +23 -23
- package/dist/src/commands/furnace/chrome-doc-templates.js +23 -23
- package/dist/src/commands/furnace/chrome-doc-tests.js +26 -29
- package/dist/src/commands/furnace/chrome-doc.d.ts +16 -17
- package/dist/src/commands/furnace/chrome-doc.js +31 -41
- package/dist/src/commands/furnace/create-browser-test.d.ts +4 -4
- package/dist/src/commands/furnace/create-browser-test.js +8 -8
- package/dist/src/commands/furnace/create-mochikit.d.ts +6 -7
- package/dist/src/commands/furnace/create-mochikit.js +8 -9
- package/dist/src/commands/furnace/create-readback.d.ts +12 -13
- package/dist/src/commands/furnace/create-readback.js +12 -13
- package/dist/src/commands/furnace/create-templates.d.ts +22 -28
- package/dist/src/commands/furnace/create-templates.js +35 -30
- package/dist/src/commands/furnace/create-xpcshell.js +2 -2
- package/dist/src/commands/furnace/create.js +33 -23
- package/dist/src/commands/furnace/deploy.js +16 -24
- package/dist/src/commands/furnace/diff.js +15 -10
- package/dist/src/commands/furnace/init.js +33 -36
- package/dist/src/commands/furnace/override.js +23 -25
- package/dist/src/commands/furnace/preview.js +47 -67
- package/dist/src/commands/furnace/refresh.js +12 -16
- package/dist/src/commands/furnace/remove-mutations.d.ts +3 -6
- package/dist/src/commands/furnace/remove-mutations.js +14 -17
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +33 -38
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +8 -11
- package/dist/src/commands/furnace/rename-xpcshell.js +8 -11
- package/dist/src/commands/furnace/rename.js +59 -69
- package/dist/src/commands/furnace/scan.js +19 -33
- package/dist/src/commands/furnace/status.js +12 -9
- package/dist/src/commands/furnace/sync.js +9 -16
- package/dist/src/commands/furnace/validate.js +20 -20
- package/dist/src/commands/import.js +48 -37
- package/dist/src/commands/lint-per-patch.js +15 -10
- package/dist/src/commands/lint-per-run-checkjs.d.ts +13 -13
- package/dist/src/commands/lint-per-run-checkjs.js +13 -13
- package/dist/src/commands/lint-report.js +6 -7
- package/dist/src/commands/lint.d.ts +15 -16
- package/dist/src/commands/lint.js +86 -102
- package/dist/src/commands/package.js +6 -11
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +24 -33
- package/dist/src/commands/patch/index.d.ts +5 -6
- package/dist/src/commands/patch/index.js +10 -12
- package/dist/src/commands/patch/lint-ignore.js +14 -13
- package/dist/src/commands/patch/move-files-create.d.ts +6 -6
- package/dist/src/commands/patch/move-files-create.js +8 -8
- package/dist/src/commands/patch/move-files-into.d.ts +6 -6
- package/dist/src/commands/patch/move-files-into.js +8 -8
- package/dist/src/commands/patch/patch-context.d.ts +2 -3
- package/dist/src/commands/patch/patch-context.js +2 -3
- package/dist/src/commands/patch/rename.d.ts +10 -11
- package/dist/src/commands/patch/rename.js +11 -12
- package/dist/src/commands/patch/reorder.js +8 -9
- package/dist/src/commands/patch/split-plan.js +1 -1
- package/dist/src/commands/patch/split.d.ts +8 -10
- package/dist/src/commands/patch/split.js +9 -11
- package/dist/src/commands/patch/staged-dependency-validate.js +8 -8
- package/dist/src/commands/patch/staged-dependency.js +7 -3
- package/dist/src/commands/patch/tier.d.ts +9 -9
- package/dist/src/commands/patch/tier.js +18 -15
- package/dist/src/commands/re-export-adjacent.js +9 -8
- package/dist/src/commands/re-export-bulk-scan.d.ts +9 -9
- package/dist/src/commands/re-export-bulk-scan.js +22 -21
- package/dist/src/commands/re-export-drift.js +10 -10
- package/dist/src/commands/re-export-files.d.ts +6 -7
- package/dist/src/commands/re-export-files.js +34 -44
- package/dist/src/commands/re-export-lint.d.ts +10 -13
- package/dist/src/commands/re-export-lint.js +16 -14
- package/dist/src/commands/re-export-options.d.ts +6 -6
- package/dist/src/commands/re-export-options.js +6 -6
- package/dist/src/commands/re-export-register.d.ts +4 -10
- package/dist/src/commands/re-export-register.js +5 -11
- package/dist/src/commands/re-export-scan.js +1 -1
- package/dist/src/commands/re-export-single.d.ts +3 -3
- package/dist/src/commands/re-export-single.js +33 -25
- package/dist/src/commands/re-export.js +13 -21
- package/dist/src/commands/rebase/abort.js +3 -3
- package/dist/src/commands/rebase/confirm.js +2 -1
- package/dist/src/commands/rebase/continue.d.ts +1 -1
- package/dist/src/commands/rebase/continue.js +14 -9
- package/dist/src/commands/rebase/index.js +11 -11
- package/dist/src/commands/rebase/patch-loop.d.ts +7 -1
- package/dist/src/commands/rebase/patch-loop.js +60 -39
- package/dist/src/commands/rebase/summary.js +1 -1
- package/dist/src/commands/register.js +5 -7
- package/dist/src/commands/reset.js +2 -1
- package/dist/src/commands/resolve.d.ts +16 -13
- package/dist/src/commands/resolve.js +30 -33
- package/dist/src/commands/run.js +33 -35
- package/dist/src/commands/setup-support.js +15 -19
- package/dist/src/commands/setup.js +13 -9
- package/dist/src/commands/status-check.d.ts +6 -6
- package/dist/src/commands/status-json.d.ts +6 -6
- package/dist/src/commands/status-json.js +5 -0
- package/dist/src/commands/status-output.d.ts +5 -5
- package/dist/src/commands/status-output.js +6 -6
- package/dist/src/commands/status-ownership.d.ts +16 -14
- package/dist/src/commands/status-ownership.js +16 -14
- package/dist/src/commands/status.js +42 -34
- package/dist/src/commands/test-build-phase.js +26 -13
- package/dist/src/commands/test-diagnose.js +44 -44
- package/dist/src/commands/test-register.js +1 -0
- package/dist/src/commands/test-run.d.ts +14 -16
- package/dist/src/commands/test-run.js +21 -13
- package/dist/src/commands/test-stale-gate.d.ts +15 -16
- package/dist/src/commands/test-stale-gate.js +15 -16
- package/dist/src/commands/test-verdict.d.ts +20 -3
- package/dist/src/commands/test-verdict.js +30 -0
- package/dist/src/commands/test.js +83 -76
- package/dist/src/commands/token-coverage.js +3 -4
- package/dist/src/commands/token.js +16 -18
- package/dist/src/commands/tree.js +47 -31
- package/dist/src/commands/typecheck.d.ts +10 -12
- package/dist/src/commands/typecheck.js +24 -27
- package/dist/src/commands/verify.js +13 -15
- package/dist/src/commands/watch.js +21 -23
- package/dist/src/commands/wire.js +52 -62
- package/dist/src/core/ast-utils.d.ts +8 -7
- package/dist/src/core/ast-utils.js +8 -7
- package/dist/src/core/branding.d.ts +9 -14
- package/dist/src/core/branding.js +7 -11
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +14 -19
- package/dist/src/core/build-audit-platform.js +25 -33
- package/dist/src/core/build-audit-registration.js +17 -25
- package/dist/src/core/build-audit-resolve.d.ts +15 -17
- package/dist/src/core/build-audit-resolve.js +39 -36
- package/dist/src/core/build-audit-transforms.js +18 -19
- package/dist/src/core/build-audit.js +28 -42
- package/dist/src/core/build-baseline-types.d.ts +29 -35
- package/dist/src/core/build-baseline.d.ts +5 -4
- package/dist/src/core/build-baseline.js +14 -14
- package/dist/src/core/build-overwrite-guard.d.ts +7 -14
- package/dist/src/core/build-overwrite-guard.js +17 -27
- package/dist/src/core/build-prepare.d.ts +2 -2
- package/dist/src/core/build-prepare.js +8 -9
- package/dist/src/core/config-mutate.js +20 -19
- package/dist/src/core/config-state.js +12 -4
- package/dist/src/core/config-validate.js +8 -5
- package/dist/src/core/config.d.ts +5 -8
- package/dist/src/core/config.js +7 -16
- package/dist/src/core/coverage-extend.d.ts +15 -13
- package/dist/src/core/coverage-extend.js +15 -13
- package/dist/src/core/destructive.d.ts +31 -9
- package/dist/src/core/destructive.js +29 -26
- package/dist/src/core/diff-hunks.js +10 -12
- package/dist/src/core/discard-baseline.d.ts +8 -8
- package/dist/src/core/discard-baseline.js +16 -15
- package/dist/src/core/display-state.d.ts +12 -14
- package/dist/src/core/display-state.js +12 -14
- package/dist/src/core/engine-changes.d.ts +2 -4
- package/dist/src/core/engine-changes.js +2 -4
- package/dist/src/core/engine-precondition.d.ts +28 -13
- package/dist/src/core/engine-precondition.js +25 -10
- package/dist/src/core/engine-session-lock.d.ts +47 -21
- package/dist/src/core/engine-session-lock.js +168 -33
- package/dist/src/core/export-moved-code-shape.d.ts +10 -10
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock.d.ts +62 -5
- package/dist/src/core/file-lock.js +196 -59
- package/dist/src/core/firefox-cache.js +1 -3
- package/dist/src/core/firefox-extract.js +10 -14
- package/dist/src/core/firefox.d.ts +7 -5
- package/dist/src/core/firefox.js +4 -5
- package/dist/src/core/furnace-apply-dry-run.d.ts +2 -2
- package/dist/src/core/furnace-apply-dry-run.js +3 -2
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -9
- package/dist/src/core/furnace-apply-ftl.js +16 -13
- package/dist/src/core/furnace-apply-helpers.d.ts +7 -7
- package/dist/src/core/furnace-apply-helpers.js +30 -21
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +8 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +8 -9
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +3 -4
- package/dist/src/core/furnace-apply-undeploy-actions.js +3 -4
- package/dist/src/core/furnace-apply.d.ts +5 -8
- package/dist/src/core/furnace-apply.js +19 -24
- package/dist/src/core/furnace-checksum-utils.d.ts +14 -0
- package/dist/src/core/furnace-checksum-utils.js +16 -0
- package/dist/src/core/furnace-config.d.ts +21 -30
- package/dist/src/core/furnace-config.js +32 -54
- package/dist/src/core/furnace-constants.d.ts +8 -0
- package/dist/src/core/furnace-constants.js +10 -2
- package/dist/src/core/furnace-css-fragments.d.ts +5 -5
- package/dist/src/core/furnace-css-fragments.js +5 -5
- package/dist/src/core/furnace-jsconfig.d.ts +11 -12
- package/dist/src/core/furnace-jsconfig.js +11 -12
- package/dist/src/core/furnace-marker.d.ts +7 -8
- package/dist/src/core/furnace-marker.js +7 -8
- package/dist/src/core/furnace-operation.d.ts +31 -0
- package/dist/src/core/furnace-operation.js +54 -17
- package/dist/src/core/furnace-precondition.d.ts +61 -0
- package/dist/src/core/furnace-precondition.js +67 -0
- package/dist/src/core/furnace-registration-remove.d.ts +5 -6
- package/dist/src/core/furnace-registration-remove.js +6 -7
- package/dist/src/core/furnace-registration-validate.d.ts +13 -0
- package/dist/src/core/furnace-registration-validate.js +20 -1
- package/dist/src/core/furnace-registration.d.ts +5 -6
- package/dist/src/core/furnace-registration.js +10 -12
- package/dist/src/core/furnace-rollback.js +7 -7
- package/dist/src/core/furnace-scanner.d.ts +1 -0
- package/dist/src/core/furnace-scanner.js +1 -2
- package/dist/src/core/furnace-stale-export.d.ts +10 -10
- package/dist/src/core/furnace-stale-export.js +10 -10
- package/dist/src/core/furnace-state-persist.d.ts +6 -8
- package/dist/src/core/furnace-state-persist.js +6 -8
- package/dist/src/core/furnace-validate-accessibility.d.ts +22 -0
- package/dist/src/core/furnace-validate-accessibility.js +310 -1
- package/dist/src/core/furnace-validate-compatibility.js +141 -1
- package/dist/src/core/furnace-validate-helpers.d.ts +5 -116
- package/dist/src/core/furnace-validate-helpers.js +0 -491
- package/dist/src/core/furnace-validate-registration.d.ts +7 -0
- package/dist/src/core/furnace-validate-registration.js +115 -41
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +188 -145
- package/dist/src/core/furnace-version-drift.d.ts +10 -11
- package/dist/src/core/furnace-version-drift.js +10 -11
- package/dist/src/core/git-base.d.ts +21 -9
- package/dist/src/core/git-base.js +24 -9
- package/dist/src/core/git-diff.d.ts +20 -9
- package/dist/src/core/git-diff.js +148 -63
- package/dist/src/core/git-file-ops.d.ts +19 -19
- package/dist/src/core/git-file-ops.js +19 -19
- package/dist/src/core/git-readonly-index.d.ts +53 -19
- package/dist/src/core/git-readonly-index.js +75 -31
- package/dist/src/core/git-status.d.ts +5 -6
- package/dist/src/core/git-status.js +5 -6
- package/dist/src/core/git.d.ts +9 -10
- package/dist/src/core/git.js +57 -71
- package/dist/src/core/license-headers.d.ts +17 -23
- package/dist/src/core/license-headers.js +17 -23
- package/dist/src/core/mach-build-artifacts.d.ts +9 -9
- package/dist/src/core/mach-build-artifacts.js +57 -19
- package/dist/src/core/mach-error-hints.js +42 -29
- package/dist/src/core/mach-known-noise-filter.d.ts +15 -16
- package/dist/src/core/mach-known-noise-filter.js +18 -20
- package/dist/src/core/mach-mozconfig.d.ts +14 -0
- package/dist/src/core/mach-mozconfig.js +30 -0
- package/dist/src/core/mach-resource-shim.d.ts +43 -58
- package/dist/src/core/mach-resource-shim.js +50 -67
- package/dist/src/core/mach.d.ts +37 -41
- package/dist/src/core/mach.js +50 -51
- package/dist/src/core/marionette-port.d.ts +36 -1
- package/dist/src/core/marionette-port.js +96 -31
- package/dist/src/core/marionette-preflight.d.ts +8 -12
- package/dist/src/core/marionette-preflight.js +86 -52
- package/dist/src/core/mochitest-server-port.d.ts +42 -0
- package/dist/src/core/mochitest-server-port.js +119 -0
- package/dist/src/core/module-resolution-preflight.d.ts +9 -11
- package/dist/src/core/module-resolution-preflight.js +9 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +79 -0
- package/dist/src/core/moz-manifest-helpers.js +163 -0
- package/dist/src/core/{manifest-register.d.ts → moz-manifest-register.d.ts} +1 -1
- package/dist/src/core/{manifest-register.js → moz-manifest-register.js} +13 -28
- package/dist/src/core/{manifest-rules.d.ts → moz-manifest-rules.d.ts} +10 -1
- package/dist/src/core/{manifest-rules.js → moz-manifest-rules.js} +31 -24
- package/dist/src/core/{manifest-tokenizers.d.ts → moz-manifest-tokenizers.d.ts} +3 -5
- package/dist/src/core/{manifest-tokenizers.js → moz-manifest-tokenizers.js} +9 -12
- package/dist/src/core/ownership-table.d.ts +14 -16
- package/dist/src/core/ownership-table.js +14 -16
- package/dist/src/core/parser-fallback.d.ts +15 -1
- package/dist/src/core/parser-fallback.js +22 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +10 -12
- package/dist/src/core/patch-apply-fuzz.js +15 -18
- package/dist/src/core/patch-apply.d.ts +13 -34
- package/dist/src/core/patch-apply.js +16 -76
- package/dist/src/core/patch-artifact-normalize.d.ts +13 -15
- package/dist/src/core/patch-artifact-normalize.js +13 -15
- package/dist/src/core/patch-export-metadata.d.ts +12 -2
- package/dist/src/core/patch-export-metadata.js +13 -4
- package/dist/src/core/patch-export-update.d.ts +13 -1
- package/dist/src/core/patch-export-update.js +25 -8
- package/dist/src/core/patch-export.d.ts +15 -8
- package/dist/src/core/patch-export.js +10 -11
- package/dist/src/core/patch-files.d.ts +5 -6
- package/dist/src/core/patch-files.js +5 -6
- package/dist/src/core/patch-identifier-suggest.d.ts +7 -12
- package/dist/src/core/patch-identifier-suggest.js +14 -19
- package/dist/src/core/patch-lint-binary.d.ts +51 -0
- package/dist/src/core/patch-lint-binary.js +39 -0
- package/dist/src/core/{lint-cache.d.ts → patch-lint-cache.d.ts} +5 -5
- package/dist/src/core/{lint-cache.js → patch-lint-cache.js} +21 -23
- package/dist/src/core/patch-lint-checkjs.d.ts +16 -16
- package/dist/src/core/patch-lint-checkjs.js +41 -20
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +6 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -14
- package/dist/src/core/patch-lint-creators.d.ts +8 -8
- package/dist/src/core/patch-lint-creators.js +8 -8
- package/dist/src/core/patch-lint-cross.d.ts +17 -20
- package/dist/src/core/patch-lint-cross.js +16 -16
- package/dist/src/core/patch-lint-css.d.ts +3 -5
- package/dist/src/core/patch-lint-css.js +17 -22
- package/dist/src/core/patch-lint-diff-tag.d.ts +14 -16
- package/dist/src/core/patch-lint-diff-tag.js +14 -16
- package/dist/src/core/patch-lint-jsdoc.d.ts +7 -8
- package/dist/src/core/patch-lint-jsdoc.js +26 -19
- package/dist/src/core/patch-lint-mozbuild.js +20 -20
- package/dist/src/core/patch-lint-observer.d.ts +7 -7
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint.d.ts +38 -29
- package/dist/src/core/patch-lint.js +89 -121
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +45 -9
- package/dist/src/core/patch-manifest-consistency.d.ts +57 -6
- package/dist/src/core/patch-manifest-consistency.js +111 -40
- package/dist/src/core/patch-manifest-files-affected.d.ts +43 -0
- package/dist/src/core/patch-manifest-files-affected.js +77 -0
- package/dist/src/core/patch-manifest-io.js +14 -18
- package/dist/src/core/patch-manifest-resolve.d.ts +9 -12
- package/dist/src/core/patch-manifest-resolve.js +9 -12
- package/dist/src/core/patch-manifest-validate.d.ts +6 -1
- package/dist/src/core/patch-manifest-validate.js +25 -13
- package/dist/src/core/patch-manifest.d.ts +2 -1
- package/dist/src/core/patch-manifest.js +2 -1
- package/dist/src/core/patch-parse.d.ts +24 -13
- package/dist/src/core/patch-parse.js +19 -14
- package/dist/src/core/patch-policy.d.ts +2 -2
- package/dist/src/core/patch-policy.js +2 -2
- package/dist/src/core/patch-registration-refs.d.ts +7 -8
- package/dist/src/core/patch-registration-refs.js +9 -9
- package/dist/src/core/process-cpu-time.d.ts +12 -0
- package/dist/src/core/process-cpu-time.js +52 -0
- package/dist/src/core/rebase-session.d.ts +38 -26
- package/dist/src/core/rebase-session.js +55 -28
- package/dist/src/core/register-browser-content.js +9 -74
- package/dist/src/core/{register-test-manifest.js → register-browser-test.js} +7 -42
- package/dist/src/core/register-module.js +10 -43
- package/dist/src/core/register-scaffold.d.ts +8 -8
- package/dist/src/core/register-scaffold.js +10 -10
- package/dist/src/core/register-shared-css.d.ts +9 -12
- package/dist/src/core/register-shared-css.js +17 -87
- package/dist/src/core/register-xpcshell-test.d.ts +6 -7
- package/dist/src/core/register-xpcshell-test.js +7 -8
- package/dist/src/core/shared-ftl.js +12 -4
- package/dist/src/core/state-file.d.ts +45 -0
- package/dist/src/core/state-file.js +34 -0
- package/dist/src/core/status-binary.d.ts +18 -11
- package/dist/src/core/status-binary.js +19 -12
- package/dist/src/core/status-classify.d.ts +30 -36
- package/dist/src/core/status-classify.js +21 -26
- package/dist/src/core/test-changed-prefs.d.ts +30 -0
- package/dist/src/core/test-changed-prefs.js +78 -0
- package/dist/src/core/test-harness-crash.d.ts +25 -63
- package/dist/src/core/test-harness-crash.js +121 -142
- package/dist/src/core/test-harness-signature.d.ts +18 -0
- package/dist/src/core/test-harness-signature.js +13 -0
- package/dist/src/core/test-path-scope.d.ts +12 -15
- package/dist/src/core/test-path-scope.js +15 -18
- package/dist/src/core/test-stale-check.d.ts +17 -17
- package/dist/src/core/test-stale-check.js +50 -43
- package/dist/src/core/test-stall-triage.d.ts +51 -0
- package/dist/src/core/test-stall-triage.js +126 -0
- package/dist/src/core/token-category.js +66 -14
- package/dist/src/core/token-coverage.js +9 -9
- package/dist/src/core/token-dark-mode.d.ts +9 -11
- package/dist/src/core/token-dark-mode.js +29 -13
- package/dist/src/core/token-docs.d.ts +2 -0
- package/dist/src/core/token-docs.js +3 -1
- package/dist/src/core/token-manager.d.ts +10 -2
- package/dist/src/core/token-manager.js +17 -8
- package/dist/src/core/token-scaffold.d.ts +7 -7
- package/dist/src/core/token-scaffold.js +7 -7
- package/dist/src/core/token-variant.d.ts +4 -4
- package/dist/src/core/token-variant.js +28 -6
- package/dist/src/core/toolchain-preflight.d.ts +20 -21
- package/dist/src/core/toolchain-preflight.js +28 -31
- package/dist/src/core/tree-guard.js +12 -2
- package/dist/src/core/tree-store.d.ts +41 -27
- package/dist/src/core/tree-store.js +68 -43
- package/dist/src/core/typecheck-shim.d.ts +23 -24
- package/dist/src/core/typecheck-shim.js +23 -24
- package/dist/src/core/typecheck.js +15 -9
- package/dist/src/core/wire-destroy.d.ts +3 -3
- package/dist/src/core/wire-destroy.js +7 -15
- package/dist/src/core/wire-dom-fragment.d.ts +9 -17
- package/dist/src/core/wire-dom-fragment.js +11 -44
- package/dist/src/core/wire-init.d.ts +2 -3
- package/dist/src/core/wire-init.js +8 -19
- package/dist/src/core/wire-subscript.d.ts +2 -3
- package/dist/src/core/wire-subscript.js +4 -13
- package/dist/src/core/wire-utils.d.ts +7 -8
- package/dist/src/core/wire-utils.js +7 -8
- package/dist/src/core/xpcshell-appdir.d.ts +38 -45
- package/dist/src/core/xpcshell-appdir.js +38 -45
- package/dist/src/errors/base.d.ts +37 -16
- package/dist/src/errors/base.js +37 -16
- package/dist/src/errors/build.d.ts +13 -1
- package/dist/src/errors/build.js +14 -2
- package/dist/src/errors/codes.d.ts +16 -0
- package/dist/src/errors/codes.js +16 -0
- package/dist/src/errors/furnace.d.ts +4 -4
- package/dist/src/errors/git.d.ts +6 -10
- package/dist/src/errors/git.js +6 -10
- package/dist/src/errors/patch.d.ts +7 -7
- package/dist/src/errors/patch.js +7 -7
- package/dist/src/errors/rebase.d.ts +4 -4
- package/dist/src/errors/rebase.js +4 -4
- package/dist/src/index.d.ts +7 -1
- package/dist/src/index.js +5 -0
- package/dist/src/types/commands/index.d.ts +2 -2
- package/dist/src/types/commands/options.d.ts +111 -70
- package/dist/src/types/commands/patches.d.ts +24 -34
- package/dist/src/types/commands/project.d.ts +5 -34
- package/dist/src/types/config.d.ts +25 -23
- package/dist/src/types/config.js +6 -1
- package/dist/src/types/furnace.d.ts +37 -13
- package/dist/src/types/furnace.js +19 -1
- package/dist/src/types/index.d.ts +3 -3
- package/dist/src/utils/build-info.d.ts +7 -8
- package/dist/src/utils/build-info.js +12 -11
- package/dist/src/utils/errors.d.ts +6 -8
- package/dist/src/utils/errors.js +6 -8
- package/dist/src/utils/logger.d.ts +27 -10
- package/dist/src/utils/logger.js +28 -16
- package/dist/src/utils/machine-output.d.ts +12 -0
- package/dist/src/utils/machine-output.js +33 -0
- package/dist/src/utils/options.d.ts +31 -14
- package/dist/src/utils/options.js +86 -30
- package/dist/src/utils/paths.d.ts +10 -8
- package/dist/src/utils/paths.js +10 -8
- package/dist/src/utils/platform.d.ts +0 -25
- package/dist/src/utils/platform.js +1 -42
- package/dist/src/utils/process-group.d.ts +9 -4
- package/dist/src/utils/process-group.js +19 -5
- package/dist/src/utils/process.d.ts +42 -7
- package/dist/src/utils/process.js +44 -17
- package/dist/src/utils/ps-duration.d.ts +31 -0
- package/dist/src/utils/ps-duration.js +70 -0
- package/dist/src/utils/regex.d.ts +9 -10
- package/dist/src/utils/regex.js +9 -10
- package/dist/src/utils/validation.d.ts +58 -28
- package/dist/src/utils/validation.js +60 -33
- package/package.json +3 -3
- package/dist/src/commands/doctor/post-rebase-audit.d.ts +0 -2
- package/dist/src/commands/doctor-furnace-manifest-sync.d.ts +0 -18
- package/dist/src/core/manifest-helpers.d.ts +0 -38
- package/dist/src/core/manifest-helpers.js +0 -120
- /package/dist/src/core/{lint-projection.d.ts → patch-lint-projection.d.ts} +0 -0
- /package/dist/src/core/{lint-projection.js → patch-lint-projection.js} +0 -0
- /package/dist/src/core/{register-test-manifest.d.ts → register-browser-test.d.ts} +0 -0
|
@@ -88,17 +88,17 @@ export async function fileExistsInHead(repoDir, filePath) {
|
|
|
88
88
|
return (await git(['ls-tree', 'HEAD', '--', filePath], repoDir)).trim().length > 0;
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
* Batched equivalent of {@link fileExistsInHead}: returns the subset of
|
|
92
|
-
* that are tracked in HEAD, using a single `git ls-tree` per ARG_MAX
|
|
93
|
-
* instead of one spawn per file. This is the cold-run hot path — a
|
|
94
|
-
* checkout has hundreds of affected files
|
|
95
|
-
*
|
|
91
|
+
* Batched equivalent of {@link fileExistsInHead}: returns the subset of
|
|
92
|
+
* `files` that are tracked in HEAD, using a single `git ls-tree` per ARG_MAX
|
|
93
|
+
* chunk instead of one spawn per file. This is the cold-run hot path — a
|
|
94
|
+
* Firefox-sized checkout has hundreds of affected files.
|
|
95
|
+
*
|
|
96
|
+
* `-r` lists nested blobs by full repo-relative path; `--name-only -z` makes
|
|
97
|
+
* the output a trivial NUL-split with no quoting to undo. Membership in the
|
|
98
|
+
* returned Set is exactly `await fileExistsInHead(repoDir, file)` for any
|
|
99
|
+
* non-directory `file`. Throws (via {@link git}) when HEAD itself is
|
|
100
|
+
* unresolvable, matching the per-file helper's failure mode.
|
|
96
101
|
*
|
|
97
|
-
* `-r` lists nested blobs by full repo-relative path; `--name-only -z` makes the
|
|
98
|
-
* output a trivial NUL-split with no quoting to undo. Membership in the returned
|
|
99
|
-
* Set is exactly `await fileExistsInHead(repoDir, file)` for any non-directory
|
|
100
|
-
* `file`. Throws (via {@link git}) when HEAD itself is unresolvable, matching the
|
|
101
|
-
* per-file helper's failure mode.
|
|
102
102
|
* @param repoDir - Repository directory
|
|
103
103
|
* @param files - Repo-relative paths to classify
|
|
104
104
|
* @returns The subset of `files` present in HEAD
|
|
@@ -129,15 +129,15 @@ export async function listTrackedInHead(repoDir, files) {
|
|
|
129
129
|
*
|
|
130
130
|
* Uses {@link import('../utils/process.js').exec} rather than {@link git}
|
|
131
131
|
* (which throws on a non-zero exit) because `git hash-object f1 f2 …` is
|
|
132
|
-
* all-or-nothing: it aborts at the first unreadable path and emits nothing
|
|
133
|
-
* the rest. To
|
|
134
|
-
* only its own index line — a chunk that does not return exactly one hash
|
|
135
|
-
* input falls back to hashing that chunk's paths individually. A path
|
|
136
|
-
* still unhashable is
|
|
137
|
-
* `0000000000` zero-hash fallback
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
132
|
+
* all-or-nothing: it aborts at the first unreadable path and emits nothing
|
|
133
|
+
* for the rest. To keep the per-file contract — where one bad path zeroes
|
|
134
|
+
* only its own index line — a chunk that does not return exactly one hash
|
|
135
|
+
* per input falls back to hashing that chunk's paths individually. A path
|
|
136
|
+
* that is still unhashable is left out of the map; the caller applies the
|
|
137
|
+
* `0000000000` zero-hash fallback for any miss. Hashing stays in git rather
|
|
138
|
+
* than in-process so filters and `.gitattributes` are applied per path and
|
|
139
|
+
* the result cannot diverge under `core.autocrlf`/`text` attributes.
|
|
140
|
+
*
|
|
141
141
|
* @param repoDir - Repository directory
|
|
142
142
|
* @param fullPaths - Absolute file paths to hash
|
|
143
143
|
* @returns Map from each input path to its full blob hash (misses omitted)
|
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Private-index scope for FireForge's READ-ONLY git plumbing.
|
|
3
3
|
*
|
|
4
|
-
* `git status` and `git diff HEAD` are read-only in the sense operators
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `.git/index
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* `git status` and `git diff HEAD` are read-only in the sense operators care
|
|
5
|
+
* about — they never change tracked content — but they are NOT read-only to
|
|
6
|
+
* git: both refresh the index's stat cache and write `.git/index` (through
|
|
7
|
+
* `.git/index.lock`) when a file's stat data has moved. That makes
|
|
8
|
+
* `fireforge verify` / `lint --per-patch` / `typecheck` a second WRITER of
|
|
9
|
+
* the primary `engine/` checkout, even when the command was pointed at a CoW
|
|
10
|
+
* tree clone.
|
|
11
11
|
*
|
|
12
12
|
* The consequence is not cosmetic. A concurrent `fireforge test`
|
|
13
13
|
* fingerprints `engine/` before and after the harness run and refuses a
|
|
14
|
-
* verdict taken across a change (`FAIL reason=inconclusive`). That refusal
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* between lane overlap and inconclusive verdicts, on suites that had
|
|
18
|
-
* actually passed.
|
|
14
|
+
* verdict taken across a change (`FAIL reason=inconclusive`). That refusal is
|
|
15
|
+
* CORRECT and stays; the defect is FireForge's own read-only commands
|
|
16
|
+
* tripping it.
|
|
19
17
|
*
|
|
20
18
|
* The fix is the standard git one: point the plumbing at a PRIVATE index
|
|
21
|
-
* (`GIT_INDEX_FILE`) seeded from the repository's own, in a temp
|
|
22
|
-
*
|
|
23
|
-
* `.git/index
|
|
24
|
-
*
|
|
19
|
+
* (`GIT_INDEX_FILE`) seeded from the repository's own, in a temp directory.
|
|
20
|
+
* Refreshes land there and are thrown away; the primary `.git/index` — and
|
|
21
|
+
* `.git/index.lock`, which is what makes a concurrent `git status` fail
|
|
22
|
+
* outright rather than merely churn — is never touched.
|
|
25
23
|
*
|
|
26
24
|
* Fail-open by design: if the git dir or the index cannot be resolved or
|
|
27
|
-
* copied, the scope
|
|
28
|
-
*
|
|
29
|
-
*
|
|
25
|
+
* copied, the scope does not activate and the commands behave exactly as
|
|
26
|
+
* before. A read-only command must not start failing because an optimisation
|
|
27
|
+
* could not be set up.
|
|
30
28
|
*
|
|
31
29
|
* The scope is process-global and non-reentrant on purpose: FireForge
|
|
32
30
|
* commands are one-shot CLI invocations, and nesting two different private
|
|
@@ -57,3 +55,39 @@ export declare function hasReadOnlyGitIndexScope(): boolean;
|
|
|
57
55
|
* @returns Whatever `operation` returns
|
|
58
56
|
*/
|
|
59
57
|
export declare function withPrivateGitIndex<T>(repoDir: string, operation: () => Promise<T>): Promise<T>;
|
|
58
|
+
/**
|
|
59
|
+
* A private index file plus the cleanup that removes it.
|
|
60
|
+
*
|
|
61
|
+
* `env` is meant to be handed to a SINGLE git invocation (or a small
|
|
62
|
+
* sequence of them), rather than installed process-wide the way
|
|
63
|
+
* {@link withPrivateGitIndex} installs a scope.
|
|
64
|
+
*/
|
|
65
|
+
export interface DisposableGitIndex {
|
|
66
|
+
/** Environment overlay pointing git at the private index. */
|
|
67
|
+
env: Record<string, string>;
|
|
68
|
+
/** Removes the private index. Never throws. */
|
|
69
|
+
dispose: () => Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Mints a private index seeded from `repoDir`'s own, for a caller that
|
|
73
|
+
* needs to WRITE the index without the write being visible to anyone else.
|
|
74
|
+
*
|
|
75
|
+
* The distinction from {@link withPrivateGitIndex} matters. That one exists
|
|
76
|
+
* so a read-only command's incidental index refreshes do not touch the
|
|
77
|
+
* primary checkout, and it is process-global, non-reentrant, and fail-open,
|
|
78
|
+
* all of which are right for that job. This one serves a caller whose index
|
|
79
|
+
* write is DELIBERATE and whose visibility is the defect: it is per-call, so
|
|
80
|
+
* two concurrent callers cannot collide, and it never depends on an ambient
|
|
81
|
+
* scope having been installed by whichever command happens to be running.
|
|
82
|
+
*
|
|
83
|
+
* The seed is a plain copy, which is safe against a concurrent writer: git
|
|
84
|
+
* writes the index through `index.lock` and an atomic rename, so a reader
|
|
85
|
+
* sees either the old file or the new one, never a torn one. Seeding is
|
|
86
|
+
* REQUIRED rather than merely tidy — an empty index makes a tracked,
|
|
87
|
+
* unmodified file look like a fresh add.
|
|
88
|
+
*
|
|
89
|
+
* @param repoDir - Repository whose index should be shadowed
|
|
90
|
+
* @returns The overlay and its cleanup, or undefined when one could not be
|
|
91
|
+
* minted (a non-git directory, an unreadable index, no writable tmpdir)
|
|
92
|
+
*/
|
|
93
|
+
export declare function mintDisposableGitIndex(repoDir: string): Promise<DisposableGitIndex | undefined>;
|
|
@@ -2,32 +2,30 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Private-index scope for FireForge's READ-ONLY git plumbing.
|
|
4
4
|
*
|
|
5
|
-
* `git status` and `git diff HEAD` are read-only in the sense operators
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `.git/index
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* `git status` and `git diff HEAD` are read-only in the sense operators care
|
|
6
|
+
* about — they never change tracked content — but they are NOT read-only to
|
|
7
|
+
* git: both refresh the index's stat cache and write `.git/index` (through
|
|
8
|
+
* `.git/index.lock`) when a file's stat data has moved. That makes
|
|
9
|
+
* `fireforge verify` / `lint --per-patch` / `typecheck` a second WRITER of
|
|
10
|
+
* the primary `engine/` checkout, even when the command was pointed at a CoW
|
|
11
|
+
* tree clone.
|
|
12
12
|
*
|
|
13
13
|
* The consequence is not cosmetic. A concurrent `fireforge test`
|
|
14
14
|
* fingerprints `engine/` before and after the harness run and refuses a
|
|
15
|
-
* verdict taken across a change (`FAIL reason=inconclusive`). That refusal
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* between lane overlap and inconclusive verdicts, on suites that had
|
|
19
|
-
* actually passed.
|
|
15
|
+
* verdict taken across a change (`FAIL reason=inconclusive`). That refusal is
|
|
16
|
+
* CORRECT and stays; the defect is FireForge's own read-only commands
|
|
17
|
+
* tripping it.
|
|
20
18
|
*
|
|
21
19
|
* The fix is the standard git one: point the plumbing at a PRIVATE index
|
|
22
|
-
* (`GIT_INDEX_FILE`) seeded from the repository's own, in a temp
|
|
23
|
-
*
|
|
24
|
-
* `.git/index
|
|
25
|
-
*
|
|
20
|
+
* (`GIT_INDEX_FILE`) seeded from the repository's own, in a temp directory.
|
|
21
|
+
* Refreshes land there and are thrown away; the primary `.git/index` — and
|
|
22
|
+
* `.git/index.lock`, which is what makes a concurrent `git status` fail
|
|
23
|
+
* outright rather than merely churn — is never touched.
|
|
26
24
|
*
|
|
27
25
|
* Fail-open by design: if the git dir or the index cannot be resolved or
|
|
28
|
-
* copied, the scope
|
|
29
|
-
*
|
|
30
|
-
*
|
|
26
|
+
* copied, the scope does not activate and the commands behave exactly as
|
|
27
|
+
* before. A read-only command must not start failing because an optimisation
|
|
28
|
+
* could not be set up.
|
|
31
29
|
*
|
|
32
30
|
* The scope is process-global and non-reentrant on purpose: FireForge
|
|
33
31
|
* commands are one-shot CLI invocations, and nesting two different private
|
|
@@ -106,6 +104,56 @@ export async function withPrivateGitIndex(repoDir, operation) {
|
|
|
106
104
|
const gitDir = await resolveGitDir(repoDir);
|
|
107
105
|
if (gitDir === undefined)
|
|
108
106
|
return operation();
|
|
107
|
+
const minted = await mintPrivateIndex(gitDir);
|
|
108
|
+
if (minted === undefined)
|
|
109
|
+
return operation();
|
|
110
|
+
activeScope = { repoDir: resolve(repoDir), indexFile: minted.indexFile };
|
|
111
|
+
verbose(`Private git index active for ${repoDir} (${minted.indexFile}).`);
|
|
112
|
+
try {
|
|
113
|
+
return await operation();
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
activeScope = undefined;
|
|
117
|
+
await minted.dispose();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Mints a private index seeded from `repoDir`'s own, for a caller that
|
|
122
|
+
* needs to WRITE the index without the write being visible to anyone else.
|
|
123
|
+
*
|
|
124
|
+
* The distinction from {@link withPrivateGitIndex} matters. That one exists
|
|
125
|
+
* so a read-only command's incidental index refreshes do not touch the
|
|
126
|
+
* primary checkout, and it is process-global, non-reentrant, and fail-open,
|
|
127
|
+
* all of which are right for that job. This one serves a caller whose index
|
|
128
|
+
* write is DELIBERATE and whose visibility is the defect: it is per-call, so
|
|
129
|
+
* two concurrent callers cannot collide, and it never depends on an ambient
|
|
130
|
+
* scope having been installed by whichever command happens to be running.
|
|
131
|
+
*
|
|
132
|
+
* The seed is a plain copy, which is safe against a concurrent writer: git
|
|
133
|
+
* writes the index through `index.lock` and an atomic rename, so a reader
|
|
134
|
+
* sees either the old file or the new one, never a torn one. Seeding is
|
|
135
|
+
* REQUIRED rather than merely tidy — an empty index makes a tracked,
|
|
136
|
+
* unmodified file look like a fresh add.
|
|
137
|
+
*
|
|
138
|
+
* @param repoDir - Repository whose index should be shadowed
|
|
139
|
+
* @returns The overlay and its cleanup, or undefined when one could not be
|
|
140
|
+
* minted (a non-git directory, an unreadable index, no writable tmpdir)
|
|
141
|
+
*/
|
|
142
|
+
export async function mintDisposableGitIndex(repoDir) {
|
|
143
|
+
const gitDir = await resolveGitDir(repoDir);
|
|
144
|
+
if (gitDir === undefined)
|
|
145
|
+
return undefined;
|
|
146
|
+
const minted = await mintPrivateIndex(gitDir);
|
|
147
|
+
if (minted === undefined)
|
|
148
|
+
return undefined;
|
|
149
|
+
return { env: { GIT_INDEX_FILE: minted.indexFile }, dispose: minted.dispose };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Copies `gitDir`'s index into a fresh temp directory. Returns undefined
|
|
153
|
+
* rather than throwing: every caller has a defined behaviour for "no private
|
|
154
|
+
* index available", and none of them wants an exception from an optimisation.
|
|
155
|
+
*/
|
|
156
|
+
async function mintPrivateIndex(gitDir) {
|
|
109
157
|
let tempDir;
|
|
110
158
|
try {
|
|
111
159
|
tempDir = await mkdtemp(join(tmpdir(), 'fireforge-roindex-'));
|
|
@@ -116,22 +164,18 @@ export async function withPrivateGitIndex(repoDir, operation) {
|
|
|
116
164
|
if (await pathExists(sourceIndex)) {
|
|
117
165
|
await copyFile(sourceIndex, privateIndex);
|
|
118
166
|
}
|
|
119
|
-
|
|
120
|
-
|
|
167
|
+
const dir = tempDir;
|
|
168
|
+
return {
|
|
169
|
+
indexFile: privateIndex,
|
|
170
|
+
dispose: async () => {
|
|
171
|
+
await rm(dir, { recursive: true, force: true });
|
|
172
|
+
},
|
|
173
|
+
};
|
|
121
174
|
}
|
|
122
175
|
catch (error) {
|
|
123
|
-
// Fail-open: an unset-up scope must never fail a read-only command.
|
|
124
176
|
verbose(`Private git index unavailable — ${toError(error).message}`);
|
|
125
|
-
activeScope = undefined;
|
|
126
177
|
if (tempDir !== undefined)
|
|
127
178
|
await rm(tempDir, { recursive: true, force: true });
|
|
128
|
-
return
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
return await operation();
|
|
132
|
-
}
|
|
133
|
-
finally {
|
|
134
|
-
activeScope = undefined;
|
|
135
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
179
|
+
return undefined;
|
|
136
180
|
}
|
|
137
181
|
}
|
|
@@ -22,15 +22,14 @@ export declare function resolveMaxUntrackedFilesPerDir(): number;
|
|
|
22
22
|
* Git status may report "?? dir/" instead of listing each file underneath.
|
|
23
23
|
*
|
|
24
24
|
* Expansion is capped per directory (FIREFORGE_MAX_UNTRACKED_FILES, default
|
|
25
|
-
* 5000) with a warning on overflow.
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* --dry-run` after an interrupted download (unborn HEAD, the entire ~300k
|
|
29
|
-
* file tree untracked) enumerated and printed every file.
|
|
25
|
+
* 5000) with a warning on overflow. Without the cap, `reset --dry-run` after
|
|
26
|
+
* an interrupted download — unborn HEAD, the entire ~300k file tree
|
|
27
|
+
* untracked — enumerates and prints every file.
|
|
30
28
|
*
|
|
31
29
|
* @param repoDir - Repository directory
|
|
32
30
|
* @param entries - Parsed status entries
|
|
33
|
-
* @returns Status entries with untracked directories expanded to individual
|
|
31
|
+
* @returns Status entries with untracked directories expanded to individual
|
|
32
|
+
* files
|
|
34
33
|
*/
|
|
35
34
|
export declare function expandUntrackedDirectoryEntries(repoDir: string, entries: GitStatusEntry[]): Promise<GitStatusEntry[]>;
|
|
36
35
|
/**
|
|
@@ -67,15 +67,14 @@ export function resolveMaxUntrackedFilesPerDir() {
|
|
|
67
67
|
* Git status may report "?? dir/" instead of listing each file underneath.
|
|
68
68
|
*
|
|
69
69
|
* Expansion is capped per directory (FIREFORGE_MAX_UNTRACKED_FILES, default
|
|
70
|
-
* 5000) with a warning on overflow.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* --dry-run` after an interrupted download (unborn HEAD, the entire ~300k
|
|
74
|
-
* file tree untracked) enumerated and printed every file.
|
|
70
|
+
* 5000) with a warning on overflow. Without the cap, `reset --dry-run` after
|
|
71
|
+
* an interrupted download — unborn HEAD, the entire ~300k file tree
|
|
72
|
+
* untracked — enumerates and prints every file.
|
|
75
73
|
*
|
|
76
74
|
* @param repoDir - Repository directory
|
|
77
75
|
* @param entries - Parsed status entries
|
|
78
|
-
* @returns Status entries with untracked directories expanded to individual
|
|
76
|
+
* @returns Status entries with untracked directories expanded to individual
|
|
77
|
+
* files
|
|
79
78
|
*/
|
|
80
79
|
export async function expandUntrackedDirectoryEntries(repoDir, entries) {
|
|
81
80
|
const expanded = [];
|
package/dist/src/core/git.d.ts
CHANGED
|
@@ -50,20 +50,19 @@ export declare function applyPatch(patchPath: string, repoDir: string, options?:
|
|
|
50
50
|
reject?: boolean;
|
|
51
51
|
}): Promise<void>;
|
|
52
52
|
/**
|
|
53
|
-
* Applies a patch idempotently using reverse-forward pattern.
|
|
54
|
-
*
|
|
55
|
-
* then applies it forward.
|
|
53
|
+
* Applies a patch idempotently using reverse-forward pattern. First tries to
|
|
54
|
+
* reverse the patch (in case it is already applied), then applies it forward.
|
|
56
55
|
*
|
|
57
56
|
* @param patchPath - Path to the patch file
|
|
58
57
|
* @param repoDir - Repository directory
|
|
59
58
|
* @param options.reject - Fall back to `git apply --reject`
|
|
60
|
-
* @param options.protectedFiles - Files that must NOT be reset to HEAD by
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
59
|
+
* @param options.protectedFiles - Files that must NOT be reset to HEAD by the
|
|
60
|
+
* recovery step. Callers applying a patch QUEUE pass the files already
|
|
61
|
+
* touched by previously applied patches in the same run: two overlapping
|
|
62
|
+
* patches (an `--allow-overlap` queue) share files, and a blanket
|
|
63
|
+
* `checkout HEAD` would wipe the earlier patch's changes from the shared
|
|
64
|
+
* file before applying the later one, leaving the engine in a hybrid state
|
|
65
|
+
* the summary never describes.
|
|
67
66
|
*/
|
|
68
67
|
export declare function applyPatchIdempotent(patchPath: string, repoDir: string, options?: {
|
|
69
68
|
reject?: boolean;
|
package/dist/src/core/git.js
CHANGED
|
@@ -9,7 +9,7 @@ import { pathExists, pathExistsStrict, removeFile } from '../utils/fs.js';
|
|
|
9
9
|
import { verbose } from '../utils/logger.js';
|
|
10
10
|
import { exec } from '../utils/process.js';
|
|
11
11
|
import { ensureFirefoxIgnorefileCompatibility } from './firefox-ignorefile.js';
|
|
12
|
-
import { chunkPathspecs, configureGitPerformance, ensureGit, git, GIT_ADD_CHUNK_TIMEOUT_ENV_VAR, GIT_ADD_CHUNK_TIMEOUT_MS, GIT_ADD_TIMEOUT_MS, } from './git-base.js';
|
|
12
|
+
import { chunkPathspecs, configureGitLineEndings, configureGitPerformance, ensureGit, git, GIT_ADD_CHUNK_TIMEOUT_ENV_VAR, GIT_ADD_CHUNK_TIMEOUT_MS, GIT_ADD_TIMEOUT_MS, } from './git-base.js';
|
|
13
13
|
import { getWorkingTreeStatus } from './git-status.js';
|
|
14
14
|
// ── Functions that remain in this file ──
|
|
15
15
|
/**
|
|
@@ -40,12 +40,10 @@ export async function ensureOriginRemote(dir) {
|
|
|
40
40
|
// ── Large-tree staging helpers ──
|
|
41
41
|
const GIT_ADD_ENV = { GIT_INDEX_THREADS: '0' };
|
|
42
42
|
/**
|
|
43
|
-
* Returns true when the error looks like a process killed by the spawn
|
|
44
|
-
* (SIGTERM → exit code 143) OR an AbortError raised by
|
|
45
|
-
* `AbortSignal.timeout
|
|
46
|
-
* the
|
|
47
|
-
* rejects with an AbortError when the signal fires, so the timeout
|
|
48
|
-
* detection here needs to recognise that shape too.
|
|
43
|
+
* Returns true when the error looks like a process killed by the spawn
|
|
44
|
+
* timeout (SIGTERM → exit code 143) OR an AbortError raised by
|
|
45
|
+
* `AbortSignal.timeout` — Node's `child_process` layer rejects with an
|
|
46
|
+
* AbortError when the signal fires, so both shapes have to be recognised.
|
|
49
47
|
*/
|
|
50
48
|
function isTimeoutError(error) {
|
|
51
49
|
// `exec` now rejects with a typed ExecTimeoutError when its `timeout`
|
|
@@ -74,23 +72,20 @@ async function cleanupIndexLock(dir) {
|
|
|
74
72
|
}
|
|
75
73
|
}
|
|
76
74
|
/**
|
|
77
|
-
* Returns true when {@link relativePath} is ignored by `.gitignore` (or
|
|
78
|
-
*
|
|
79
|
-
* core.excludesFile). Used by the chunked staging fallback to skip
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
75
|
+
* Returns true when {@link relativePath} is ignored by `.gitignore` (or any
|
|
76
|
+
* other exclusion mechanism git considers, e.g. `.git/info/exclude`,
|
|
77
|
+
* core.excludesFile). Used by the chunked staging fallback to skip entries
|
|
78
|
+
* that would otherwise fail `git add -- <path>` with the fatal "The
|
|
79
|
+
* following paths are ignored by one of your .gitignore files" error — a
|
|
80
|
+
* state the monolithic `git add -A` path silently handles. A Firefox
|
|
81
|
+
* checkout's top-level `.vscode/` is the common case: without this, the
|
|
82
|
+
* chunked invocation aborts the whole fallback and turns a recoverable
|
|
83
|
+
* monolithic timeout into a hard setup failure.
|
|
83
84
|
*
|
|
84
|
-
*
|
|
85
|
-
* is
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* 2026-04-26 eval Finding 4: a Firefox checkout's top-level `.vscode/`
|
|
90
|
-
* is gitignored by the source tree's own `.gitignore`. Pre-fix, the
|
|
91
|
-
* chunked `git add -- .vscode` invocation aborted the entire fallback
|
|
92
|
-
* and turned a recoverable monolithic timeout into a hard setup
|
|
93
|
-
* failure that required `fireforge download --force`.
|
|
85
|
+
* `git check-ignore -q -- <path>` exits 0 when the path is ignored, 1 when
|
|
86
|
+
* it is not, and >=128 on real failures. Anything other than 0/1 is treated
|
|
87
|
+
* as "unknown" and conservatively returns false, so the chunk runs and any
|
|
88
|
+
* real underlying failure surfaces normally.
|
|
94
89
|
*/
|
|
95
90
|
async function isPathIgnored(dir, relativePath) {
|
|
96
91
|
const result = await exec('git', ['check-ignore', '-q', '--', relativePath], { cwd: dir });
|
|
@@ -103,15 +98,14 @@ async function isPathIgnored(dir, relativePath) {
|
|
|
103
98
|
return false;
|
|
104
99
|
}
|
|
105
100
|
/**
|
|
106
|
-
* Stages every file by walking top-level directories one at a time.
|
|
107
|
-
*
|
|
108
|
-
*
|
|
101
|
+
* Stages every file by walking top-level directories one at a time. This
|
|
102
|
+
* avoids a single monolithic `git add -A` that may time out on very large
|
|
103
|
+
* (~300 K file) trees like Firefox.
|
|
109
104
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* operator can extend the budget and re-run.
|
|
105
|
+
* A chunked pass that hits its own timeout raises a typed
|
|
106
|
+
* {@link GitIndexingTimeoutError} rather than an opaque `AbortError: The
|
|
107
|
+
* operation was aborted`; the typed error carries the environment-variable
|
|
108
|
+
* override so the operator can extend the budget and re-run.
|
|
115
109
|
*/
|
|
116
110
|
async function stageAllFilesChunked(dir, scan, options = {}) {
|
|
117
111
|
const { directories, topLevelFiles: topLevelCandidates } = scan;
|
|
@@ -160,10 +154,9 @@ async function stageAllFilesChunked(dir, scan, options = {}) {
|
|
|
160
154
|
/**
|
|
161
155
|
* Interval between heartbeat progress messages during the monolithic
|
|
162
156
|
* `git add -A`. On a fresh ~600 MB Firefox tree the monolithic add runs
|
|
163
|
-
* 60–120 seconds, during which git emits nothing to stdout/stderr. Without
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* SIGINT'd mid-way assuming the process had stalled.
|
|
157
|
+
* 60–120 seconds, during which git emits nothing to stdout/stderr. Without a
|
|
158
|
+
* heartbeat the CLI spinner stays pinned on "Indexing Firefox source …" for
|
|
159
|
+
* the full window and looks hung, which invites a SIGINT mid-way.
|
|
167
160
|
*/
|
|
168
161
|
const GIT_ADD_HEARTBEAT_MS = 15_000;
|
|
169
162
|
const GIT_COMMIT_HEARTBEAT_MS = 15_000;
|
|
@@ -191,16 +184,12 @@ export async function stageAllFiles(dir, options = {}) {
|
|
|
191
184
|
reportProgress?.('Scanning Firefox source tree before indexing...');
|
|
192
185
|
const scan = await scanTopLevelSource(dir);
|
|
193
186
|
reportProgress?.(`Source scan complete: ${scan.directories.length} top-level director${scan.directories.length === 1 ? 'y' : 'ies'}, ${scan.topLevelFiles.length} top-level file${scan.topLevelFiles.length === 1 ? '' : 's'}`);
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
// elapsed for the whole `stageAllFiles` invocation
|
|
197
|
-
// monolithic timeout
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
// to tell where the monolithic attempt ended and the chunked pass
|
|
201
|
-
// began. The heartbeat now tracks a per-phase start timestamp and
|
|
202
|
-
// labels each tick with the phase, so the chunked pass reports its
|
|
203
|
-
// own elapsed window and the monolithic→chunked handoff is visible.
|
|
187
|
+
// The heartbeat tracks a PER-PHASE start timestamp and labels each tick
|
|
188
|
+
// with the phase. A single start time set at function entry reports
|
|
189
|
+
// cumulative elapsed for the whole `stageAllFiles` invocation, so after a
|
|
190
|
+
// monolithic timeout the chunked-phase ticks name numbers that already
|
|
191
|
+
// include the entire monolithic budget, with no way to tell from the log
|
|
192
|
+
// where one attempt ended and the next began.
|
|
204
193
|
let phase = 'monolithic';
|
|
205
194
|
let phaseStartedAt = Date.now();
|
|
206
195
|
const heartbeatTimer = reportProgress
|
|
@@ -223,13 +212,10 @@ export async function stageAllFiles(dir, options = {}) {
|
|
|
223
212
|
if (!isTimeoutError(error)) {
|
|
224
213
|
throw await maybeWrapIndexLockError(dir, error);
|
|
225
214
|
}
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
// and
|
|
230
|
-
// the chunked pass is starting. This was the missing signal in
|
|
231
|
-
// the eval log where the heartbeat went quiet for ~600s between
|
|
232
|
-
// the monolithic timeout and the chunked-pass failure.
|
|
215
|
+
// Emit a loud, one-line banner so non-TTY log scrapers and TTY
|
|
216
|
+
// operators both see that the monolithic attempt lost and the chunked
|
|
217
|
+
// pass is starting. Without it the fallback transition is invisible
|
|
218
|
+
// and the heartbeat simply goes quiet for minutes.
|
|
233
219
|
options.onProgress?.(`Monolithic git add reached the ${Math.round(timeout / 1000)}s timeout; falling back to chunked staging. This pass may take several more minutes on a large tree.`);
|
|
234
220
|
}
|
|
235
221
|
// The killed process may have left an index lock
|
|
@@ -292,6 +278,7 @@ export async function initRepository(dir, branchName = 'main', options = {}) {
|
|
|
292
278
|
// Enable performance settings for large trees
|
|
293
279
|
reportProgress('Configuring git performance settings...');
|
|
294
280
|
await configureGitPerformance(dir);
|
|
281
|
+
await configureGitLineEndings(dir);
|
|
295
282
|
// Add a local-only origin remote so that Firefox's mach bootstrap and
|
|
296
283
|
// build scripts (which shell out to `git remote get-url origin`) don't
|
|
297
284
|
// fail. Nothing is ever fetched from or pushed to this remote.
|
|
@@ -332,6 +319,7 @@ export async function resumeRepository(dir, options = {}) {
|
|
|
332
319
|
// Ensure performance settings are in place (may not have been set)
|
|
333
320
|
reportProgress('Configuring git performance settings...');
|
|
334
321
|
await configureGitPerformance(dir);
|
|
322
|
+
await configureGitLineEndings(dir);
|
|
335
323
|
// Clean up any stale index lock left by the killed process
|
|
336
324
|
await cleanupIndexLock(dir);
|
|
337
325
|
// Ensure origin remote exists (may have been added before the interrupt)
|
|
@@ -413,20 +401,19 @@ export async function applyPatch(patchPath, repoDir, options = {}) {
|
|
|
413
401
|
}
|
|
414
402
|
}
|
|
415
403
|
/**
|
|
416
|
-
* Applies a patch idempotently using reverse-forward pattern.
|
|
417
|
-
*
|
|
418
|
-
* then applies it forward.
|
|
404
|
+
* Applies a patch idempotently using reverse-forward pattern. First tries to
|
|
405
|
+
* reverse the patch (in case it is already applied), then applies it forward.
|
|
419
406
|
*
|
|
420
407
|
* @param patchPath - Path to the patch file
|
|
421
408
|
* @param repoDir - Repository directory
|
|
422
409
|
* @param options.reject - Fall back to `git apply --reject`
|
|
423
|
-
* @param options.protectedFiles - Files that must NOT be reset to HEAD by
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
410
|
+
* @param options.protectedFiles - Files that must NOT be reset to HEAD by the
|
|
411
|
+
* recovery step. Callers applying a patch QUEUE pass the files already
|
|
412
|
+
* touched by previously applied patches in the same run: two overlapping
|
|
413
|
+
* patches (an `--allow-overlap` queue) share files, and a blanket
|
|
414
|
+
* `checkout HEAD` would wipe the earlier patch's changes from the shared
|
|
415
|
+
* file before applying the later one, leaving the engine in a hybrid state
|
|
416
|
+
* the summary never describes.
|
|
430
417
|
*/
|
|
431
418
|
export async function applyPatchIdempotent(patchPath, repoDir, options = {}) {
|
|
432
419
|
await ensureGit();
|
|
@@ -452,16 +439,15 @@ export async function applyPatchIdempotent(patchPath, repoDir, options = {}) {
|
|
|
452
439
|
await applyPatch(patchPath, repoDir, options);
|
|
453
440
|
}
|
|
454
441
|
/**
|
|
455
|
-
* Restores `files` to their HEAD state, deleting files the patch would
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
* that
|
|
459
|
-
*
|
|
442
|
+
* Restores `files` to their HEAD state, deleting files the patch would CREATE
|
|
443
|
+
* (present on disk from a partial apply but absent in HEAD — for those,
|
|
444
|
+
* `git checkout HEAD --` fails, and ignoring that failure leaves stray files
|
|
445
|
+
* that make the subsequent forward apply die with "already exists" and no
|
|
446
|
+
* hint why).
|
|
460
447
|
*
|
|
461
|
-
* Every git invocation is chunked via {@link chunkPathspecs} so a very
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
* step exists to prevent.
|
|
448
|
+
* Every git invocation is chunked via {@link chunkPathspecs} so a very large
|
|
449
|
+
* patch cannot hit `E2BIG`, and every exit code is checked — a silent failed
|
|
450
|
+
* restore is the confusing state this recovery step exists to prevent.
|
|
465
451
|
*/
|
|
466
452
|
async function restoreFilesToHead(repoDir, patchPath, files) {
|
|
467
453
|
// Partition into tracked-in-HEAD (restore via checkout) and absent-in-HEAD
|
|
@@ -23,21 +23,19 @@ export declare function getLicenseHeader(license: ProjectLicense, style: Comment
|
|
|
23
23
|
*
|
|
24
24
|
* For `js` files, MPL-2.0 is also accepted in the upstream Mozilla block-
|
|
25
25
|
* comment form (`/* ... *\/`) used by the Firefox source tree, not just the
|
|
26
|
-
* `// ` line-comment form `getLicenseHeader` emits
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* standard MPL header — operators were forced to `--skip-lint` over a real
|
|
30
|
-
* false positive.
|
|
26
|
+
* `// ` line-comment form `getLicenseHeader` emits — otherwise a new JS file
|
|
27
|
+
* copied from upstream Firefox hits `missing-license-header` even with a
|
|
28
|
+
* verbatim standard MPL header.
|
|
31
29
|
*
|
|
32
30
|
* Editor-directive block comments (`/* -*- ... -*- *\/`, `/* vim: ... *\/`)
|
|
33
|
-
* leading the file are tolerated
|
|
34
|
-
*
|
|
35
|
-
*
|
|
31
|
+
* leading the file are tolerated: Mozilla's canonical layout puts those on
|
|
32
|
+
* lines 1–2 with the MPL header on lines 3+, which a raw `startsWith` check
|
|
33
|
+
* would miss.
|
|
36
34
|
*
|
|
37
|
-
* The MPL-2.0 header is additionally matched on normalized whitespace
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* The MPL-2.0 header is additionally matched on normalized whitespace (see
|
|
36
|
+
* {@link normalizeCommentHead}) so upstream files using the older Mozilla
|
|
37
|
+
* wrap — breaking after "file," instead of "with this" — are accepted too;
|
|
38
|
+
* only the wrap position differs, never the wording.
|
|
41
39
|
*
|
|
42
40
|
* @param content - File content to check
|
|
43
41
|
* @param style - Comment syntax of the file
|
|
@@ -46,22 +44,18 @@ export declare function hasAnyLicenseHeader(content: string, style: CommentStyle
|
|
|
46
44
|
/**
|
|
47
45
|
* Returns true if `content` starts with the verbatim upstream Mozilla
|
|
48
46
|
* MPL-2.0 block header (`/* This Source Code Form … *\/`), optionally
|
|
49
|
-
* preceded by editor-directive comments — the exact shape a JS file
|
|
50
|
-
*
|
|
47
|
+
* preceded by editor-directive comments — the exact shape a JS file copied
|
|
48
|
+
* from the Firefox source tree carries.
|
|
51
49
|
*
|
|
52
50
|
* Deliberately independent of the project license: a new JS file that
|
|
53
|
-
* legitimately keeps its upstream MPL block header
|
|
54
|
-
*
|
|
55
|
-
* this acceptance only existed behind a `license === 'MPL-2.0'` gate in
|
|
56
|
-
* patch-lint, making it dead code for every other project license and
|
|
57
|
-
* forcing repo-side audit workarounds.
|
|
51
|
+
* legitimately keeps its upstream MPL block header is valid in an
|
|
52
|
+
* EUPL/GPL/0BSD project too.
|
|
58
53
|
*
|
|
59
54
|
* Matching is wrap-agnostic: after the exact `startsWith` fast path, the
|
|
60
55
|
* leading block comment is compared on normalized whitespace (see
|
|
61
|
-
* {@link normalizeCommentHead}) so the older upstream wrap — breaking
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* still rejects.
|
|
56
|
+
* {@link normalizeCommentHead}) so the older upstream wrap — breaking after
|
|
57
|
+
* "file," instead of "with this", as `ext-browser.js` ships — passes too.
|
|
58
|
+
* Only the line-break position may differ; altered wording still rejects.
|
|
65
59
|
*
|
|
66
60
|
* @param content - File content to check
|
|
67
61
|
*/
|