@hominis/fireforge 0.45.0 → 0.46.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 +409 -446
- package/dist/bin/fireforge.d.ts +1 -1
- package/dist/bin/fireforge.js +21 -15
- package/dist/build-info.json +4 -4
- package/dist/src/cli-usage-error.d.ts +46 -0
- package/dist/src/cli-usage-error.js +81 -0
- package/dist/src/cli.d.ts +7 -2
- package/dist/src/cli.js +47 -47
- package/dist/src/commands/bootstrap-checks.js +2 -1
- package/dist/src/commands/bootstrap.js +3 -4
- package/dist/src/commands/build.js +27 -17
- package/dist/src/commands/config.js +9 -9
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/discard.js +5 -5
- package/dist/src/commands/doctor-check-core.d.ts +4 -10
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-external-toolchains.js +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.d.ts +2 -2
- package/dist/src/commands/doctor-furnace-config-sync.js +20 -20
- package/dist/src/commands/doctor-furnace-jar.d.ts +1 -1
- package/dist/src/commands/doctor-furnace-jar.js +1 -1
- package/dist/src/commands/doctor-furnace.js +22 -22
- package/dist/src/commands/doctor-orphaned-harness.d.ts +10 -17
- package/dist/src/commands/doctor-orphaned-harness.js +14 -23
- package/dist/src/commands/doctor-patch-manifest.d.ts +2 -1
- package/dist/src/commands/doctor-patch-manifest.js +7 -6
- package/dist/src/commands/doctor-post-rebase-audit.js +3 -3
- package/dist/src/commands/doctor-source-pin.d.ts +12 -12
- package/dist/src/commands/doctor-source-pin.js +14 -14
- package/dist/src/commands/doctor-working-tree.d.ts +3 -3
- package/dist/src/commands/doctor-working-tree.js +3 -3
- package/dist/src/commands/doctor.d.ts +3 -1
- package/dist/src/commands/doctor.js +15 -16
- package/dist/src/commands/download.js +50 -37
- package/dist/src/commands/export-all.js +29 -12
- package/dist/src/commands/export-flow.d.ts +5 -5
- package/dist/src/commands/export-flow.js +29 -59
- package/dist/src/commands/export-placement-conflicts.d.ts +3 -3
- package/dist/src/commands/export-placement-conflicts.js +12 -12
- package/dist/src/commands/export-placement-gate.d.ts +2 -2
- package/dist/src/commands/export-placement-gate.js +7 -13
- package/dist/src/commands/export-placement-policy.d.ts +1 -1
- package/dist/src/commands/export-placement-policy.js +4 -6
- package/dist/src/commands/export-shared.d.ts +51 -32
- package/dist/src/commands/export-shared.js +17 -32
- package/dist/src/commands/export.js +14 -5
- package/dist/src/commands/furnace/apply.js +16 -16
- package/dist/src/commands/furnace/authoring-config.d.ts +13 -0
- package/dist/src/commands/furnace/authoring-config.js +19 -0
- package/dist/src/commands/furnace/chrome-doc-remove.d.ts +1 -1
- package/dist/src/commands/furnace/chrome-doc-remove.js +2 -2
- package/dist/src/commands/furnace/chrome-doc-templates.d.ts +14 -14
- package/dist/src/commands/furnace/chrome-doc-templates.js +17 -17
- package/dist/src/commands/furnace/chrome-doc-tests.d.ts +2 -2
- package/dist/src/commands/furnace/chrome-doc-tests.js +4 -4
- package/dist/src/commands/furnace/chrome-doc.d.ts +8 -8
- package/dist/src/commands/furnace/chrome-doc.js +18 -18
- package/dist/src/commands/furnace/create-browser-test.d.ts +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +7 -12
- package/dist/src/commands/furnace/create-dry-run.d.ts +4 -4
- package/dist/src/commands/furnace/create-dry-run.js +6 -9
- package/dist/src/commands/furnace/create-features.d.ts +2 -2
- package/dist/src/commands/furnace/create-features.js +2 -2
- package/dist/src/commands/furnace/create-mochikit.d.ts +4 -4
- package/dist/src/commands/furnace/create-mochikit.js +7 -7
- package/dist/src/commands/furnace/create-templates.d.ts +31 -15
- package/dist/src/commands/furnace/create-templates.js +20 -19
- package/dist/src/commands/furnace/create-xpcshell.d.ts +5 -5
- package/dist/src/commands/furnace/create-xpcshell.js +8 -8
- package/dist/src/commands/furnace/create.d.ts +1 -1
- package/dist/src/commands/furnace/create.js +35 -29
- package/dist/src/commands/furnace/deploy.js +15 -6
- package/dist/src/commands/furnace/diff.js +7 -7
- package/dist/src/commands/furnace/index.js +1 -1
- package/dist/src/commands/furnace/init.js +17 -16
- package/dist/src/commands/furnace/list.js +2 -2
- package/dist/src/commands/furnace/override.d.ts +1 -1
- package/dist/src/commands/furnace/override.js +43 -34
- package/dist/src/commands/furnace/preview.js +17 -17
- package/dist/src/commands/furnace/refresh.js +15 -7
- package/dist/src/commands/furnace/remove-mutations.d.ts +9 -10
- package/dist/src/commands/furnace/remove-mutations.js +19 -19
- package/dist/src/commands/furnace/remove-state.d.ts +1 -1
- package/dist/src/commands/furnace/remove-state.js +1 -1
- package/dist/src/commands/furnace/remove.js +4 -8
- package/dist/src/commands/furnace/rename-browser-test.js +10 -15
- package/dist/src/commands/furnace/rename-xpcshell.d.ts +2 -2
- package/dist/src/commands/furnace/rename-xpcshell.js +3 -3
- package/dist/src/commands/furnace/rename.js +36 -36
- package/dist/src/commands/furnace/scan.js +3 -3
- package/dist/src/commands/furnace/status.js +19 -16
- package/dist/src/commands/furnace/sync.js +6 -6
- package/dist/src/commands/furnace/test-file-name.d.ts +28 -0
- package/dist/src/commands/furnace/test-file-name.js +39 -0
- package/dist/src/commands/furnace/validate.js +11 -12
- package/dist/src/commands/furnace/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +22 -29
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +27 -12
- package/dist/src/commands/lint-per-run-checkjs.d.ts +14 -15
- package/dist/src/commands/lint-per-run-checkjs.js +14 -15
- package/dist/src/commands/lint-report.d.ts +3 -3
- package/dist/src/commands/lint-report.js +4 -4
- package/dist/src/commands/lint.d.ts +5 -4
- package/dist/src/commands/lint.js +36 -36
- package/dist/src/commands/manifest.d.ts +4 -4
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +4 -6
- package/dist/src/commands/patch/compact.d.ts +2 -2
- package/dist/src/commands/patch/compact.js +19 -20
- package/dist/src/commands/patch/delete.d.ts +1 -1
- package/dist/src/commands/patch/delete.js +23 -33
- package/dist/src/commands/patch/entry-projection.d.ts +13 -0
- package/dist/src/commands/patch/entry-projection.js +24 -0
- package/dist/src/commands/patch/lint-ignore.d.ts +3 -12
- package/dist/src/commands/patch/lint-ignore.js +33 -44
- package/dist/src/commands/patch/move-files-create.d.ts +2 -2
- package/dist/src/commands/patch/move-files-create.js +29 -15
- package/dist/src/commands/patch/move-files-into.d.ts +2 -2
- package/dist/src/commands/patch/move-files-into.js +41 -37
- package/dist/src/commands/patch/move-files.js +5 -14
- package/dist/src/commands/patch/patch-context.d.ts +1 -1
- package/dist/src/commands/patch/rename.d.ts +4 -4
- package/dist/src/commands/patch/rename.js +35 -49
- package/dist/src/commands/patch/reorder.js +35 -48
- package/dist/src/commands/patch/split-plan.d.ts +7 -8
- package/dist/src/commands/patch/split-plan.js +10 -13
- package/dist/src/commands/patch/split.d.ts +2 -2
- package/dist/src/commands/patch/split.js +50 -48
- package/dist/src/commands/patch/staged-dependency-validate.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency-validate.js +3 -3
- package/dist/src/commands/patch/staged-dependency.d.ts +1 -1
- package/dist/src/commands/patch/staged-dependency.js +22 -28
- package/dist/src/commands/patch/tier.d.ts +2 -2
- package/dist/src/commands/patch/tier.js +20 -30
- package/dist/src/commands/patch-rename-map.d.ts +19 -0
- package/dist/src/commands/patch-rename-map.js +36 -0
- package/dist/src/commands/pending-resolution.d.ts +15 -0
- package/dist/src/commands/pending-resolution.js +25 -0
- package/dist/src/commands/re-export-adjacent.d.ts +25 -3
- package/dist/src/commands/re-export-adjacent.js +40 -24
- package/dist/src/commands/re-export-bulk-scan.d.ts +3 -3
- package/dist/src/commands/re-export-bulk-scan.js +23 -27
- package/dist/src/commands/re-export-drift.d.ts +10 -10
- package/dist/src/commands/re-export-drift.js +33 -33
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +52 -44
- package/dist/src/commands/re-export-lint.d.ts +29 -30
- package/dist/src/commands/re-export-lint.js +36 -29
- package/dist/src/commands/re-export-options.d.ts +1 -1
- package/dist/src/commands/re-export-options.js +1 -1
- package/dist/src/commands/re-export-register.d.ts +1 -1
- package/dist/src/commands/re-export-register.js +1 -1
- package/dist/src/commands/re-export-scan.d.ts +1 -1
- package/dist/src/commands/re-export-scan.js +12 -9
- package/dist/src/commands/re-export-single.d.ts +23 -4
- package/dist/src/commands/re-export-single.js +39 -31
- package/dist/src/commands/re-export.js +35 -17
- package/dist/src/commands/rebase/abort.js +9 -14
- package/dist/src/commands/rebase/continue.js +20 -19
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +5 -5
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +20 -24
- package/dist/src/commands/register.js +5 -5
- package/dist/src/commands/reset.js +1 -1
- package/dist/src/commands/resolve.d.ts +2 -2
- package/dist/src/commands/resolve.js +21 -13
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +38 -51
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +20 -20
- package/dist/src/commands/setup.js +4 -10
- package/dist/src/commands/source.js +9 -2
- package/dist/src/commands/status-check.d.ts +3 -3
- package/dist/src/commands/status-check.js +6 -6
- package/dist/src/commands/status-json.d.ts +14 -13
- package/dist/src/commands/status-json.js +9 -8
- package/dist/src/commands/status-output.d.ts +3 -3
- package/dist/src/commands/status-output.js +5 -5
- package/dist/src/commands/status-ownership.d.ts +3 -3
- package/dist/src/commands/status-ownership.js +3 -3
- package/dist/src/commands/status.js +25 -26
- package/dist/src/commands/test-build-phase.d.ts +3 -3
- package/dist/src/commands/test-build-phase.js +48 -24
- package/dist/src/commands/test-diagnose.d.ts +1 -1
- package/dist/src/commands/test-diagnose.js +20 -20
- package/dist/src/commands/test-modes.d.ts +4 -4
- package/dist/src/commands/test-modes.js +4 -5
- package/dist/src/commands/test-register.js +5 -3
- package/dist/src/commands/test-run.d.ts +11 -11
- package/dist/src/commands/test-run.js +40 -33
- package/dist/src/commands/test-stale-gate.d.ts +12 -12
- package/dist/src/commands/test-stale-gate.js +17 -17
- package/dist/src/commands/test-verdict.d.ts +19 -5
- package/dist/src/commands/test-verdict.js +26 -11
- package/dist/src/commands/test.d.ts +3 -3
- package/dist/src/commands/test.js +73 -36
- package/dist/src/commands/token-coverage.js +3 -3
- package/dist/src/commands/token-list.d.ts +26 -0
- package/dist/src/commands/token-list.js +153 -0
- package/dist/src/commands/token.js +26 -10
- package/dist/src/commands/tree.js +26 -21
- package/dist/src/commands/typecheck.d.ts +6 -6
- package/dist/src/commands/typecheck.js +16 -16
- package/dist/src/commands/verify.d.ts +3 -3
- package/dist/src/commands/verify.js +10 -10
- package/dist/src/commands/watch.js +11 -11
- package/dist/src/commands/wire.js +17 -16
- package/dist/src/core/ast-utils.d.ts +7 -7
- package/dist/src/core/ast-utils.js +8 -8
- package/dist/src/core/branding.d.ts +5 -12
- package/dist/src/core/branding.js +6 -5
- package/dist/src/core/browser-wire.d.ts +1 -1
- package/dist/src/core/browser-wire.js +10 -7
- package/dist/src/core/build-audit-platform.d.ts +32 -3
- package/dist/src/core/build-audit-platform.js +153 -13
- package/dist/src/core/build-audit-registration.d.ts +5 -5
- package/dist/src/core/build-audit-registration.js +10 -9
- package/dist/src/core/build-audit-resolve.d.ts +5 -5
- package/dist/src/core/build-audit-resolve.js +6 -6
- package/dist/src/core/build-audit-skip.d.ts +57 -0
- package/dist/src/core/build-audit-skip.js +112 -0
- package/dist/src/core/build-audit-transforms.d.ts +2 -2
- package/dist/src/core/build-audit-transforms.js +3 -3
- package/dist/src/core/build-audit.d.ts +21 -8
- package/dist/src/core/build-audit.js +142 -40
- package/dist/src/core/build-baseline-types.d.ts +19 -18
- package/dist/src/core/build-baseline-types.js +1 -1
- package/dist/src/core/build-baseline.d.ts +48 -31
- package/dist/src/core/build-baseline.js +20 -43
- package/dist/src/core/build-jar-escalation.d.ts +8 -8
- package/dist/src/core/build-jar-escalation.js +18 -17
- package/dist/src/core/build-overwrite-guard.d.ts +4 -4
- package/dist/src/core/build-overwrite-guard.js +14 -14
- package/dist/src/core/build-prepare.d.ts +4 -12
- package/dist/src/core/build-prepare.js +22 -26
- package/dist/src/core/config-mutate.js +4 -4
- package/dist/src/core/config-paths.d.ts +2 -6
- package/dist/src/core/config-paths.js +4 -2
- package/dist/src/core/config-state.d.ts +0 -6
- package/dist/src/core/config-state.js +3 -21
- package/dist/src/core/config-validate-build-audit.d.ts +8 -0
- package/dist/src/core/config-validate-build-audit.js +80 -0
- package/dist/src/core/config-validate-file-size.d.ts +1 -1
- package/dist/src/core/config-validate-file-size.js +3 -3
- package/dist/src/core/config-validate-patch-policy.d.ts +2 -2
- package/dist/src/core/config-validate-patch-policy.js +3 -3
- package/dist/src/core/config-validate-test-toolchains.d.ts +2 -2
- package/dist/src/core/config-validate-test-toolchains.js +4 -5
- package/dist/src/core/config-validate.js +22 -12
- package/dist/src/core/config.d.ts +12 -12
- package/dist/src/core/config.js +21 -25
- package/dist/src/core/coverage-extend.d.ts +16 -16
- package/dist/src/core/coverage-extend.js +20 -20
- package/dist/src/core/destructive.d.ts +14 -14
- package/dist/src/core/destructive.js +9 -9
- package/dist/src/core/diff-hunks.d.ts +2 -2
- package/dist/src/core/diff-hunks.js +7 -7
- package/dist/src/core/discard-baseline.d.ts +10 -10
- package/dist/src/core/discard-baseline.js +22 -23
- package/dist/src/core/display-state.d.ts +11 -11
- package/dist/src/core/display-state.js +12 -12
- package/dist/src/core/engine-changes.d.ts +2 -2
- package/dist/src/core/engine-changes.js +2 -2
- package/dist/src/core/engine-precondition.d.ts +5 -13
- package/dist/src/core/engine-precondition.js +5 -10
- package/dist/src/core/engine-session-lock.d.ts +18 -18
- package/dist/src/core/engine-session-lock.js +50 -54
- package/dist/src/core/export-moved-code-shape.d.ts +7 -7
- package/dist/src/core/export-moved-code-shape.js +10 -10
- package/dist/src/core/file-lock-owner.d.ts +103 -0
- package/dist/src/core/file-lock-owner.js +259 -0
- package/dist/src/core/file-lock.d.ts +14 -19
- package/dist/src/core/file-lock.js +90 -128
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +61 -36
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +38 -22
- package/dist/src/core/firefox-extract.d.ts +8 -7
- package/dist/src/core/firefox-extract.js +45 -27
- package/dist/src/core/firefox.d.ts +34 -36
- package/dist/src/core/firefox.js +13 -44
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +2 -8
- package/dist/src/core/furnace-apply-ftl.d.ts +5 -5
- package/dist/src/core/furnace-apply-ftl.js +8 -8
- package/dist/src/core/furnace-apply-helpers.d.ts +9 -20
- package/dist/src/core/furnace-apply-helpers.js +28 -39
- package/dist/src/core/furnace-apply-output.js +1 -1
- package/dist/src/core/furnace-apply-overwrite-warn.d.ts +9 -9
- package/dist/src/core/furnace-apply-overwrite-warn.js +13 -11
- package/dist/src/core/furnace-apply-undeploy-actions.d.ts +1 -1
- package/dist/src/core/furnace-apply-undeploy-actions.js +1 -1
- package/dist/src/core/furnace-apply.d.ts +4 -4
- package/dist/src/core/furnace-apply.js +50 -29
- package/dist/src/core/furnace-checksum-utils.d.ts +5 -5
- package/dist/src/core/furnace-checksum-utils.js +5 -5
- package/dist/src/core/furnace-config-custom.d.ts +1 -1
- package/dist/src/core/furnace-config-custom.js +2 -2
- package/dist/src/core/furnace-config-order.js +1 -1
- package/dist/src/core/furnace-config-tokens.d.ts +3 -3
- package/dist/src/core/furnace-config-tokens.js +3 -3
- package/dist/src/core/furnace-config-validate.js +2 -2
- package/dist/src/core/furnace-config.d.ts +5 -5
- package/dist/src/core/furnace-config.js +40 -53
- package/dist/src/core/furnace-constants.d.ts +6 -6
- package/dist/src/core/furnace-constants.js +9 -8
- package/dist/src/core/furnace-css-fragments.d.ts +6 -6
- package/dist/src/core/furnace-css-fragments.js +11 -11
- package/dist/src/core/furnace-dir-entry.d.ts +20 -0
- package/dist/src/core/furnace-dir-entry.js +21 -0
- package/dist/src/core/furnace-jsconfig.d.ts +7 -7
- package/dist/src/core/furnace-jsconfig.js +22 -20
- package/dist/src/core/furnace-operation.d.ts +22 -19
- package/dist/src/core/furnace-operation.js +38 -34
- package/dist/src/core/furnace-precondition.d.ts +10 -10
- package/dist/src/core/furnace-precondition.js +8 -8
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +5 -8
- package/dist/src/core/furnace-registration-ast.d.ts +2 -3
- package/dist/src/core/furnace-registration-ast.js +9 -12
- package/dist/src/core/furnace-registration-remove.d.ts +4 -4
- package/dist/src/core/furnace-registration-remove.js +6 -6
- package/dist/src/core/furnace-registration-validate.d.ts +2 -2
- package/dist/src/core/furnace-registration-validate.js +2 -2
- package/dist/src/core/furnace-registration.d.ts +7 -6
- package/dist/src/core/furnace-registration.js +29 -36
- package/dist/src/core/furnace-rollback.d.ts +1 -1
- package/dist/src/core/furnace-rollback.js +5 -5
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-stale-export.d.ts +17 -16
- package/dist/src/core/furnace-stale-export.js +16 -15
- package/dist/src/core/furnace-staleness.d.ts +2 -2
- package/dist/src/core/furnace-staleness.js +2 -2
- package/dist/src/core/furnace-state-persist.d.ts +12 -12
- package/dist/src/core/furnace-state-persist.js +10 -10
- package/dist/src/core/furnace-step-errors.d.ts +6 -6
- package/dist/src/core/furnace-step-errors.js +6 -6
- package/dist/src/core/furnace-validate-accessibility.js +14 -14
- package/dist/src/core/furnace-validate-compatibility.js +9 -9
- package/dist/src/core/furnace-validate-registration.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +18 -20
- package/dist/src/core/furnace-validate-structure.d.ts +1 -1
- package/dist/src/core/furnace-validate-structure.js +4 -4
- package/dist/src/core/furnace-validate.js +9 -9
- package/dist/src/core/furnace-version-drift.d.ts +5 -5
- package/dist/src/core/furnace-version-drift.js +5 -5
- package/dist/src/core/git-base.d.ts +6 -4
- package/dist/src/core/git-base.js +29 -7
- package/dist/src/core/git-diff-new-file.d.ts +40 -0
- package/dist/src/core/git-diff-new-file.js +119 -0
- package/dist/src/core/git-diff.d.ts +13 -13
- package/dist/src/core/git-diff.js +121 -189
- package/dist/src/core/git-file-ops.d.ts +6 -13
- package/dist/src/core/git-file-ops.js +11 -35
- package/dist/src/core/git-readonly-index.d.ts +12 -14
- package/dist/src/core/git-readonly-index.js +12 -16
- package/dist/src/core/git-status.d.ts +9 -2
- package/dist/src/core/git-status.js +23 -11
- package/dist/src/core/git.d.ts +3 -9
- package/dist/src/core/git.js +28 -57
- package/dist/src/core/harness-orphans.d.ts +17 -17
- package/dist/src/core/harness-orphans.js +28 -27
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/license-headers.d.ts +19 -18
- package/dist/src/core/license-headers.js +29 -28
- package/dist/src/core/mach-build-artifacts.d.ts +21 -21
- package/dist/src/core/mach-build-artifacts.js +23 -23
- package/dist/src/core/mach-error-hints.d.ts +5 -10
- package/dist/src/core/mach-error-hints.js +14 -14
- package/dist/src/core/mach-known-noise-filter.d.ts +42 -38
- package/dist/src/core/mach-known-noise-filter.js +57 -56
- package/dist/src/core/mach-mozconfig.d.ts +6 -6
- package/dist/src/core/mach-mozconfig.js +17 -16
- package/dist/src/core/mach-python.d.ts +3 -0
- package/dist/src/core/mach-python.js +13 -7
- package/dist/src/core/mach-resource-shim.d.ts +24 -12
- package/dist/src/core/mach-resource-shim.js +124 -21
- package/dist/src/core/mach.d.ts +59 -73
- package/dist/src/core/mach.js +47 -115
- package/dist/src/core/marionette-port.d.ts +15 -30
- package/dist/src/core/marionette-port.js +46 -89
- package/dist/src/core/marionette-preflight.d.ts +6 -6
- package/dist/src/core/marionette-preflight.js +32 -50
- package/dist/src/core/markdown-table.d.ts +9 -9
- package/dist/src/core/markdown-table.js +14 -14
- package/dist/src/core/mochitest-server-port.d.ts +8 -8
- package/dist/src/core/mochitest-server-port.js +17 -17
- package/dist/src/core/module-resolution-preflight.d.ts +8 -8
- package/dist/src/core/module-resolution-preflight.js +11 -11
- package/dist/src/core/moz-manifest-helpers.d.ts +7 -7
- package/dist/src/core/moz-manifest-helpers.js +7 -7
- package/dist/src/core/moz-manifest-register.d.ts +1 -1
- package/dist/src/core/moz-manifest-register.js +2 -2
- package/dist/src/core/moz-manifest-rules.js +46 -42
- package/dist/src/core/moz-manifest-tokenizers.js +1 -1
- package/dist/src/core/ownership-table.d.ts +5 -5
- package/dist/src/core/ownership-table.js +7 -7
- package/dist/src/core/parser-fallback.d.ts +3 -3
- package/dist/src/core/parser-fallback.js +3 -3
- package/dist/src/core/patch-apply-fuzz.d.ts +5 -5
- package/dist/src/core/patch-apply-fuzz.js +13 -13
- package/dist/src/core/patch-apply.d.ts +13 -14
- package/dist/src/core/patch-apply.js +36 -42
- package/dist/src/core/patch-export-coverage.d.ts +0 -9
- package/dist/src/core/patch-export-coverage.js +1 -30
- package/dist/src/core/patch-export-update.d.ts +21 -4
- package/dist/src/core/patch-export-update.js +7 -6
- package/dist/src/core/patch-export.d.ts +20 -30
- package/dist/src/core/patch-export.js +55 -77
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-identifier-suggest.d.ts +1 -1
- package/dist/src/core/patch-identifier-suggest.js +4 -4
- package/dist/src/core/patch-lint-binary.d.ts +12 -18
- package/dist/src/core/patch-lint-cache.d.ts +18 -2
- package/dist/src/core/patch-lint-cache.js +16 -19
- package/dist/src/core/patch-lint-checkjs.d.ts +55 -38
- package/dist/src/core/patch-lint-checkjs.js +78 -64
- package/dist/src/core/patch-lint-chrome-jsdoc.d.ts +8 -9
- package/dist/src/core/patch-lint-chrome-jsdoc.js +10 -11
- package/dist/src/core/patch-lint-creators.d.ts +5 -9
- package/dist/src/core/patch-lint-creators.js +3 -3
- package/dist/src/core/patch-lint-cross.d.ts +27 -19
- package/dist/src/core/patch-lint-cross.js +67 -110
- package/dist/src/core/patch-lint-css.d.ts +1 -1
- package/dist/src/core/patch-lint-css.js +15 -11
- package/dist/src/core/patch-lint-diff-tag.d.ts +5 -5
- package/dist/src/core/patch-lint-diff-tag.js +5 -5
- package/dist/src/core/patch-lint-diff.d.ts +4 -4
- package/dist/src/core/patch-lint-diff.js +4 -4
- package/dist/src/core/patch-lint-file-size.d.ts +3 -3
- package/dist/src/core/patch-lint-file-size.js +6 -6
- package/dist/src/core/patch-lint-forward-registration.d.ts +58 -0
- package/dist/src/core/patch-lint-forward-registration.js +210 -0
- package/dist/src/core/patch-lint-jsdoc.d.ts +2 -2
- package/dist/src/core/patch-lint-jsdoc.js +46 -46
- package/dist/src/core/patch-lint-module-registration.d.ts +3 -9
- package/dist/src/core/patch-lint-module-registration.js +1 -1
- package/dist/src/core/patch-lint-mozbuild.d.ts +1 -1
- package/dist/src/core/patch-lint-mozbuild.js +10 -10
- package/dist/src/core/patch-lint-observer.d.ts +3 -3
- package/dist/src/core/patch-lint-observer.js +7 -7
- package/dist/src/core/patch-lint-ownership.d.ts +6 -6
- package/dist/src/core/patch-lint-ownership.js +6 -6
- package/dist/src/core/patch-lint-prettier.d.ts +6 -6
- package/dist/src/core/patch-lint-prettier.js +7 -7
- package/dist/src/core/patch-lint-queue-types.d.ts +60 -0
- package/dist/src/core/patch-lint-queue-types.js +12 -0
- package/dist/src/core/patch-lint-staged-registration.d.ts +61 -0
- package/dist/src/core/patch-lint-staged-registration.js +90 -0
- package/dist/src/core/patch-lint-unmanaged-companion.d.ts +23 -23
- package/dist/src/core/patch-lint-unmanaged-companion.js +26 -26
- package/dist/src/core/patch-lint.d.ts +41 -35
- package/dist/src/core/patch-lint.js +52 -49
- package/dist/src/core/patch-lock.d.ts +1 -1
- package/dist/src/core/patch-lock.js +11 -11
- package/dist/src/core/patch-manifest-consistency.d.ts +7 -7
- package/dist/src/core/patch-manifest-consistency.js +16 -17
- package/dist/src/core/patch-manifest-files-affected.d.ts +1 -1
- package/dist/src/core/patch-manifest-files-affected.js +3 -3
- package/dist/src/core/patch-manifest-io.d.ts +14 -14
- package/dist/src/core/patch-manifest-io.js +35 -34
- package/dist/src/core/patch-manifest-query.d.ts +1 -1
- package/dist/src/core/patch-manifest-query.js +4 -4
- package/dist/src/core/patch-manifest-resolve.d.ts +5 -5
- package/dist/src/core/patch-manifest-resolve.js +7 -7
- package/dist/src/core/patch-manifest-validate.js +3 -3
- package/dist/src/core/patch-manifest.d.ts +2 -2
- package/dist/src/core/patch-manifest.js +2 -2
- package/dist/src/core/patch-parse.d.ts +32 -21
- package/dist/src/core/patch-parse.js +40 -15
- package/dist/src/core/patch-policy.js +15 -27
- package/dist/src/core/patch-registration-refs.d.ts +4 -4
- package/dist/src/core/patch-registration-refs.js +7 -7
- package/dist/src/core/patch-source-metadata.d.ts +1 -3
- package/dist/src/core/patch-source-metadata.js +0 -4
- package/dist/src/core/patch-transform.d.ts +8 -16
- package/dist/src/core/patch-transform.js +13 -23
- package/dist/src/core/process-cpu-time.d.ts +1 -1
- package/dist/src/core/process-cpu-time.js +6 -6
- package/dist/src/core/rebase-session.d.ts +9 -15
- package/dist/src/core/rebase-session.js +13 -25
- package/dist/src/core/register-browser-content.js +3 -2
- package/dist/src/core/register-browser-test.js +2 -1
- package/dist/src/core/register-module.js +2 -1
- package/dist/src/core/register-result.d.ts +1 -1
- package/dist/src/core/register-result.js +1 -1
- package/dist/src/core/register-scaffold.d.ts +2 -2
- package/dist/src/core/register-scaffold.js +8 -7
- package/dist/src/core/register-shared-css.d.ts +3 -3
- package/dist/src/core/register-shared-css.js +6 -5
- package/dist/src/core/register-xpcshell-test.d.ts +2 -2
- package/dist/src/core/register-xpcshell-test.js +2 -2
- package/dist/src/core/run-log-redact.d.ts +38 -0
- package/dist/src/core/run-log-redact.js +69 -0
- package/dist/src/core/run-log.d.ts +21 -10
- package/dist/src/core/run-log.js +76 -27
- package/dist/src/core/shared-ftl.d.ts +2 -2
- package/dist/src/core/shared-ftl.js +6 -6
- package/dist/src/core/signal-critical.d.ts +2 -2
- package/dist/src/core/signal-critical.js +4 -6
- package/dist/src/core/smoke-patterns.d.ts +5 -6
- package/dist/src/core/smoke-patterns.js +15 -20
- package/dist/src/core/state-file.d.ts +15 -4
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-binary.d.ts +8 -8
- package/dist/src/core/status-binary.js +12 -12
- package/dist/src/core/status-classify.d.ts +17 -17
- package/dist/src/core/status-classify.js +13 -12
- package/dist/src/core/test-changed-prefs.d.ts +12 -12
- package/dist/src/core/test-changed-prefs.js +40 -25
- package/dist/src/core/test-harness-crash.d.ts +39 -39
- package/dist/src/core/test-harness-crash.js +69 -69
- package/dist/src/core/test-harness-output.d.ts +7 -7
- package/dist/src/core/test-harness-output.js +7 -7
- package/dist/src/core/test-harness-verdict-notes.d.ts +13 -14
- package/dist/src/core/test-harness-verdict-notes.js +4 -4
- package/dist/src/core/test-path-scope.d.ts +8 -8
- package/dist/src/core/test-path-scope.js +11 -11
- package/dist/src/core/test-stale-check.d.ts +22 -23
- package/dist/src/core/test-stale-check.js +31 -30
- package/dist/src/core/test-stale-symlink.d.ts +1 -1
- package/dist/src/core/test-stale-symlink.js +1 -1
- package/dist/src/core/test-stall-triage.d.ts +9 -9
- package/dist/src/core/test-stall-triage.js +22 -22
- package/dist/src/core/test-xpcshell-retry.d.ts +26 -7
- package/dist/src/core/test-xpcshell-retry.js +14 -11
- package/dist/src/core/token-category.d.ts +35 -2
- package/dist/src/core/token-category.js +67 -58
- package/dist/src/core/token-coverage.js +4 -5
- package/dist/src/core/token-dark-mode.d.ts +9 -9
- package/dist/src/core/token-dark-mode.js +13 -25
- package/dist/src/core/token-docs.d.ts +1 -1
- package/dist/src/core/token-inventory.d.ts +56 -0
- package/dist/src/core/token-inventory.js +109 -0
- package/dist/src/core/token-manager.d.ts +4 -4
- package/dist/src/core/token-manager.js +22 -22
- package/dist/src/core/token-scaffold.d.ts +4 -4
- package/dist/src/core/token-scaffold.js +4 -4
- package/dist/src/core/token-variant.d.ts +14 -14
- package/dist/src/core/token-variant.js +52 -53
- package/dist/src/core/toolchain-preflight.d.ts +15 -15
- package/dist/src/core/toolchain-preflight.js +23 -23
- package/dist/src/core/tree-cow.d.ts +3 -5
- package/dist/src/core/tree-cow.js +8 -8
- package/dist/src/core/tree-guard.d.ts +3 -3
- package/dist/src/core/tree-guard.js +23 -23
- package/dist/src/core/tree-store.d.ts +15 -15
- package/dist/src/core/tree-store.js +39 -38
- package/dist/src/core/typecheck-shim.d.ts +16 -15
- package/dist/src/core/typecheck-shim.js +26 -25
- package/dist/src/core/typecheck.d.ts +12 -12
- package/dist/src/core/typecheck.js +33 -33
- package/dist/src/core/wire-destroy.d.ts +2 -2
- package/dist/src/core/wire-destroy.js +5 -5
- package/dist/src/core/wire-dom-fragment.d.ts +3 -3
- package/dist/src/core/wire-dom-fragment.js +12 -23
- package/dist/src/core/wire-init.d.ts +2 -2
- package/dist/src/core/wire-init.js +7 -7
- package/dist/src/core/wire-subscript.d.ts +1 -1
- package/dist/src/core/wire-subscript.js +3 -3
- package/dist/src/core/wire-utils.d.ts +9 -9
- package/dist/src/core/wire-utils.js +16 -28
- package/dist/src/core/xpcshell-appdir.d.ts +20 -20
- package/dist/src/core/xpcshell-appdir.js +28 -30
- package/dist/src/core/xpcshell-profile-dir.d.ts +3 -3
- package/dist/src/core/xpcshell-profile-dir.js +7 -7
- package/dist/src/errors/base.d.ts +69 -16
- package/dist/src/errors/base.js +95 -26
- package/dist/src/errors/build.d.ts +6 -6
- package/dist/src/errors/build.js +26 -34
- package/dist/src/errors/codes.d.ts +10 -10
- package/dist/src/errors/codes.js +10 -10
- package/dist/src/errors/config.d.ts +0 -14
- package/dist/src/errors/config.js +13 -34
- package/dist/src/errors/download.d.ts +13 -0
- package/dist/src/errors/download.js +53 -24
- package/dist/src/errors/furnace.d.ts +2 -2
- package/dist/src/errors/furnace.js +8 -9
- package/dist/src/errors/git.d.ts +9 -9
- package/dist/src/errors/git.js +21 -31
- package/dist/src/errors/patch.d.ts +3 -3
- package/dist/src/errors/patch.js +11 -13
- package/dist/src/errors/rebase.d.ts +1 -1
- package/dist/src/errors/rebase.js +8 -8
- package/dist/src/errors/run.d.ts +1 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.d.ts +4 -4
- package/dist/src/index.js +4 -4
- package/dist/src/types/commands/options.d.ts +155 -200
- package/dist/src/types/commands/patches.d.ts +19 -19
- package/dist/src/types/commands/project.d.ts +3 -3
- package/dist/src/types/config.d.ts +52 -19
- package/dist/src/types/furnace.d.ts +17 -17
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/types/json.d.ts +3 -3
- package/dist/src/types/json.js +2 -2
- package/dist/src/types/typecheck.d.ts +3 -3
- package/dist/src/utils/assert.d.ts +4 -16
- package/dist/src/utils/assert.js +7 -24
- package/dist/src/utils/build-info.d.ts +6 -6
- package/dist/src/utils/build-info.js +6 -6
- package/dist/src/utils/child-env.d.ts +7 -6
- package/dist/src/utils/child-env.js +5 -5
- package/dist/src/utils/concurrency.d.ts +2 -2
- package/dist/src/utils/concurrency.js +2 -2
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/errors.d.ts +8 -8
- package/dist/src/utils/errors.js +8 -8
- package/dist/src/utils/fs.d.ts +1 -1
- package/dist/src/utils/fs.js +15 -20
- package/dist/src/utils/hash.d.ts +12 -0
- package/dist/src/utils/hash.js +16 -0
- package/dist/src/utils/line-dispatch.d.ts +15 -0
- package/dist/src/utils/line-dispatch.js +48 -0
- package/dist/src/utils/logger.d.ts +4 -4
- package/dist/src/utils/logger.js +11 -11
- package/dist/src/utils/machine-output.js +2 -2
- package/dist/src/utils/options.d.ts +14 -20
- package/dist/src/utils/options.js +26 -27
- package/dist/src/utils/package-root.js +5 -14
- package/dist/src/utils/paths.d.ts +4 -4
- package/dist/src/utils/paths.js +4 -4
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +10 -9
- package/dist/src/utils/process-group.js +37 -36
- package/dist/src/utils/process.d.ts +70 -55
- package/dist/src/utils/process.js +129 -179
- package/dist/src/utils/ps-duration.d.ts +4 -4
- package/dist/src/utils/ps-duration.js +9 -9
- package/dist/src/utils/regex.d.ts +4 -4
- package/dist/src/utils/regex.js +7 -7
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/stdio-drain.d.ts +7 -7
- package/dist/src/utils/stdio-drain.js +8 -8
- package/dist/src/utils/validation.d.ts +12 -49
- package/dist/src/utils/validation.js +26 -36
- package/docs/README.md +2 -2
- package/docs/configuration.md +163 -69
- package/docs/exit-codes.md +66 -49
- package/docs/furnace.md +20 -19
- package/docs/lifecycle-invariants.md +414 -247
- package/docs/machine-output.md +58 -34
- package/docs/patch-workflow.md +48 -44
- package/docs/run-logs.md +72 -28
- package/docs/testing.md +105 -98
- package/docs/verification-trees.md +23 -22
- package/package.json +7 -6
- package/dist/src/commands/rebase.d.ts +0 -4
- package/dist/src/commands/rebase.js +0 -5
- package/dist/src/core/patch-artifact-normalize.d.ts +0 -21
- package/dist/src/core/patch-artifact-normalize.js +0 -24
- package/dist/src/core/patch-lint-reexports.d.ts +0 -7
- package/dist/src/core/patch-lint-reexports.js +0 -8
- package/dist/src/core/wire-targets.d.ts +0 -7
- package/dist/src/core/wire-targets.js +0 -8
|
@@ -5,6 +5,21 @@
|
|
|
5
5
|
* Progress callback for download operations.
|
|
6
6
|
*/
|
|
7
7
|
export type ProgressCallback = (downloaded: number, total: number) => void;
|
|
8
|
+
/**
|
|
9
|
+
* Fetches a URL with timeout and bounded retry for transient failures
|
|
10
|
+
* (429/5xx, network errors, the per-request timeout).
|
|
11
|
+
*
|
|
12
|
+
* Any other response (2xx or a non-retryable failure such as 404) is
|
|
13
|
+
* returned as-is on the first attempt. The caller decides what a given
|
|
14
|
+
* status means for its request. Shared by the tarball download and the
|
|
15
|
+
* SHA256SUMS lookup so both requests the download makes survive the same
|
|
16
|
+
* transient blips: with checksum verification failing closed, an
|
|
17
|
+
* un-retried checksum fetch would throw away a just-landed 600 MB archive
|
|
18
|
+
* over one dropped connection.
|
|
19
|
+
*
|
|
20
|
+
* @throws DownloadError once every attempt has failed with a retryable error
|
|
21
|
+
*/
|
|
22
|
+
export declare function fetchWithRetry(url: string): Promise<Response>;
|
|
8
23
|
/**
|
|
9
24
|
* Downloads a file from a URL with progress tracking, timeout, and retry.
|
|
10
25
|
* @param url - URL to download
|
|
@@ -7,7 +7,13 @@ import { basename } from 'node:path';
|
|
|
7
7
|
import { Readable, Transform } from 'node:stream';
|
|
8
8
|
import { pipeline } from 'node:stream/promises';
|
|
9
9
|
import { DownloadError, VersionNotFoundError } from '../errors/download.js';
|
|
10
|
-
|
|
10
|
+
import { sleep } from '../utils/sleep.js';
|
|
11
|
+
/**
|
|
12
|
+
* Per-attempt request timeout in milliseconds (60 seconds). Every request
|
|
13
|
+
* the download makes (the tarball and the SHA256SUMS lookup in
|
|
14
|
+
* `firefox-cache.ts`) goes through {@link fetchWithRetry} and so shares
|
|
15
|
+
* this abort ceiling.
|
|
16
|
+
*/
|
|
11
17
|
const REQUEST_TIMEOUT_MS = 60_000;
|
|
12
18
|
/** Maximum number of download attempts. */
|
|
13
19
|
const MAX_ATTEMPTS = 3;
|
|
@@ -15,14 +21,23 @@ const MAX_ATTEMPTS = 3;
|
|
|
15
21
|
const RETRYABLE_STATUS_CODES = new Set([429, 500, 502, 503, 504]);
|
|
16
22
|
/** Base delay between retries in milliseconds. */
|
|
17
23
|
const RETRY_BASE_DELAY_MS = 1_000;
|
|
18
|
-
/** Stall detection timeout
|
|
24
|
+
/** Stall detection timeout: abort if no data received for this duration (30 seconds). */
|
|
19
25
|
const DOWNLOAD_STALL_TIMEOUT_MS = 30_000;
|
|
20
26
|
/**
|
|
21
|
-
* Fetches a URL with timeout and bounded retry for transient failures
|
|
27
|
+
* Fetches a URL with timeout and bounded retry for transient failures
|
|
28
|
+
* (429/5xx, network errors, the per-request timeout).
|
|
22
29
|
*
|
|
23
|
-
*
|
|
30
|
+
* Any other response (2xx or a non-retryable failure such as 404) is
|
|
31
|
+
* returned as-is on the first attempt. The caller decides what a given
|
|
32
|
+
* status means for its request. Shared by the tarball download and the
|
|
33
|
+
* SHA256SUMS lookup so both requests the download makes survive the same
|
|
34
|
+
* transient blips: with checksum verification failing closed, an
|
|
35
|
+
* un-retried checksum fetch would throw away a just-landed 600 MB archive
|
|
36
|
+
* over one dropped connection.
|
|
37
|
+
*
|
|
38
|
+
* @throws DownloadError once every attempt has failed with a retryable error
|
|
24
39
|
*/
|
|
25
|
-
async function fetchWithRetry(url) {
|
|
40
|
+
export async function fetchWithRetry(url) {
|
|
26
41
|
let lastError;
|
|
27
42
|
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
28
43
|
const controller = new AbortController();
|
|
@@ -31,23 +46,12 @@ async function fetchWithRetry(url) {
|
|
|
31
46
|
}, REQUEST_TIMEOUT_MS);
|
|
32
47
|
try {
|
|
33
48
|
const response = await fetch(url, { signal: controller.signal });
|
|
34
|
-
if (response.status
|
|
35
|
-
throw new VersionNotFoundError(basename(url).replace('.source.tar.xz', ''));
|
|
36
|
-
}
|
|
37
|
-
if (RETRYABLE_STATUS_CODES.has(response.status)) {
|
|
38
|
-
lastError = new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
|
|
39
|
-
}
|
|
40
|
-
else if (!response.ok) {
|
|
41
|
-
throw new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
49
|
+
if (!RETRYABLE_STATUS_CODES.has(response.status)) {
|
|
44
50
|
return response;
|
|
45
51
|
}
|
|
52
|
+
lastError = new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
|
|
46
53
|
}
|
|
47
54
|
catch (error) {
|
|
48
|
-
if (error instanceof VersionNotFoundError || error instanceof DownloadError) {
|
|
49
|
-
throw error;
|
|
50
|
-
}
|
|
51
55
|
// Network / timeout errors are retryable
|
|
52
56
|
lastError = error;
|
|
53
57
|
}
|
|
@@ -55,9 +59,7 @@ async function fetchWithRetry(url) {
|
|
|
55
59
|
clearTimeout(timer);
|
|
56
60
|
}
|
|
57
61
|
if (attempt < MAX_ATTEMPTS - 1) {
|
|
58
|
-
await
|
|
59
|
-
setTimeout(resolve, RETRY_BASE_DELAY_MS * (attempt + 1) ** 2);
|
|
60
|
-
});
|
|
62
|
+
await sleep(RETRY_BASE_DELAY_MS * (attempt + 1) ** 2);
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
if (lastError instanceof DownloadError) {
|
|
@@ -65,6 +67,20 @@ async function fetchWithRetry(url) {
|
|
|
65
67
|
}
|
|
66
68
|
throw new DownloadError(lastError instanceof Error ? lastError.message : 'Download failed after retries', url, lastError instanceof Error ? lastError : undefined);
|
|
67
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Fetches the archive itself: a 404 is the release not existing
|
|
72
|
+
* (`VersionNotFoundError`), any other non-2xx is a `DownloadError`.
|
|
73
|
+
*/
|
|
74
|
+
async function fetchArchive(url) {
|
|
75
|
+
const response = await fetchWithRetry(url);
|
|
76
|
+
if (response.status === 404) {
|
|
77
|
+
throw new VersionNotFoundError(basename(url).replace('.source.tar.xz', ''));
|
|
78
|
+
}
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
throw new DownloadError(`HTTP ${response.status}: ${response.statusText}`, url);
|
|
81
|
+
}
|
|
82
|
+
return response;
|
|
83
|
+
}
|
|
68
84
|
/**
|
|
69
85
|
* Creates a Transform stream that aborts if no data is received within the stall timeout.
|
|
70
86
|
* The timer resets on each chunk. If it fires, the stream is destroyed with a DownloadError.
|
|
@@ -110,7 +126,7 @@ function createStallDetector(url, timeoutMs = DOWNLOAD_STALL_TIMEOUT_MS) {
|
|
|
110
126
|
* @returns The content-length if available, otherwise undefined
|
|
111
127
|
*/
|
|
112
128
|
export async function downloadFile(url, destPath, onProgress) {
|
|
113
|
-
const response = await
|
|
129
|
+
const response = await fetchArchive(url);
|
|
114
130
|
if (!response.body) {
|
|
115
131
|
throw new DownloadError('No response body received', url);
|
|
116
132
|
}
|
|
@@ -2,24 +2,25 @@
|
|
|
2
2
|
* Firefox source extraction and installed version detection.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* Validates entry names from a `tar -tf` listing
|
|
5
|
+
* Validates entry names from a `tar -tf` listing: escaping paths and
|
|
6
|
+
* `.git` members are both rejected.
|
|
6
7
|
* @param names - Listing lines (one member name per line)
|
|
7
|
-
* @returns The first unsafe member name, or
|
|
8
|
+
* @returns The first unsafe member name, or undefined when all are safe
|
|
8
9
|
*/
|
|
9
|
-
export declare function findUnsafeArchiveEntryName(names: readonly string[]): string |
|
|
10
|
+
export declare function findUnsafeArchiveEntryName(names: readonly string[]): string | undefined;
|
|
10
11
|
/**
|
|
11
12
|
* Validates symlink and hardlink targets from a `tar -tvf` listing.
|
|
12
13
|
*
|
|
13
14
|
* A relative link target without `..` segments can only resolve inside the
|
|
14
15
|
* extraction root, so only absolute or `..`-containing targets are rejected.
|
|
15
|
-
* Symlinks are `l`-typed lines with a ` -> target` suffix (the
|
|
16
|
+
* Symlinks are `l`-typed lines with a ` -> target` suffix (the last arrow is
|
|
16
17
|
* taken, so a link whose own name contains ` -> ` still parses to its real
|
|
17
|
-
* target)
|
|
18
|
+
* target). Hardlinks print ` link to target` on GNU tar and bsdtar alike.
|
|
18
19
|
*
|
|
19
20
|
* @param verboseLines - `tar -tvf` listing lines
|
|
20
|
-
* @returns A description of the first unsafe link found, or
|
|
21
|
+
* @returns A description of the first unsafe link found, or undefined
|
|
21
22
|
*/
|
|
22
|
-
export declare function findUnsafeArchiveLink(verboseLines: readonly string[]): string |
|
|
23
|
+
export declare function findUnsafeArchiveLink(verboseLines: readonly string[]): string | undefined;
|
|
23
24
|
/**
|
|
24
25
|
* Extracts a tar.xz archive after a listing preflight that rejects
|
|
25
26
|
* path-traversal member names and escaping link targets.
|
|
@@ -20,31 +20,54 @@ function isUnsafeArchivePath(path) {
|
|
|
20
20
|
return path.split(/[\\/]/).includes('..');
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* Returns true when an archive member path has a `.git` segment at any
|
|
24
|
+
* depth (`.git`, `.git/config`, `foo/.git/hooks/pre-commit`). Such a member
|
|
25
|
+
* lands inside the extraction root, so the traversal check passes it, but
|
|
26
|
+
* the extracted tree is immediately turned into a git repository and
|
|
27
|
+
* committed, and git honours a pre-seeded `.git/config` (`core.fsmonitor`,
|
|
28
|
+
* `core.hooksPath`) or `.git/hooks/*` on that first commit. Only the `.git`
|
|
29
|
+
* directory/file is rejected. `.gitmodules`, `.gitignore` and the like are
|
|
30
|
+
* legitimate upstream files.
|
|
31
|
+
*/
|
|
32
|
+
function hasGitSegment(path) {
|
|
33
|
+
return path.split(/[\\/]/).some((segment) => segment.toLowerCase() === '.git');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns true when an archive member name must be rejected: an escaping
|
|
37
|
+
* path, or a `.git` segment (see {@link hasGitSegment}). Link targets use
|
|
38
|
+
* the narrower {@link isUnsafeArchivePath}: a target can only be reached
|
|
39
|
+
* through a member name that was checked here.
|
|
40
|
+
*/
|
|
41
|
+
function isUnsafeArchiveMemberName(name) {
|
|
42
|
+
return isUnsafeArchivePath(name) || hasGitSegment(name);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Validates entry names from a `tar -tf` listing: escaping paths and
|
|
46
|
+
* `.git` members are both rejected.
|
|
24
47
|
* @param names - Listing lines (one member name per line)
|
|
25
|
-
* @returns The first unsafe member name, or
|
|
48
|
+
* @returns The first unsafe member name, or undefined when all are safe
|
|
26
49
|
*/
|
|
27
50
|
export function findUnsafeArchiveEntryName(names) {
|
|
28
51
|
for (const raw of names) {
|
|
29
52
|
const name = raw.trim();
|
|
30
53
|
if (name.length === 0)
|
|
31
54
|
continue;
|
|
32
|
-
if (
|
|
55
|
+
if (isUnsafeArchiveMemberName(name))
|
|
33
56
|
return name;
|
|
34
57
|
}
|
|
35
|
-
return
|
|
58
|
+
return undefined;
|
|
36
59
|
}
|
|
37
60
|
/**
|
|
38
61
|
* Validates symlink and hardlink targets from a `tar -tvf` listing.
|
|
39
62
|
*
|
|
40
63
|
* A relative link target without `..` segments can only resolve inside the
|
|
41
64
|
* extraction root, so only absolute or `..`-containing targets are rejected.
|
|
42
|
-
* Symlinks are `l`-typed lines with a ` -> target` suffix (the
|
|
65
|
+
* Symlinks are `l`-typed lines with a ` -> target` suffix (the last arrow is
|
|
43
66
|
* taken, so a link whose own name contains ` -> ` still parses to its real
|
|
44
|
-
* target)
|
|
67
|
+
* target). Hardlinks print ` link to target` on GNU tar and bsdtar alike.
|
|
45
68
|
*
|
|
46
69
|
* @param verboseLines - `tar -tvf` listing lines
|
|
47
|
-
* @returns A description of the first unsafe link found, or
|
|
70
|
+
* @returns A description of the first unsafe link found, or undefined
|
|
48
71
|
*/
|
|
49
72
|
export function findUnsafeArchiveLink(verboseLines) {
|
|
50
73
|
for (const line of verboseLines) {
|
|
@@ -64,19 +87,19 @@ export function findUnsafeArchiveLink(verboseLines) {
|
|
|
64
87
|
return `hardlink target: ${target}`;
|
|
65
88
|
}
|
|
66
89
|
}
|
|
67
|
-
return
|
|
90
|
+
return undefined;
|
|
68
91
|
}
|
|
69
92
|
/**
|
|
70
93
|
* Lists the archive and rejects members that could escape the extraction
|
|
71
94
|
* root before anything is written to disk: absolute names, `..` traversal,
|
|
72
95
|
* and symlink/hardlink targets that are absolute or `..`-escaping. Modern
|
|
73
|
-
* GNU tar / bsdtar refuse most of these at extraction time
|
|
96
|
+
* GNU tar / bsdtar refuse most of these at extraction time. The preflight
|
|
74
97
|
* makes the guarantee explicit and independent of the host tar's defaults.
|
|
75
98
|
*
|
|
76
99
|
* Two listings are needed because they answer different questions and
|
|
77
100
|
* neither is safe to derive from the other: member names come from `-tf`,
|
|
78
|
-
* where the whole line
|
|
79
|
-
* `-tvf`. Names are
|
|
101
|
+
* where the whole line is the name, while link targets only appear in
|
|
102
|
+
* `-tvf`. Names are not parsed out of the `-tvf` columns, on purpose: the
|
|
80
103
|
* adjacent uname/gname fields are attacker-controlled in a crafted archive,
|
|
81
104
|
* so a date-shaped owner name could shift the column boundary and hide an
|
|
82
105
|
* absolute member name from the check. Each listing pass costs one full
|
|
@@ -111,23 +134,23 @@ function createLineScanner(onLine) {
|
|
|
111
134
|
}
|
|
112
135
|
/**
|
|
113
136
|
* Runs one tar listing pass, streaming lines through `checkLine` and
|
|
114
|
-
* returning the first unsafe finding (or
|
|
137
|
+
* returning the first unsafe finding (or undefined) plus the exit code.
|
|
115
138
|
*
|
|
116
139
|
* Streaming matters for safety, not just memory: a buffered `exec` collector
|
|
117
140
|
* silently truncates at 50 MB, and a full Firefox `-tvf` listing already
|
|
118
|
-
* sits in the 40
|
|
141
|
+
* sits in the 40-50 MB range, so a buffered implementation scans only the
|
|
119
142
|
* head of the listing while reporting the archive safe. A crafted archive
|
|
120
|
-
* could exploit
|
|
143
|
+
* could exploit that by padding benign entries first and hiding a
|
|
121
144
|
* traversal name or absolute link target past the cap. Per-line streaming
|
|
122
|
-
* scans
|
|
145
|
+
* scans every entry with bounded memory.
|
|
123
146
|
*/
|
|
124
147
|
async function runListingScan(archivePath, tarFlag, checkLine) {
|
|
125
148
|
// LC_ALL=C keeps the -tvf column format stable for the link parse.
|
|
126
149
|
const listEnv = { LC_ALL: 'C', LANG: 'C' };
|
|
127
|
-
let unsafe
|
|
150
|
+
let unsafe;
|
|
128
151
|
let stderrTail = '';
|
|
129
152
|
const scanner = createLineScanner((line) => {
|
|
130
|
-
if (unsafe ===
|
|
153
|
+
if (unsafe === undefined) {
|
|
131
154
|
unsafe = checkLine(line);
|
|
132
155
|
}
|
|
133
156
|
});
|
|
@@ -137,7 +160,7 @@ async function runListingScan(archivePath, tarFlag, checkLine) {
|
|
|
137
160
|
scanner.push(chunk);
|
|
138
161
|
},
|
|
139
162
|
onStderr: (chunk) => {
|
|
140
|
-
// Keep a small diagnostic tail
|
|
163
|
+
// Keep a small diagnostic tail. The listing itself is the big stream.
|
|
141
164
|
stderrTail = (stderrTail + chunk).slice(-4096);
|
|
142
165
|
},
|
|
143
166
|
});
|
|
@@ -146,24 +169,19 @@ async function runListingScan(archivePath, tarFlag, checkLine) {
|
|
|
146
169
|
}
|
|
147
170
|
async function preflightArchiveEntries(archivePath) {
|
|
148
171
|
const [nameScan, linkScan] = await Promise.all([
|
|
149
|
-
runListingScan(archivePath, '-tf', (line) =>
|
|
150
|
-
const name = line.trim();
|
|
151
|
-
if (name.length === 0)
|
|
152
|
-
return null;
|
|
153
|
-
return isUnsafeArchivePath(name) ? name : null;
|
|
154
|
-
}),
|
|
172
|
+
runListingScan(archivePath, '-tf', (line) => findUnsafeArchiveEntryName([line])),
|
|
155
173
|
runListingScan(archivePath, '-tvf', (line) => findUnsafeArchiveLink([line])),
|
|
156
174
|
]);
|
|
157
175
|
if (nameScan.exitCode !== 0) {
|
|
158
176
|
throw new ExtractionError(archivePath, new Error(`tar -tf preflight exited with code ${nameScan.exitCode}:\n${nameScan.stderrTail}`));
|
|
159
177
|
}
|
|
160
|
-
if (nameScan.unsafe !==
|
|
161
|
-
throw new ExtractionError(archivePath, new Error(`Archive rejected: member name could escape the extraction root: ${nameScan.unsafe}`));
|
|
178
|
+
if (nameScan.unsafe !== undefined) {
|
|
179
|
+
throw new ExtractionError(archivePath, new Error(`Archive rejected: member name could escape the extraction root or seed .git: ${nameScan.unsafe}`));
|
|
162
180
|
}
|
|
163
181
|
if (linkScan.exitCode !== 0) {
|
|
164
182
|
throw new ExtractionError(archivePath, new Error(`tar -tvf preflight exited with code ${linkScan.exitCode}:\n${linkScan.stderrTail}`));
|
|
165
183
|
}
|
|
166
|
-
if (linkScan.unsafe !==
|
|
184
|
+
if (linkScan.unsafe !== undefined) {
|
|
167
185
|
throw new ExtractionError(archivePath, new Error(`Archive rejected: link could escape the extraction root (${linkScan.unsafe})`));
|
|
168
186
|
}
|
|
169
187
|
}
|
|
@@ -5,26 +5,9 @@
|
|
|
5
5
|
* {@link downloadFirefoxSource} orchestrator.
|
|
6
6
|
*/
|
|
7
7
|
import type { FirefoxProduct } from '../types/config.js';
|
|
8
|
+
import type { ArchiveIntegrityOptions } from './firefox-cache.js';
|
|
8
9
|
import type { ProgressCallback } from './firefox-download.js';
|
|
9
|
-
export { resolveArchive } from './firefox-archive.js';
|
|
10
|
-
export type { ProgressCallback } from './firefox-download.js';
|
|
11
10
|
export { formatBytes, getFirefoxVersion } from './firefox-extract.js';
|
|
12
|
-
/**
|
|
13
|
-
* Gets the download URL for a Firefox source tarball.
|
|
14
|
-
* @param version - Firefox version (e.g., "140.9.0esr")
|
|
15
|
-
* @param product - Firefox product type
|
|
16
|
-
* @param candidate - Optional release-candidate build directory (e.g. "build2")
|
|
17
|
-
* @returns Full URL to the source tarball
|
|
18
|
-
*/
|
|
19
|
-
export declare function getDownloadUrl(version: string, product?: FirefoxProduct, candidate?: string): string;
|
|
20
|
-
/**
|
|
21
|
-
* Gets the filename for a Firefox source tarball.
|
|
22
|
-
* @param version - Firefox version
|
|
23
|
-
* @param product - Firefox product type
|
|
24
|
-
* @param candidate - Optional release-candidate build directory (e.g. "build2")
|
|
25
|
-
* @returns Tarball filename
|
|
26
|
-
*/
|
|
27
|
-
export declare function getTarballFilename(version: string, product?: FirefoxProduct, candidate?: string): string;
|
|
28
11
|
/**
|
|
29
12
|
* Lifecycle phase reported by {@link downloadFirefoxSource}. The download
|
|
30
13
|
* CLI command uses this to swap spinners between the bytes-on-the-wire phase
|
|
@@ -41,28 +24,43 @@ export type FirefoxSourceProgressCallback = (message: string) => void;
|
|
|
41
24
|
* Sweeps orphaned working directories left behind by interrupted downloads
|
|
42
25
|
* (`<engine>.tmp-*` from extraction, `<engine>.replacement-*` from --force
|
|
43
26
|
* replacement). Both hold multi-GB partial trees, are worthless after the
|
|
44
|
-
* owning process died, and nothing else ever reclaimed them.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
27
|
+
* owning process died, and nothing else ever reclaimed them. Does not
|
|
28
|
+
* touch `<engine>.backup-*`: a backup may hold the operator's previous
|
|
29
|
+
* engine after a failed forced replacement and is their recovery copy, so
|
|
30
|
+
* callers should surface its existence instead.
|
|
48
31
|
*
|
|
49
32
|
* @returns names of the directories that were removed
|
|
50
33
|
*/
|
|
51
34
|
export declare function sweepOrphanedEngineWorkDirs(destDir: string): Promise<string[]>;
|
|
35
|
+
/** Inputs for {@link downloadFirefoxSource}. */
|
|
36
|
+
export interface DownloadFirefoxSourceOptions {
|
|
37
|
+
/** Firefox version to fetch, e.g. `140.9.0esr`. */
|
|
38
|
+
version: string;
|
|
39
|
+
/** Product channel the version belongs to. */
|
|
40
|
+
product: FirefoxProduct;
|
|
41
|
+
/** Directory the extracted source tree is moved into. */
|
|
42
|
+
destDir: string;
|
|
43
|
+
/** Directory holding downloaded tarballs between runs. */
|
|
44
|
+
cacheDir: string;
|
|
45
|
+
/** Called with byte progress for the whole transfer. */
|
|
46
|
+
onProgress?: ProgressCallback | undefined;
|
|
47
|
+
/** Called when the run moves from downloading to extracting. */
|
|
48
|
+
onPhase?: FirefoxSourcePhaseCallback | undefined;
|
|
49
|
+
/** Expected archive checksum, verified after download when supplied. */
|
|
50
|
+
expectedSha256?: string | undefined;
|
|
51
|
+
/** Called with byte progress within the current phase. */
|
|
52
|
+
onPhaseProgress?: FirefoxSourceProgressCallback | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Release-candidate build directory (e.g. `build2`), resolving the archive
|
|
55
|
+
* under `candidates/` instead of `releases/`.
|
|
56
|
+
*/
|
|
57
|
+
candidate?: string | undefined;
|
|
58
|
+
/** Integrity-check defaults for unpinned downloads. */
|
|
59
|
+
integrity?: ArchiveIntegrityOptions | undefined;
|
|
60
|
+
}
|
|
52
61
|
/**
|
|
53
62
|
* Downloads and extracts Firefox source.
|
|
54
|
-
*
|
|
55
|
-
* @param
|
|
56
|
-
* @param destDir - Destination directory for extracted source
|
|
57
|
-
* @param cacheDir - Directory to store downloaded tarball
|
|
58
|
-
* @param onProgress - Optional progress callback for the download byte stream
|
|
59
|
-
* @param onPhase - Optional callback fired when the function transitions
|
|
60
|
-
* between phases (`'download'` → `'extract'`). Fires exactly once per
|
|
61
|
-
* phase even if the cached archive path skips the wire entirely.
|
|
62
|
-
* @param expectedSha256 - Expected archive checksum; verified after download when supplied
|
|
63
|
-
* @param onPhaseProgress - Called with byte progress within the current phase
|
|
64
|
-
* @param candidate - Optional release-candidate build directory (e.g.
|
|
65
|
-
* "build2") resolving the archive under `candidates/` instead of
|
|
66
|
-
* `releases/`.
|
|
63
|
+
*
|
|
64
|
+
* @param options - See {@link DownloadFirefoxSourceOptions}.
|
|
67
65
|
*/
|
|
68
|
-
export declare function downloadFirefoxSource(
|
|
66
|
+
export declare function downloadFirefoxSource(options: DownloadFirefoxSourceOptions): Promise<void>;
|
package/dist/src/core/firefox.js
CHANGED
|
@@ -14,33 +14,12 @@ import { resolveArchive } from './firefox-archive.js';
|
|
|
14
14
|
import { ensureCachedArchive, invalidateArchiveCache } from './firefox-cache.js';
|
|
15
15
|
import { extractTarXz } from './firefox-extract.js';
|
|
16
16
|
// ── Re-exports (preserve public API) ──
|
|
17
|
-
export { resolveArchive } from './firefox-archive.js';
|
|
18
17
|
export { formatBytes, getFirefoxVersion } from './firefox-extract.js';
|
|
19
|
-
/**
|
|
20
|
-
* Gets the download URL for a Firefox source tarball.
|
|
21
|
-
* @param version - Firefox version (e.g., "140.9.0esr")
|
|
22
|
-
* @param product - Firefox product type
|
|
23
|
-
* @param candidate - Optional release-candidate build directory (e.g. "build2")
|
|
24
|
-
* @returns Full URL to the source tarball
|
|
25
|
-
*/
|
|
26
|
-
export function getDownloadUrl(version, product = 'firefox', candidate) {
|
|
27
|
-
return resolveArchive(version, product, candidate).url;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Gets the filename for a Firefox source tarball.
|
|
31
|
-
* @param version - Firefox version
|
|
32
|
-
* @param product - Firefox product type
|
|
33
|
-
* @param candidate - Optional release-candidate build directory (e.g. "build2")
|
|
34
|
-
* @returns Tarball filename
|
|
35
|
-
*/
|
|
36
|
-
export function getTarballFilename(version, product = 'firefox', candidate) {
|
|
37
|
-
return resolveArchive(version, product, candidate).filename;
|
|
38
|
-
}
|
|
39
18
|
/**
|
|
40
19
|
* Classifies an extraction failure as archive corruption (invalidate the
|
|
41
20
|
* cache and re-download) versus an environmental problem (keep the cached
|
|
42
|
-
* archive
|
|
43
|
-
* conservative list
|
|
21
|
+
* archive so the retry can reuse it). Environmental signatures are the
|
|
22
|
+
* conservative list. Anything unrecognized is treated as corruption so a
|
|
44
23
|
* genuinely bad archive can never survive in the cache.
|
|
45
24
|
*/
|
|
46
25
|
function isLikelyArchiveCorruptionError(error) {
|
|
@@ -53,7 +32,7 @@ function isLikelyArchiveCorruptionError(error) {
|
|
|
53
32
|
return false;
|
|
54
33
|
}
|
|
55
34
|
// Missing tar binary / preflight refusing an unsafe archive both carry
|
|
56
|
-
// ExtractionError text that names the condition
|
|
35
|
+
// ExtractionError text that names the condition. A missing tar is
|
|
57
36
|
// environmental, an unsafe-entry rejection indicts the archive.
|
|
58
37
|
if (/"tar" command was not found/i.test(message)) {
|
|
59
38
|
return false;
|
|
@@ -64,10 +43,10 @@ function isLikelyArchiveCorruptionError(error) {
|
|
|
64
43
|
* Sweeps orphaned working directories left behind by interrupted downloads
|
|
65
44
|
* (`<engine>.tmp-*` from extraction, `<engine>.replacement-*` from --force
|
|
66
45
|
* replacement). Both hold multi-GB partial trees, are worthless after the
|
|
67
|
-
* owning process died, and nothing else ever reclaimed them.
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
46
|
+
* owning process died, and nothing else ever reclaimed them. Does not
|
|
47
|
+
* touch `<engine>.backup-*`: a backup may hold the operator's previous
|
|
48
|
+
* engine after a failed forced replacement and is their recovery copy, so
|
|
49
|
+
* callers should surface its existence instead.
|
|
71
50
|
*
|
|
72
51
|
* @returns names of the directories that were removed
|
|
73
52
|
*/
|
|
@@ -95,27 +74,17 @@ export async function sweepOrphanedEngineWorkDirs(destDir) {
|
|
|
95
74
|
}
|
|
96
75
|
/**
|
|
97
76
|
* Downloads and extracts Firefox source.
|
|
98
|
-
*
|
|
99
|
-
* @param
|
|
100
|
-
* @param destDir - Destination directory for extracted source
|
|
101
|
-
* @param cacheDir - Directory to store downloaded tarball
|
|
102
|
-
* @param onProgress - Optional progress callback for the download byte stream
|
|
103
|
-
* @param onPhase - Optional callback fired when the function transitions
|
|
104
|
-
* between phases (`'download'` → `'extract'`). Fires exactly once per
|
|
105
|
-
* phase even if the cached archive path skips the wire entirely.
|
|
106
|
-
* @param expectedSha256 - Expected archive checksum; verified after download when supplied
|
|
107
|
-
* @param onPhaseProgress - Called with byte progress within the current phase
|
|
108
|
-
* @param candidate - Optional release-candidate build directory (e.g.
|
|
109
|
-
* "build2") resolving the archive under `candidates/` instead of
|
|
110
|
-
* `releases/`.
|
|
77
|
+
*
|
|
78
|
+
* @param options - See {@link DownloadFirefoxSourceOptions}.
|
|
111
79
|
*/
|
|
112
|
-
export async function downloadFirefoxSource(
|
|
80
|
+
export async function downloadFirefoxSource(options) {
|
|
81
|
+
const { version, product, destDir, cacheDir, onProgress, onPhase, expectedSha256, onPhaseProgress, candidate, integrity, } = options;
|
|
113
82
|
const archive = resolveArchive(version, product, candidate);
|
|
114
83
|
const tarballPath = join(cacheDir, archive.filename);
|
|
115
84
|
// Ensure cache directory exists
|
|
116
85
|
await ensureDir(cacheDir);
|
|
117
86
|
onPhase?.('download');
|
|
118
|
-
await ensureCachedArchive(archive, cacheDir, onProgress, expectedSha256, onPhaseProgress);
|
|
87
|
+
await ensureCachedArchive(archive, cacheDir, onProgress, expectedSha256, onPhaseProgress, integrity);
|
|
119
88
|
// Extract to a unique temporary directory so concurrent downloads for
|
|
120
89
|
// the same destination do not clobber each other.
|
|
121
90
|
onPhase?.('extract');
|
|
@@ -126,7 +95,7 @@ export async function downloadFirefoxSource(version, product, destDir, cacheDir,
|
|
|
126
95
|
catch (error) {
|
|
127
96
|
await removeDir(tempDir);
|
|
128
97
|
// Only throw away the ~600 MB cached archive when the failure indicts
|
|
129
|
-
// the
|
|
98
|
+
// the archive, not the environment. ENOSPC, a permission problem in
|
|
130
99
|
// destDir, or tar disappearing mid-run used to invalidate a perfectly
|
|
131
100
|
// good download and force a full re-fetch on retry.
|
|
132
101
|
if (isLikelyArchiveCorruptionError(error)) {
|
|
@@ -4,14 +4,9 @@
|
|
|
4
4
|
* stay within the per-file line budget. Consumed only by that module.
|
|
5
5
|
*/
|
|
6
6
|
import type { ComponentApplyContext, CustomComponentConfig, DryRunAction, StepError } from '../types/furnace.js';
|
|
7
|
-
|
|
8
|
-
isFile(): boolean;
|
|
9
|
-
isSymbolicLink?(): boolean;
|
|
10
|
-
name: string;
|
|
11
|
-
}
|
|
7
|
+
import { type DirectoryEntry } from './furnace-dir-entry.js';
|
|
12
8
|
/** Computes the planned dry-run actions (and pre-flight step errors) for a custom component. */
|
|
13
9
|
export declare function buildCustomDryRunActions(ctx: Pick<ComponentApplyContext, 'engineDir' | 'name' | 'componentDir' | 'ftlDir'>, config: CustomComponentConfig, targetDir: string, entries: DirectoryEntry[]): Promise<{
|
|
14
10
|
actions: DryRunAction[];
|
|
15
11
|
stepErrors: StepError[];
|
|
16
12
|
}>;
|
|
17
|
-
export {};
|
|
@@ -9,14 +9,8 @@ import { toError } from '../utils/errors.js';
|
|
|
9
9
|
import { pathExists } from '../utils/fs.js';
|
|
10
10
|
import { describeLocaleFtlJarMnRegistration, describeSharedFtlPrune } from './furnace-apply-ftl.js';
|
|
11
11
|
import { describeFragmentExpansion } from './furnace-css-fragments.js';
|
|
12
|
+
import { isRegularFile } from './furnace-dir-entry.js';
|
|
12
13
|
import { validateCustomElementRegistration, validateJarMnInsertionForFiles, } from './furnace-registration.js';
|
|
13
|
-
function isRegularFile(entry) {
|
|
14
|
-
if (!entry.isFile())
|
|
15
|
-
return false;
|
|
16
|
-
if (typeof entry.isSymbolicLink === 'function' && entry.isSymbolicLink())
|
|
17
|
-
return false;
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
14
|
/** Computes the planned dry-run actions (and pre-flight step errors) for a custom component. */
|
|
21
15
|
export async function buildCustomDryRunActions(ctx, config, targetDir, entries) {
|
|
22
16
|
const { engineDir, name, componentDir, ftlDir } = ctx;
|
|
@@ -58,7 +52,7 @@ export async function buildCustomDryRunActions(ctx, config, targetDir, entries)
|
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
54
|
}
|
|
61
|
-
// A sharedFtl widget owns its strings via the shared bundle
|
|
55
|
+
// A sharedFtl widget owns its strings via the shared bundle. Surface the
|
|
62
56
|
// removal of any dangling per-widget locale jar.mn entry so the dry-run
|
|
63
57
|
// plan matches what apply will do (and explains the unblocked build).
|
|
64
58
|
const pruneAction = await describeSharedFtlPrune(ctx, config);
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* per-file LOC budget.
|
|
5
5
|
*
|
|
6
6
|
* Every helper here degrades gracefully: if the locale jar.mn is missing or
|
|
7
|
-
* the FTL tree is non-standard, apply logs an
|
|
7
|
+
* the FTL tree is non-standard, apply logs an advisory `stepError`
|
|
8
8
|
* (`advisory: true`) rather than aborting the whole command. Advisory step
|
|
9
|
-
* errors are reported as warnings and never trigger rollback
|
|
9
|
+
* errors are reported as warnings and never trigger rollback: a missing
|
|
10
10
|
* jar.mn on a fork without a locale package must not block a working
|
|
11
11
|
* `.mjs`/`.css` from shipping.
|
|
12
12
|
*/
|
|
@@ -29,8 +29,8 @@ export declare function describeSharedFtlPrune(ctx: Pick<ComponentApplyContext,
|
|
|
29
29
|
* in the locale jar.mn.
|
|
30
30
|
*
|
|
31
31
|
* Failure modes (missing jar.mn, regex write error) are captured as
|
|
32
|
-
* stepErrors rather than thrown
|
|
33
|
-
* blocked by a broken locale path.
|
|
32
|
+
* stepErrors rather than thrown, since a well-formed `.mjs`/`.css` must
|
|
33
|
+
* never be blocked by a broken locale path.
|
|
34
34
|
*/
|
|
35
35
|
export declare function applyCustomFtlFile(ctx: Pick<ComponentApplyContext, 'engineDir' | 'name' | 'componentDir' | 'ftlDir'>, affectedPaths: string[], stepErrors: StepError[], rollbackJournal?: RollbackJournal): Promise<void>;
|
|
36
36
|
/**
|
|
@@ -41,7 +41,7 @@ export declare function applyCustomFtlFile(ctx: Pick<ComponentApplyContext, 'eng
|
|
|
41
41
|
export declare function describeLocaleFtlJarMnRegistration(name: string, ftlDir: string, ftlFile: string): DryRunAction | undefined;
|
|
42
42
|
/**
|
|
43
43
|
* Drops the locale jar.mn entry for `fileName` when it's a `.ftl` whose
|
|
44
|
-
* source workspace file has been deleted. Idempotent
|
|
44
|
+
* source workspace file has been deleted. Idempotent: absent entries are a
|
|
45
45
|
* no-op. Early-returns for `sharedFtl` components: the shared bundle is
|
|
46
46
|
* owned elsewhere, and dropping its jar.mn line on our component's delete
|
|
47
47
|
* would orphan every other participant.
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* per-file LOC budget.
|
|
6
6
|
*
|
|
7
7
|
* Every helper here degrades gracefully: if the locale jar.mn is missing or
|
|
8
|
-
* the FTL tree is non-standard, apply logs an
|
|
8
|
+
* the FTL tree is non-standard, apply logs an advisory `stepError`
|
|
9
9
|
* (`advisory: true`) rather than aborting the whole command. Advisory step
|
|
10
|
-
* errors are reported as warnings and never trigger rollback
|
|
10
|
+
* errors are reported as warnings and never trigger rollback: a missing
|
|
11
11
|
* jar.mn on a fork without a locale package must not block a working
|
|
12
12
|
* `.mjs`/`.css` from shipping.
|
|
13
13
|
*/
|
|
@@ -44,12 +44,12 @@ function resolveSharedFtlPruneTarget(name, ftlDir) {
|
|
|
44
44
|
*
|
|
45
45
|
* A `localized: true` widget that opts into a feature-scoped `sharedFtl`
|
|
46
46
|
* bundle (its strings live under `browser/...` and load via
|
|
47
|
-
* `insertFTLIfNeeded`) must
|
|
47
|
+
* `insertFTLIfNeeded`) must not carry a per-widget
|
|
48
48
|
* `locale/@AB_CD@/<chromeSubPath>/<name>.ftl` line. Such a line points at a
|
|
49
49
|
* `.ftl` that does not exist, so `mach build` fails hard (`Cannot find
|
|
50
50
|
* <chromeSubPath>/<name>.ftl`) and blocks every build.
|
|
51
51
|
*
|
|
52
|
-
* The pruned line is the per-widget toolkit entry only
|
|
52
|
+
* The pruned line is the per-widget toolkit entry only. The shared bundle's
|
|
53
53
|
* own line (a different chrome sub-path / base name) is never matched, so
|
|
54
54
|
* pruning one widget cannot orphan the shared bundle. Idempotent: when no
|
|
55
55
|
* dangling entry exists the file is left untouched (no journal churn).
|
|
@@ -120,8 +120,8 @@ export async function describeSharedFtlPrune(ctx, config) {
|
|
|
120
120
|
* in the locale jar.mn.
|
|
121
121
|
*
|
|
122
122
|
* Failure modes (missing jar.mn, regex write error) are captured as
|
|
123
|
-
* stepErrors rather than thrown
|
|
124
|
-
* blocked by a broken locale path.
|
|
123
|
+
* stepErrors rather than thrown, since a well-formed `.mjs`/`.css` must
|
|
124
|
+
* never be blocked by a broken locale path.
|
|
125
125
|
*/
|
|
126
126
|
export async function applyCustomFtlFile(ctx, affectedPaths, stepErrors, rollbackJournal) {
|
|
127
127
|
const { engineDir, name, componentDir, ftlDir } = ctx;
|
|
@@ -134,7 +134,7 @@ export async function applyCustomFtlFile(ctx, affectedPaths, stepErrors, rollbac
|
|
|
134
134
|
await snapshotFile(rollbackJournal, ftlDest);
|
|
135
135
|
}
|
|
136
136
|
await copyFile(ftlSrc, ftlDest);
|
|
137
|
-
// Sibling pushes on this list are POSIX literals (`localeJarRel`)
|
|
137
|
+
// Sibling pushes on this list are POSIX literals (`localeJarRel`). Keep
|
|
138
138
|
// the computed one in the same spelling.
|
|
139
139
|
affectedPaths.push(normalizePathSlashes(relative(engineDir, ftlDest)));
|
|
140
140
|
const chromeSubPath = resolveFtlChromeSubPath(ftlDir);
|
|
@@ -185,7 +185,7 @@ export function describeLocaleFtlJarMnRegistration(name, ftlDir, ftlFile) {
|
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
187
|
* Drops the locale jar.mn entry for `fileName` when it's a `.ftl` whose
|
|
188
|
-
* source workspace file has been deleted. Idempotent
|
|
188
|
+
* source workspace file has been deleted. Idempotent: absent entries are a
|
|
189
189
|
* no-op. Early-returns for `sharedFtl` components: the shared bundle is
|
|
190
190
|
* owned elsewhere, and dropping its jar.mn line on our component's delete
|
|
191
191
|
* would orphan every other participant.
|