@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
|
@@ -11,27 +11,16 @@ import { chunkPathspecs, ensureGit, git } from './git-base.js';
|
|
|
11
11
|
* @param filePath - Path to the file (relative to repo)
|
|
12
12
|
*/
|
|
13
13
|
export async function restoreTrackedPath(repoDir, filePath) {
|
|
14
|
-
await ensureGit();
|
|
15
14
|
await git(['restore', '--source', 'HEAD', '--staged', '--worktree', '--', filePath], repoDir);
|
|
16
15
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Removes an untracked path from disk.
|
|
19
|
-
* @param repoDir - Repository directory
|
|
20
|
-
* @param filePath - Path to the file (relative to repo)
|
|
21
|
-
*/
|
|
22
|
-
async function removeUntrackedPath(repoDir, filePath) {
|
|
23
|
-
const fullPath = join(repoDir, filePath);
|
|
24
|
-
await removeFile(fullPath);
|
|
25
|
-
}
|
|
26
16
|
/**
|
|
27
17
|
* Removes a path that is present only in the index/worktree and not in HEAD.
|
|
28
18
|
* @param repoDir - Repository directory
|
|
29
19
|
* @param filePath - Path to remove
|
|
30
20
|
*/
|
|
31
21
|
async function removeAddedPath(repoDir, filePath) {
|
|
32
|
-
await ensureGit();
|
|
33
22
|
await git(['reset', 'HEAD', '--', filePath], repoDir);
|
|
34
|
-
await
|
|
23
|
+
await removeFile(join(repoDir, filePath));
|
|
35
24
|
}
|
|
36
25
|
/**
|
|
37
26
|
* Discards a status entry according to its git state.
|
|
@@ -40,7 +29,7 @@ async function removeAddedPath(repoDir, filePath) {
|
|
|
40
29
|
*/
|
|
41
30
|
export async function discardStatusEntry(repoDir, entry) {
|
|
42
31
|
if (entry.isUntracked) {
|
|
43
|
-
await
|
|
32
|
+
await removeFile(join(repoDir, entry.file));
|
|
44
33
|
return;
|
|
45
34
|
}
|
|
46
35
|
if (entry.isRenameOrCopy && entry.originalPath) {
|
|
@@ -65,7 +54,6 @@ export async function discardStatusEntry(repoDir, entry) {
|
|
|
65
54
|
* @param files - File paths to stage (relative to repo)
|
|
66
55
|
*/
|
|
67
56
|
export async function stageFiles(repoDir, files) {
|
|
68
|
-
await ensureGit();
|
|
69
57
|
await git(['add', '--', ...files], repoDir);
|
|
70
58
|
}
|
|
71
59
|
/**
|
|
@@ -74,7 +62,6 @@ export async function stageFiles(repoDir, files) {
|
|
|
74
62
|
* @param files - File paths to unstage (relative to repo)
|
|
75
63
|
*/
|
|
76
64
|
export async function unstageFiles(repoDir, files) {
|
|
77
|
-
await ensureGit();
|
|
78
65
|
await git(['reset', 'HEAD', '--', ...files], repoDir);
|
|
79
66
|
}
|
|
80
67
|
/**
|
|
@@ -84,16 +71,15 @@ export async function unstageFiles(repoDir, files) {
|
|
|
84
71
|
* @returns true if file exists in HEAD
|
|
85
72
|
*/
|
|
86
73
|
export async function fileExistsInHead(repoDir, filePath) {
|
|
87
|
-
await ensureGit();
|
|
88
74
|
return (await git(['ls-tree', 'HEAD', '--', filePath], repoDir)).trim().length > 0;
|
|
89
75
|
}
|
|
90
76
|
/**
|
|
91
77
|
* Batched equivalent of {@link fileExistsInHead}: returns the subset of
|
|
92
78
|
* `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
|
|
94
|
-
* Firefox-sized checkout has hundreds of affected files.
|
|
79
|
+
* chunk instead of one spawn per file. This is the cold-run hot path, and
|
|
80
|
+
* a Firefox-sized checkout has hundreds of affected files.
|
|
95
81
|
*
|
|
96
|
-
* `-r` lists nested blobs by full repo-relative path
|
|
82
|
+
* `-r` lists nested blobs by full repo-relative path. `--name-only -z` makes
|
|
97
83
|
* the output a trivial NUL-split with no quoting to undo. Membership in the
|
|
98
84
|
* returned Set is exactly `await fileExistsInHead(repoDir, file)` for any
|
|
99
85
|
* non-directory `file`. Throws (via {@link git}) when HEAD itself is
|
|
@@ -107,13 +93,12 @@ export async function listTrackedInHead(repoDir, files) {
|
|
|
107
93
|
const tracked = new Set();
|
|
108
94
|
if (files.length === 0)
|
|
109
95
|
return tracked;
|
|
110
|
-
await ensureGit();
|
|
111
96
|
const wanted = new Set(files);
|
|
112
97
|
for (const chunk of chunkPathspecs(files)) {
|
|
113
98
|
const output = await git(['ls-tree', '-r', 'HEAD', '--name-only', '-z', '--', ...chunk], repoDir);
|
|
114
99
|
for (const name of output.split('\0')) {
|
|
115
100
|
// `ls-tree -r` can surface entries beyond the literal inputs only when an
|
|
116
|
-
// input is itself a directory in HEAD
|
|
101
|
+
// input is itself a directory in HEAD. Intersect with `wanted` so the
|
|
117
102
|
// result is always a subset of the requested files, never a superset.
|
|
118
103
|
if (name.length > 0 && wanted.has(name))
|
|
119
104
|
tracked.add(name);
|
|
@@ -130,10 +115,10 @@ export async function listTrackedInHead(repoDir, files) {
|
|
|
130
115
|
* Uses {@link import('../utils/process.js').exec} rather than {@link git}
|
|
131
116
|
* (which throws on a non-zero exit) because `git hash-object f1 f2 …` is
|
|
132
117
|
* all-or-nothing: it aborts at the first unreadable path and emits nothing
|
|
133
|
-
* for the rest. To keep the per-file contract
|
|
134
|
-
* only its own index line
|
|
118
|
+
* for the rest. To keep the per-file contract, where one bad path zeroes
|
|
119
|
+
* only its own index line, a chunk that does not return exactly one hash
|
|
135
120
|
* per input falls back to hashing that chunk's paths individually. A path
|
|
136
|
-
* that is still unhashable is left out of the map
|
|
121
|
+
* that is still unhashable is left out of the map. The caller applies the
|
|
137
122
|
* `0000000000` zero-hash fallback for any miss. Hashing stays in git rather
|
|
138
123
|
* than in-process so filters and `.gitattributes` are applied per path and
|
|
139
124
|
* the result cannot diverge under `core.autocrlf`/`text` attributes.
|
|
@@ -151,8 +136,8 @@ export async function hashObjectBatch(repoDir, fullPaths) {
|
|
|
151
136
|
const result = await exec('git', ['hash-object', '--', ...chunk], { cwd: repoDir });
|
|
152
137
|
const lines = result.stdout.split('\n').filter((line) => line.length > 0);
|
|
153
138
|
if (result.exitCode === 0 && lines.length === chunk.length) {
|
|
154
|
-
for (
|
|
155
|
-
hashes.set(
|
|
139
|
+
for (const [i, path] of chunk.entries()) {
|
|
140
|
+
hashes.set(path, lines[i]);
|
|
156
141
|
}
|
|
157
142
|
continue;
|
|
158
143
|
}
|
|
@@ -190,15 +175,6 @@ export async function getFileContentAtRef(repoDir, filePath, ref = 'HEAD') {
|
|
|
190
175
|
}
|
|
191
176
|
return result.stdout;
|
|
192
177
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Gets the content of a file from HEAD commit.
|
|
195
|
-
* @param repoDir - Repository directory
|
|
196
|
-
* @param filePath - Path to the file (relative to repo)
|
|
197
|
-
* @returns File content or null if file doesn't exist in HEAD
|
|
198
|
-
*/
|
|
199
|
-
export async function getFileContentFromHead(repoDir, filePath) {
|
|
200
|
-
return getFileContentAtRef(repoDir, filePath, 'HEAD');
|
|
201
|
-
}
|
|
202
178
|
/**
|
|
203
179
|
* Checks if a file is binary by looking for NUL bytes in the first 8KB.
|
|
204
180
|
* Uses the same heuristic as git.
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Private-index scope for FireForge's
|
|
2
|
+
* Private-index scope for FireForge's read-only git plumbing.
|
|
3
3
|
*
|
|
4
4
|
* `git status` and `git diff HEAD` are read-only in the sense operators care
|
|
5
|
-
* about
|
|
5
|
+
* about (they never change tracked content), but they are not read-only to
|
|
6
6
|
* git: both refresh the index's stat cache and write `.git/index` (through
|
|
7
7
|
* `.git/index.lock`) when a file's stat data has moved. That makes
|
|
8
|
-
* `fireforge verify` / `lint --per-patch` / `typecheck` a second
|
|
8
|
+
* `fireforge verify` / `lint --per-patch` / `typecheck` a second writer of
|
|
9
9
|
* the primary `engine/` checkout, even when the command was pointed at a CoW
|
|
10
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
14
|
* verdict taken across a change (`FAIL reason=inconclusive`). That refusal is
|
|
15
|
-
*
|
|
15
|
+
* correct and stays. The defect is FireForge's own read-only commands
|
|
16
16
|
* tripping it.
|
|
17
17
|
*
|
|
18
|
-
* The fix is the standard git one: point the plumbing at a
|
|
18
|
+
* The fix is the standard git one: point the plumbing at a private index
|
|
19
19
|
* (`GIT_INDEX_FILE`) seeded from the repository's own, in a temp directory.
|
|
20
|
-
* Refreshes land there and are thrown away
|
|
21
|
-
* `.git/index.lock`, which is what makes a
|
|
22
|
-
* outright rather than merely churn
|
|
20
|
+
* Refreshes land there and are thrown away. The primary `.git/index` is
|
|
21
|
+
* never touched, and neither is `.git/index.lock`, which is what makes a
|
|
22
|
+
* concurrent `git status` fail outright rather than merely churn.
|
|
23
23
|
*
|
|
24
24
|
* Fail-open by design: if the git dir or the index cannot be resolved or
|
|
25
25
|
* copied, the scope does not activate and the commands behave exactly as
|
|
@@ -43,8 +43,6 @@
|
|
|
43
43
|
* @returns `{ GIT_INDEX_FILE }` when scoped, otherwise undefined
|
|
44
44
|
*/
|
|
45
45
|
export declare function readOnlyGitIndexEnv(cwd: string): Record<string, string> | undefined;
|
|
46
|
-
/** True while a private-index scope is installed (diagnostics and tests). */
|
|
47
|
-
export declare function hasReadOnlyGitIndexScope(): boolean;
|
|
48
46
|
/**
|
|
49
47
|
* Runs `operation` with FireForge's git plumbing pointed at a private
|
|
50
48
|
* index seeded from `repoDir`'s own, so the primary checkout's
|
|
@@ -58,7 +56,7 @@ export declare function withPrivateGitIndex<T>(repoDir: string, operation: () =>
|
|
|
58
56
|
/**
|
|
59
57
|
* A private index file plus the cleanup that removes it.
|
|
60
58
|
*
|
|
61
|
-
* `env` is meant to be handed to a
|
|
59
|
+
* `env` is meant to be handed to a single git invocation (or a small
|
|
62
60
|
* sequence of them), rather than installed process-wide the way
|
|
63
61
|
* {@link withPrivateGitIndex} installs a scope.
|
|
64
62
|
*/
|
|
@@ -70,20 +68,20 @@ export interface DisposableGitIndex {
|
|
|
70
68
|
}
|
|
71
69
|
/**
|
|
72
70
|
* Mints a private index seeded from `repoDir`'s own, for a caller that
|
|
73
|
-
* needs to
|
|
71
|
+
* needs to write the index without the write being visible to anyone else.
|
|
74
72
|
*
|
|
75
73
|
* The distinction from {@link withPrivateGitIndex} matters. That one exists
|
|
76
74
|
* so a read-only command's incidental index refreshes do not touch the
|
|
77
75
|
* primary checkout, and it is process-global, non-reentrant, and fail-open,
|
|
78
76
|
* all of which are right for that job. This one serves a caller whose index
|
|
79
|
-
* write is
|
|
77
|
+
* write is intentional and whose visibility is the defect: it is per-call, so
|
|
80
78
|
* two concurrent callers cannot collide, and it never depends on an ambient
|
|
81
79
|
* scope having been installed by whichever command happens to be running.
|
|
82
80
|
*
|
|
83
81
|
* The seed is a plain copy, which is safe against a concurrent writer: git
|
|
84
82
|
* writes the index through `index.lock` and an atomic rename, so a reader
|
|
85
83
|
* sees either the old file or the new one, never a torn one. Seeding is
|
|
86
|
-
*
|
|
84
|
+
* required rather than merely tidy: an empty index makes a tracked,
|
|
87
85
|
* unmodified file look like a fresh add.
|
|
88
86
|
*
|
|
89
87
|
* @param repoDir - Repository whose index should be shadowed
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
/**
|
|
3
|
-
* Private-index scope for FireForge's
|
|
3
|
+
* Private-index scope for FireForge's read-only git plumbing.
|
|
4
4
|
*
|
|
5
5
|
* `git status` and `git diff HEAD` are read-only in the sense operators care
|
|
6
|
-
* about
|
|
6
|
+
* about (they never change tracked content), but they are not read-only to
|
|
7
7
|
* git: both refresh the index's stat cache and write `.git/index` (through
|
|
8
8
|
* `.git/index.lock`) when a file's stat data has moved. That makes
|
|
9
|
-
* `fireforge verify` / `lint --per-patch` / `typecheck` a second
|
|
9
|
+
* `fireforge verify` / `lint --per-patch` / `typecheck` a second writer of
|
|
10
10
|
* the primary `engine/` checkout, even when the command was pointed at a CoW
|
|
11
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
15
|
* verdict taken across a change (`FAIL reason=inconclusive`). That refusal is
|
|
16
|
-
*
|
|
16
|
+
* correct and stays. The defect is FireForge's own read-only commands
|
|
17
17
|
* tripping it.
|
|
18
18
|
*
|
|
19
|
-
* The fix is the standard git one: point the plumbing at a
|
|
19
|
+
* The fix is the standard git one: point the plumbing at a private index
|
|
20
20
|
* (`GIT_INDEX_FILE`) seeded from the repository's own, in a temp directory.
|
|
21
|
-
* Refreshes land there and are thrown away
|
|
22
|
-
* `.git/index.lock`, which is what makes a
|
|
23
|
-
* outright rather than merely churn
|
|
21
|
+
* Refreshes land there and are thrown away. The primary `.git/index` is
|
|
22
|
+
* never touched, and neither is `.git/index.lock`, which is what makes a
|
|
23
|
+
* concurrent `git status` fail outright rather than merely churn.
|
|
24
24
|
*
|
|
25
25
|
* Fail-open by design: if the git dir or the index cannot be resolved or
|
|
26
26
|
* copied, the scope does not activate and the commands behave exactly as
|
|
@@ -64,13 +64,9 @@ export function readOnlyGitIndexEnv(cwd) {
|
|
|
64
64
|
return undefined;
|
|
65
65
|
return { GIT_INDEX_FILE: activeScope.indexFile };
|
|
66
66
|
}
|
|
67
|
-
/** True while a private-index scope is installed (diagnostics and tests). */
|
|
68
|
-
export function hasReadOnlyGitIndexScope() {
|
|
69
|
-
return activeScope !== undefined;
|
|
70
|
-
}
|
|
71
67
|
/**
|
|
72
68
|
* Resolves a repository's git directory. Returns undefined for anything
|
|
73
|
-
* that is not a readable git checkout
|
|
69
|
+
* that is not a readable git checkout. `engine/` is not always one
|
|
74
70
|
* (`fireforge download` extracts a source tarball).
|
|
75
71
|
*/
|
|
76
72
|
async function resolveGitDir(repoDir) {
|
|
@@ -119,20 +115,20 @@ export async function withPrivateGitIndex(repoDir, operation) {
|
|
|
119
115
|
}
|
|
120
116
|
/**
|
|
121
117
|
* Mints a private index seeded from `repoDir`'s own, for a caller that
|
|
122
|
-
* needs to
|
|
118
|
+
* needs to write the index without the write being visible to anyone else.
|
|
123
119
|
*
|
|
124
120
|
* The distinction from {@link withPrivateGitIndex} matters. That one exists
|
|
125
121
|
* so a read-only command's incidental index refreshes do not touch the
|
|
126
122
|
* primary checkout, and it is process-global, non-reentrant, and fail-open,
|
|
127
123
|
* all of which are right for that job. This one serves a caller whose index
|
|
128
|
-
* write is
|
|
124
|
+
* write is intentional and whose visibility is the defect: it is per-call, so
|
|
129
125
|
* two concurrent callers cannot collide, and it never depends on an ambient
|
|
130
126
|
* scope having been installed by whichever command happens to be running.
|
|
131
127
|
*
|
|
132
128
|
* The seed is a plain copy, which is safe against a concurrent writer: git
|
|
133
129
|
* writes the index through `index.lock` and an atomic rename, so a reader
|
|
134
130
|
* sees either the old file or the new one, never a torn one. Seeding is
|
|
135
|
-
*
|
|
131
|
+
* required rather than merely tidy: an empty index makes a tracked,
|
|
136
132
|
* unmodified file look like a fresh add.
|
|
137
133
|
*
|
|
138
134
|
* @param repoDir - Repository whose index should be shadowed
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { GitStatusEntry } from './git-base.js';
|
|
2
2
|
/**
|
|
3
3
|
* Parses NUL-delimited porcelain status output.
|
|
4
|
+
*
|
|
5
|
+
* A rename or copy occupies two NUL records (`XY new\0old\0`), and the `R`/`C`
|
|
6
|
+
* may sit in either column: git >= 2.18 detects renames in the worktree too
|
|
7
|
+
* (`status.renames`), emitting ` R new\0old\0` for an unstaged rename and
|
|
8
|
+
* `RM`/`R ` for a staged one. Only consuming the second record for an index
|
|
9
|
+
* `R`/`C` turned the worktree form's `old` field into a bogus extra entry
|
|
10
|
+
* whose status was whatever its first two path characters happened to be.
|
|
4
11
|
* @param output - Raw git status output
|
|
5
12
|
* @returns Parsed entries
|
|
6
13
|
*/
|
|
@@ -23,8 +30,8 @@ export declare function resolveMaxUntrackedFilesPerDir(): number;
|
|
|
23
30
|
*
|
|
24
31
|
* Expansion is capped per directory (FIREFORGE_MAX_UNTRACKED_FILES, default
|
|
25
32
|
* 5000) with a warning on overflow. Without the cap, `reset --dry-run` after
|
|
26
|
-
* an interrupted download
|
|
27
|
-
* untracked
|
|
33
|
+
* an interrupted download (unborn HEAD, the entire ~300k file tree
|
|
34
|
+
* untracked) enumerates and prints every file.
|
|
28
35
|
*
|
|
29
36
|
* @param repoDir - Repository directory
|
|
30
37
|
* @param entries - Parsed status entries
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
2
|
import { warn } from '../utils/logger.js';
|
|
3
|
-
import {
|
|
3
|
+
import { git } from './git-base.js';
|
|
4
|
+
/**
|
|
5
|
+
* True when a porcelain status column carries a rename or copy, i.e. the
|
|
6
|
+
* record is followed by a second NUL-terminated field holding the original
|
|
7
|
+
* path.
|
|
8
|
+
* @param column - A single status column character
|
|
9
|
+
* @returns Whether the column is `R` or `C`
|
|
10
|
+
*/
|
|
11
|
+
function isRenameOrCopyColumn(column) {
|
|
12
|
+
return column === 'R' || column === 'C';
|
|
13
|
+
}
|
|
4
14
|
/**
|
|
5
15
|
* Parses NUL-delimited porcelain status output.
|
|
16
|
+
*
|
|
17
|
+
* A rename or copy occupies two NUL records (`XY new\0old\0`), and the `R`/`C`
|
|
18
|
+
* may sit in either column: git >= 2.18 detects renames in the worktree too
|
|
19
|
+
* (`status.renames`), emitting ` R new\0old\0` for an unstaged rename and
|
|
20
|
+
* `RM`/`R ` for a staged one. Only consuming the second record for an index
|
|
21
|
+
* `R`/`C` turned the worktree form's `old` field into a bogus extra entry
|
|
22
|
+
* whose status was whatever its first two path characters happened to be.
|
|
6
23
|
* @param output - Raw git status output
|
|
7
24
|
* @returns Parsed entries
|
|
8
25
|
*/
|
|
@@ -18,7 +35,7 @@ export function parsePorcelainStatus(output) {
|
|
|
18
35
|
const worktreeStatus = record[1] ?? ' ';
|
|
19
36
|
const status = `${indexStatus}${worktreeStatus}`;
|
|
20
37
|
const pathField = record.slice(3);
|
|
21
|
-
const isRenameOrCopy = indexStatus
|
|
38
|
+
const isRenameOrCopy = isRenameOrCopyColumn(indexStatus) || isRenameOrCopyColumn(worktreeStatus);
|
|
22
39
|
const originalPath = isRenameOrCopy ? records[i + 1] : undefined;
|
|
23
40
|
if (isRenameOrCopy) {
|
|
24
41
|
i++;
|
|
@@ -42,7 +59,6 @@ export function parsePorcelainStatus(output) {
|
|
|
42
59
|
* @returns Parsed git status entries
|
|
43
60
|
*/
|
|
44
61
|
export async function getWorkingTreeStatus(repoDir) {
|
|
45
|
-
await ensureGit();
|
|
46
62
|
return parsePorcelainStatus(await git(['status', '--porcelain=v1', '-z'], repoDir));
|
|
47
63
|
}
|
|
48
64
|
/** Default per-directory cap for untracked-directory expansion. */
|
|
@@ -57,7 +73,7 @@ export function resolveMaxUntrackedFilesPerDir() {
|
|
|
57
73
|
return DEFAULT_MAX_UNTRACKED_FILES_PER_DIR;
|
|
58
74
|
const parsed = Number.parseInt(raw, 10);
|
|
59
75
|
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
60
|
-
warn(`Ignoring FIREFORGE_MAX_UNTRACKED_FILES="${raw}" — expected a positive integer. Falling back to ${
|
|
76
|
+
warn(`Ignoring FIREFORGE_MAX_UNTRACKED_FILES="${raw}" — expected a positive integer. Falling back to ${DEFAULT_MAX_UNTRACKED_FILES_PER_DIR}.`);
|
|
61
77
|
return DEFAULT_MAX_UNTRACKED_FILES_PER_DIR;
|
|
62
78
|
}
|
|
63
79
|
return parsed;
|
|
@@ -68,8 +84,8 @@ export function resolveMaxUntrackedFilesPerDir() {
|
|
|
68
84
|
*
|
|
69
85
|
* Expansion is capped per directory (FIREFORGE_MAX_UNTRACKED_FILES, default
|
|
70
86
|
* 5000) with a warning on overflow. Without the cap, `reset --dry-run` after
|
|
71
|
-
* an interrupted download
|
|
72
|
-
* untracked
|
|
87
|
+
* an interrupted download (unborn HEAD, the entire ~300k file tree
|
|
88
|
+
* untracked) enumerates and prints every file.
|
|
73
89
|
*
|
|
74
90
|
* @param repoDir - Repository directory
|
|
75
91
|
* @param entries - Parsed status entries
|
|
@@ -86,7 +102,7 @@ export async function expandUntrackedDirectoryEntries(repoDir, entries) {
|
|
|
86
102
|
}
|
|
87
103
|
const individualFiles = await getUntrackedFilesInDir(repoDir, entry.file);
|
|
88
104
|
if (individualFiles.length > maxPerDir) {
|
|
89
|
-
warn(`Untracked directory ${entry.file} contains ${
|
|
105
|
+
warn(`Untracked directory ${entry.file} contains ${individualFiles.length} files — only the first ${maxPerDir} are listed. Add a .gitignore entry or clean the directory.`);
|
|
90
106
|
}
|
|
91
107
|
for (const file of individualFiles.slice(0, maxPerDir)) {
|
|
92
108
|
expanded.push({
|
|
@@ -108,7 +124,6 @@ export async function expandUntrackedDirectoryEntries(repoDir, entries) {
|
|
|
108
124
|
* @returns List of untracked file paths
|
|
109
125
|
*/
|
|
110
126
|
export async function getUntrackedFiles(repoDir) {
|
|
111
|
-
await ensureGit();
|
|
112
127
|
// Use git ls-files to get all untracked files, which properly expands directories
|
|
113
128
|
const output = await git(['ls-files', '--others', '--exclude-standard'], repoDir);
|
|
114
129
|
return output.split('\n').filter((line) => line.trim().length > 0);
|
|
@@ -121,7 +136,6 @@ export async function getUntrackedFiles(repoDir) {
|
|
|
121
136
|
* @returns List of untracked file paths relative to repo root
|
|
122
137
|
*/
|
|
123
138
|
export async function getUntrackedFilesInDir(repoDir, dir) {
|
|
124
|
-
await ensureGit();
|
|
125
139
|
const output = await git(['ls-files', '--others', '--exclude-standard', '--', dir], repoDir);
|
|
126
140
|
return output.split('\n').filter((line) => line.trim().length > 0);
|
|
127
141
|
}
|
|
@@ -133,7 +147,6 @@ export async function getUntrackedFilesInDir(repoDir, dir) {
|
|
|
133
147
|
* @returns List of modified file paths relative to repo root
|
|
134
148
|
*/
|
|
135
149
|
export async function getModifiedFilesInDir(repoDir, dir) {
|
|
136
|
-
await ensureGit();
|
|
137
150
|
const output = await git(['diff', '--name-only', 'HEAD', '--', dir], repoDir);
|
|
138
151
|
return output.split('\n').filter((line) => line.trim().length > 0);
|
|
139
152
|
}
|
|
@@ -146,7 +159,6 @@ export async function getModifiedFilesInDir(repoDir, dir) {
|
|
|
146
159
|
export async function getDirtyFiles(repoDir, files) {
|
|
147
160
|
if (files.length === 0)
|
|
148
161
|
return [];
|
|
149
|
-
await ensureGit();
|
|
150
162
|
// Check both staged and unstaged changes for the given files
|
|
151
163
|
const trackedOutput = await git(['diff', '--name-only', 'HEAD', '--', ...files], repoDir);
|
|
152
164
|
const tracked = trackedOutput.split('\n').filter((line) => line.trim().length > 0);
|
package/dist/src/core/git.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export declare function isGitRepository(dir: string): Promise<boolean>;
|
|
|
17
17
|
export declare function ensureOriginRemote(dir: string): Promise<void>;
|
|
18
18
|
/**
|
|
19
19
|
* Stages all files in the repository.
|
|
20
|
-
* Tries a monolithic `git add -A` first
|
|
20
|
+
* Tries a monolithic `git add -A` first. If that times out, falls back to
|
|
21
21
|
* directory-by-directory staged adds.
|
|
22
22
|
*/
|
|
23
23
|
export declare function stageAllFiles(dir: string, options?: {
|
|
@@ -56,8 +56,8 @@ export declare function applyPatch(patchPath: string, repoDir: string, options?:
|
|
|
56
56
|
* @param patchPath - Path to the patch file
|
|
57
57
|
* @param repoDir - Repository directory
|
|
58
58
|
* @param options.reject - Fall back to `git apply --reject`
|
|
59
|
-
* @param options.protectedFiles - Files that must
|
|
60
|
-
* recovery step. Callers applying a patch
|
|
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
61
|
* touched by previously applied patches in the same run: two overlapping
|
|
62
62
|
* patches (an `--allow-overlap` queue) share files, and a blanket
|
|
63
63
|
* `checkout HEAD` would wipe the earlier patch's changes from the shared
|
|
@@ -103,12 +103,6 @@ export declare function getCurrentBranch(repoDir: string): Promise<string>;
|
|
|
103
103
|
* @param repoDir - Repository directory
|
|
104
104
|
*/
|
|
105
105
|
export declare function resetChanges(repoDir: string): Promise<void>;
|
|
106
|
-
/**
|
|
107
|
-
* Creates a commit with all current changes.
|
|
108
|
-
* @param repoDir - Repository directory
|
|
109
|
-
* @param message - Commit message
|
|
110
|
-
*/
|
|
111
|
-
export declare function commit(repoDir: string, message: string): Promise<void>;
|
|
112
106
|
/**
|
|
113
107
|
* Gets the status of files with their status codes.
|
|
114
108
|
* @param repoDir - Repository directory
|
package/dist/src/core/git.js
CHANGED
|
@@ -41,8 +41,8 @@ export async function ensureOriginRemote(dir) {
|
|
|
41
41
|
const GIT_ADD_ENV = { GIT_INDEX_THREADS: '0' };
|
|
42
42
|
/**
|
|
43
43
|
* Returns true when the error looks like a process killed by the spawn
|
|
44
|
-
* timeout (SIGTERM → exit code 143)
|
|
45
|
-
* `AbortSignal.timeout
|
|
44
|
+
* timeout (SIGTERM → exit code 143) or an AbortError raised by
|
|
45
|
+
* `AbortSignal.timeout`. Node's `child_process` layer rejects with an
|
|
46
46
|
* AbortError when the signal fires, so both shapes have to be recognised.
|
|
47
47
|
*/
|
|
48
48
|
function isTimeoutError(error) {
|
|
@@ -76,7 +76,7 @@ async function cleanupIndexLock(dir) {
|
|
|
76
76
|
* other exclusion mechanism git considers, e.g. `.git/info/exclude`,
|
|
77
77
|
* core.excludesFile). Used by the chunked staging fallback to skip entries
|
|
78
78
|
* that would otherwise fail `git add -- <path>` with the fatal "The
|
|
79
|
-
* following paths are ignored by one of your .gitignore files" error
|
|
79
|
+
* following paths are ignored by one of your .gitignore files" error, a
|
|
80
80
|
* state the monolithic `git add -A` path silently handles. A Firefox
|
|
81
81
|
* checkout's top-level `.vscode/` is the common case: without this, the
|
|
82
82
|
* chunked invocation aborts the whole fallback and turns a recoverable
|
|
@@ -93,7 +93,7 @@ async function isPathIgnored(dir, relativePath) {
|
|
|
93
93
|
return true;
|
|
94
94
|
if (result.exitCode === 1)
|
|
95
95
|
return false;
|
|
96
|
-
// Any other shape is "we don't know"
|
|
96
|
+
// Any other shape is "we don't know", so let the caller proceed and
|
|
97
97
|
// surface the real error if `git add` rejects the path.
|
|
98
98
|
return false;
|
|
99
99
|
}
|
|
@@ -104,7 +104,7 @@ async function isPathIgnored(dir, relativePath) {
|
|
|
104
104
|
*
|
|
105
105
|
* A chunked pass that hits its own timeout raises a typed
|
|
106
106
|
* {@link GitIndexingTimeoutError} rather than an opaque `AbortError: The
|
|
107
|
-
* operation was aborted
|
|
107
|
+
* operation was aborted`. The typed error carries the environment-variable
|
|
108
108
|
* override so the operator can extend the budget and re-run.
|
|
109
109
|
*/
|
|
110
110
|
async function stageAllFilesChunked(dir, scan, options = {}) {
|
|
@@ -134,7 +134,7 @@ async function stageAllFilesChunked(dir, scan, options = {}) {
|
|
|
134
134
|
options.onProgress?.(`Staging directory ${stagedDirectories}/${directories.length}: ${dirName}/...`);
|
|
135
135
|
await runChunk(['add', '--', dirName], dirName);
|
|
136
136
|
}
|
|
137
|
-
// Stage any top-level files (excluding gitignored ones
|
|
137
|
+
// Stage any top-level files (excluding gitignored ones, because `git add`
|
|
138
138
|
// on an explicit ignored path errors out, which would otherwise
|
|
139
139
|
// abort the chunked fallback after the monolithic path has already
|
|
140
140
|
// timed out).
|
|
@@ -154,7 +154,7 @@ async function stageAllFilesChunked(dir, scan, options = {}) {
|
|
|
154
154
|
/**
|
|
155
155
|
* Interval between heartbeat progress messages during the monolithic
|
|
156
156
|
* `git add -A`. On a fresh ~600 MB Firefox tree the monolithic add runs
|
|
157
|
-
* 60
|
|
157
|
+
* 60 to 120 seconds, during which git emits nothing to stdout/stderr. Without a
|
|
158
158
|
* heartbeat the CLI spinner stays pinned on "Indexing Firefox source …" for
|
|
159
159
|
* the full window and looks hung, which invites a SIGINT mid-way.
|
|
160
160
|
*/
|
|
@@ -175,7 +175,7 @@ async function scanTopLevelSource(dir) {
|
|
|
175
175
|
}
|
|
176
176
|
/**
|
|
177
177
|
* Stages all files in the repository.
|
|
178
|
-
* Tries a monolithic `git add -A` first
|
|
178
|
+
* Tries a monolithic `git add -A` first. If that times out, falls back to
|
|
179
179
|
* directory-by-directory staged adds.
|
|
180
180
|
*/
|
|
181
181
|
export async function stageAllFiles(dir, options = {}) {
|
|
@@ -184,7 +184,7 @@ export async function stageAllFiles(dir, options = {}) {
|
|
|
184
184
|
reportProgress?.('Scanning Firefox source tree before indexing...');
|
|
185
185
|
const scan = await scanTopLevelSource(dir);
|
|
186
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'}`);
|
|
187
|
-
// The heartbeat tracks a
|
|
187
|
+
// The heartbeat tracks a per-phase start timestamp and labels each tick
|
|
188
188
|
// with the phase. A single start time set at function entry reports
|
|
189
189
|
// cumulative elapsed for the whole `stageAllFiles` invocation, so after a
|
|
190
190
|
// monolithic timeout the chunked-phase ticks name numbers that already
|
|
@@ -225,15 +225,8 @@ export async function stageAllFiles(dir, options = {}) {
|
|
|
225
225
|
// monolithic budget forward.
|
|
226
226
|
phase = 'chunked';
|
|
227
227
|
phaseStartedAt = Date.now();
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
reportProgress?.('Git phase complete: chunked source indexing finished.');
|
|
231
|
-
}
|
|
232
|
-
catch (error) {
|
|
233
|
-
if (error instanceof GitIndexingTimeoutError)
|
|
234
|
-
throw error;
|
|
235
|
-
throw error;
|
|
236
|
-
}
|
|
228
|
+
await stageAllFilesChunked(dir, scan, options);
|
|
229
|
+
reportProgress?.('Git phase complete: chunked source indexing finished.');
|
|
237
230
|
}
|
|
238
231
|
finally {
|
|
239
232
|
if (heartbeatTimer)
|
|
@@ -285,10 +278,20 @@ export async function initRepository(dir, branchName = 'main', options = {}) {
|
|
|
285
278
|
reportProgress('Configuring origin remote for build compatibility...');
|
|
286
279
|
await git(['remote', 'add', 'origin', 'https://github.com/mozilla-firefox/firefox'], dir);
|
|
287
280
|
reportProgress('Git phase complete: source git repository metadata initialized.');
|
|
281
|
+
await stageAndCommitSource(dir, reportProgress, 'Indexing Firefox source with git add -A (this can take several minutes on large trees)...');
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The tail shared by {@link initRepository} and {@link resumeRepository}:
|
|
285
|
+
* normalizes the Firefox ignore files, stages the whole tree, and creates
|
|
286
|
+
* the initial source commit. Index-lock failures on either git step are
|
|
287
|
+
* wrapped into the typed lock error so both entry points report them the
|
|
288
|
+
* same way.
|
|
289
|
+
*/
|
|
290
|
+
async function stageAndCommitSource(dir, reportProgress, stagingMessage) {
|
|
288
291
|
reportProgress('Normalizing Firefox ignore files for Git-backed mach lint compatibility...');
|
|
289
292
|
await ensureFirefoxIgnorefileCompatibility(dir);
|
|
290
293
|
// Add all files
|
|
291
|
-
reportProgress(
|
|
294
|
+
reportProgress(stagingMessage);
|
|
292
295
|
await assertNoGitIndexLock(dir);
|
|
293
296
|
try {
|
|
294
297
|
await stageAllFiles(dir, { onProgress: reportProgress });
|
|
@@ -310,7 +313,6 @@ export async function initRepository(dir, branchName = 'main', options = {}) {
|
|
|
310
313
|
* cleans up stale locks, stages all files, and creates the initial commit.
|
|
311
314
|
*/
|
|
312
315
|
export async function resumeRepository(dir, options = {}) {
|
|
313
|
-
await ensureGit();
|
|
314
316
|
const reportProgress = options.onProgress ?? (() => { });
|
|
315
317
|
if (!(await isGitRepository(dir))) {
|
|
316
318
|
throw new GitError('Not a git repository', 'resume');
|
|
@@ -324,24 +326,7 @@ export async function resumeRepository(dir, options = {}) {
|
|
|
324
326
|
await cleanupIndexLock(dir);
|
|
325
327
|
// Ensure origin remote exists (may have been added before the interrupt)
|
|
326
328
|
await ensureOriginRemote(dir);
|
|
327
|
-
reportProgress
|
|
328
|
-
await ensureFirefoxIgnorefileCompatibility(dir);
|
|
329
|
-
// Stage all files
|
|
330
|
-
reportProgress('Indexing Firefox source (resuming)...');
|
|
331
|
-
await assertNoGitIndexLock(dir);
|
|
332
|
-
try {
|
|
333
|
-
await stageAllFiles(dir, { onProgress: reportProgress });
|
|
334
|
-
}
|
|
335
|
-
catch (error) {
|
|
336
|
-
throw await maybeWrapIndexLockError(dir, error);
|
|
337
|
-
}
|
|
338
|
-
// Create initial commit
|
|
339
|
-
try {
|
|
340
|
-
await createInitialSourceCommit(dir, reportProgress);
|
|
341
|
-
}
|
|
342
|
-
catch (error) {
|
|
343
|
-
throw await maybeWrapIndexLockError(dir, error);
|
|
344
|
-
}
|
|
329
|
+
await stageAndCommitSource(dir, reportProgress, 'Indexing Firefox source (resuming)...');
|
|
345
330
|
}
|
|
346
331
|
async function assertNoGitIndexLock(dir) {
|
|
347
332
|
const lockPath = join(dir, '.git', 'index.lock');
|
|
@@ -407,8 +392,8 @@ export async function applyPatch(patchPath, repoDir, options = {}) {
|
|
|
407
392
|
* @param patchPath - Path to the patch file
|
|
408
393
|
* @param repoDir - Repository directory
|
|
409
394
|
* @param options.reject - Fall back to `git apply --reject`
|
|
410
|
-
* @param options.protectedFiles - Files that must
|
|
411
|
-
* recovery step. Callers applying a patch
|
|
395
|
+
* @param options.protectedFiles - Files that must not be reset to HEAD by the
|
|
396
|
+
* recovery step. Callers applying a patch queue pass the files already
|
|
412
397
|
* touched by previously applied patches in the same run: two overlapping
|
|
413
398
|
* patches (an `--allow-overlap` queue) share files, and a blanket
|
|
414
399
|
* `checkout HEAD` would wipe the earlier patch's changes from the shared
|
|
@@ -439,14 +424,14 @@ export async function applyPatchIdempotent(patchPath, repoDir, options = {}) {
|
|
|
439
424
|
await applyPatch(patchPath, repoDir, options);
|
|
440
425
|
}
|
|
441
426
|
/**
|
|
442
|
-
* Restores `files` to their HEAD state, deleting files the patch would
|
|
443
|
-
* (present on disk from a partial apply but absent in HEAD
|
|
427
|
+
* Restores `files` to their HEAD state, deleting files the patch would create
|
|
428
|
+
* (present on disk from a partial apply but absent in HEAD, where
|
|
444
429
|
* `git checkout HEAD --` fails, and ignoring that failure leaves stray files
|
|
445
430
|
* that make the subsequent forward apply die with "already exists" and no
|
|
446
431
|
* hint why).
|
|
447
432
|
*
|
|
448
433
|
* Every git invocation is chunked via {@link chunkPathspecs} so a very large
|
|
449
|
-
* patch cannot hit `E2BIG`, and every exit code is checked
|
|
434
|
+
* patch cannot hit `E2BIG`, and every exit code is checked. A silent failed
|
|
450
435
|
* restore is the confusing state this recovery step exists to prevent.
|
|
451
436
|
*/
|
|
452
437
|
async function restoreFilesToHead(repoDir, patchPath, files) {
|
|
@@ -499,7 +484,6 @@ export async function reversePatch(patchPath, repoDir) {
|
|
|
499
484
|
* @returns True if there are uncommitted changes
|
|
500
485
|
*/
|
|
501
486
|
export async function hasChanges(repoDir) {
|
|
502
|
-
await ensureGit();
|
|
503
487
|
const entries = await getWorkingTreeStatus(repoDir);
|
|
504
488
|
return entries.length > 0;
|
|
505
489
|
}
|
|
@@ -518,7 +502,6 @@ export function isMissingHeadError(error) {
|
|
|
518
502
|
* @returns Commit hash
|
|
519
503
|
*/
|
|
520
504
|
export async function getHead(repoDir) {
|
|
521
|
-
await ensureGit();
|
|
522
505
|
const output = await git(['rev-parse', 'HEAD'], repoDir);
|
|
523
506
|
return output.trim();
|
|
524
507
|
}
|
|
@@ -528,7 +511,6 @@ export async function getHead(repoDir) {
|
|
|
528
511
|
* @returns Branch name
|
|
529
512
|
*/
|
|
530
513
|
export async function getCurrentBranch(repoDir) {
|
|
531
|
-
await ensureGit();
|
|
532
514
|
const output = await git(['rev-parse', '--abbrev-ref', 'HEAD'], repoDir);
|
|
533
515
|
return output.trim();
|
|
534
516
|
}
|
|
@@ -537,7 +519,6 @@ export async function getCurrentBranch(repoDir) {
|
|
|
537
519
|
* @param repoDir - Repository directory
|
|
538
520
|
*/
|
|
539
521
|
export async function resetChanges(repoDir) {
|
|
540
|
-
await ensureGit();
|
|
541
522
|
try {
|
|
542
523
|
await git(['reset', '--hard', 'HEAD'], repoDir);
|
|
543
524
|
}
|
|
@@ -546,16 +527,6 @@ export async function resetChanges(repoDir) {
|
|
|
546
527
|
}
|
|
547
528
|
await git(['clean', '-fd'], repoDir);
|
|
548
529
|
}
|
|
549
|
-
/**
|
|
550
|
-
* Creates a commit with all current changes.
|
|
551
|
-
* @param repoDir - Repository directory
|
|
552
|
-
* @param message - Commit message
|
|
553
|
-
*/
|
|
554
|
-
export async function commit(repoDir, message) {
|
|
555
|
-
await ensureGit();
|
|
556
|
-
await stageAllFiles(repoDir);
|
|
557
|
-
await git(['commit', '-m', message], repoDir);
|
|
558
|
-
}
|
|
559
530
|
/**
|
|
560
531
|
* Gets the status of files with their status codes.
|
|
561
532
|
* @param repoDir - Repository directory
|