@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
|
@@ -1,52 +1,28 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { basename, join } from 'node:path';
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
5
4
|
import { GitError } from '../errors/git.js';
|
|
6
5
|
import { toError } from '../utils/errors.js';
|
|
7
|
-
import { pathExists
|
|
6
|
+
import { pathExists } from '../utils/fs.js';
|
|
8
7
|
import { verbose } from '../utils/logger.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { fileExistsInHead, hashObjectBatch,
|
|
12
|
-
import { mintDisposableGitIndex
|
|
8
|
+
import { chunkPathspecs, git } from './git-base.js';
|
|
9
|
+
import { readNewFileContent, withForcedBinaryAttribute } from './git-diff-new-file.js';
|
|
10
|
+
import { fileExistsInHead, hashObjectBatch, listTrackedInHead } from './git-file-ops.js';
|
|
11
|
+
import { mintDisposableGitIndex } from './git-readonly-index.js';
|
|
13
12
|
import { getUntrackedFiles, getUntrackedFilesInDir } from './git-status.js';
|
|
14
|
-
async function execGitWithAllowedExitCodes(repoDir, args, allowedExitCodes = [0], envOverride) {
|
|
15
|
-
// Honour a read-only command's private-index scope: the `--intent-to-add`
|
|
16
|
-
// / `update-index` staging dance below is a genuine
|
|
17
|
-
// index write, and inside a read-only command it must land on the
|
|
18
|
-
// private index, not the primary checkout's.
|
|
19
|
-
//
|
|
20
|
-
// `envOverride` wins over that scope: a caller that minted an index for
|
|
21
|
-
// one specific invocation has said something more specific than the
|
|
22
|
-
// ambient scope did.
|
|
23
|
-
const readOnlyIndexEnv = readOnlyGitIndexEnv(repoDir);
|
|
24
|
-
const env = readOnlyIndexEnv !== undefined || envOverride !== undefined
|
|
25
|
-
? { ...readOnlyIndexEnv, ...envOverride }
|
|
26
|
-
: undefined;
|
|
27
|
-
const result = await exec('git', args, {
|
|
28
|
-
cwd: repoDir,
|
|
29
|
-
...(env !== undefined ? { env } : {}),
|
|
30
|
-
});
|
|
31
|
-
if (allowedExitCodes.includes(result.exitCode)) {
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
throw new GitError(result.stderr.trim() || 'Git command failed', args.join(' '));
|
|
35
|
-
}
|
|
36
13
|
/**
|
|
37
14
|
* Gets the diff for a specific file.
|
|
38
15
|
*
|
|
39
16
|
* `--binary` is load-bearing: without it git degrades a binary file's section
|
|
40
17
|
* to the informational `Binary files a/x and b/x differ`, which carries none
|
|
41
18
|
* of the bytes and cannot be replayed by `git apply`. It only expands the
|
|
42
|
-
*
|
|
19
|
+
* binary section's index line to full hashes (text sections keep their
|
|
43
20
|
* abbreviated form), so text output stays byte-identical.
|
|
44
21
|
* @param repoDir - Repository directory
|
|
45
22
|
* @param filePath - Path to the file (relative to repo)
|
|
46
23
|
* @returns Diff content
|
|
47
24
|
*/
|
|
48
25
|
export async function getFileDiff(repoDir, filePath) {
|
|
49
|
-
await ensureGit();
|
|
50
26
|
return git(['diff', '--binary', 'HEAD', '--', filePath], repoDir);
|
|
51
27
|
}
|
|
52
28
|
/**
|
|
@@ -66,7 +42,7 @@ function abbreviateBlobHash(fullHash) {
|
|
|
66
42
|
/**
|
|
67
43
|
* Pure formatter for a new (untracked) file's unified diff. Shared by the
|
|
68
44
|
* batched cold-run path in {@link getDiffForFilesAgainstHead} and the
|
|
69
|
-
* standalone {@link generateNewFileDiff}
|
|
45
|
+
* standalone {@link generateNewFileDiff}. The only thing that differs is
|
|
70
46
|
* where `blobHash` comes from (a single batched `git hash-object` vs a
|
|
71
47
|
* per-file one), never the formatting. Preserves the empty-file form, the
|
|
72
48
|
* trailing-newline handling, and the "No newline at end of file" marker
|
|
@@ -113,22 +89,36 @@ function buildNewFileDiffBody(filePath, content, blobHash) {
|
|
|
113
89
|
return diffLines.join('\n') + '\n';
|
|
114
90
|
}
|
|
115
91
|
/**
|
|
116
|
-
*
|
|
92
|
+
* Defensive check shared by the new-file readers: a directory here means a
|
|
93
|
+
* caller bypassed the expansion layers and handed the leaf reader a path it
|
|
94
|
+
* cannot read. Surfaces an actionable message naming the offending path
|
|
95
|
+
* rather than the raw `EISDIR` the read would throw. This is a recurring bug
|
|
96
|
+
* class, hence the guard at every leaf.
|
|
97
|
+
* @param repoDir - Repository directory
|
|
98
|
+
* @param filePath - Path to the file (relative to repo)
|
|
99
|
+
*/
|
|
100
|
+
async function rejectDirectory(repoDir, filePath) {
|
|
101
|
+
const fileStat = await stat(join(repoDir, filePath));
|
|
102
|
+
if (fileStat.isDirectory()) {
|
|
103
|
+
throw new GitError(`expected a file but found a directory at '${filePath}' — caller must expand directory entries before diffing`, `hash-object ${filePath}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generates a unified diff for a new (untracked) file. A file that is binary
|
|
108
|
+
* or not valid UTF-8 (see {@link readNewFileContent}) is routed through
|
|
109
|
+
* {@link generateBinaryFilePatch} instead, because a text body cannot carry
|
|
110
|
+
* its bytes faithfully.
|
|
117
111
|
* @param repoDir - Repository directory
|
|
118
112
|
* @param filePath - Path to the file (relative to repo)
|
|
119
113
|
* @returns Diff content in unified diff format
|
|
120
114
|
*/
|
|
121
115
|
export async function generateNewFileDiff(repoDir, filePath) {
|
|
122
116
|
const fullPath = join(repoDir, filePath);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const fileStat = await stat(fullPath);
|
|
128
|
-
if (fileStat.isDirectory()) {
|
|
129
|
-
throw new GitError(`expected a file but found a directory at '${filePath}' — caller must expand directory entries before diffing`, `hash-object ${filePath}`);
|
|
117
|
+
await rejectDirectory(repoDir, filePath);
|
|
118
|
+
const file = await readNewFileContent(repoDir, filePath);
|
|
119
|
+
if (file.binary) {
|
|
120
|
+
return generateBinaryFilePatch(repoDir, filePath);
|
|
130
121
|
}
|
|
131
|
-
const content = await readText(fullPath);
|
|
132
122
|
// Compute the abbreviated git blob hash for the index line
|
|
133
123
|
let blobHash = '0000000000';
|
|
134
124
|
try {
|
|
@@ -138,7 +128,7 @@ export async function generateNewFileDiff(repoDir, filePath) {
|
|
|
138
128
|
catch (error) {
|
|
139
129
|
verbose(`git hash-object failed for ${filePath}; falling back to zero blob hash: ${toError(error).message}`);
|
|
140
130
|
}
|
|
141
|
-
return buildNewFileDiffBody(filePath, content, blobHash);
|
|
131
|
+
return buildNewFileDiffBody(filePath, file.content, blobHash);
|
|
142
132
|
}
|
|
143
133
|
/**
|
|
144
134
|
* Generates a patch for a file.
|
|
@@ -150,7 +140,6 @@ export async function generateNewFileDiff(repoDir, filePath) {
|
|
|
150
140
|
* @returns Diff content in unified diff format
|
|
151
141
|
*/
|
|
152
142
|
export async function generateFullFilePatch(repoDir, filePath) {
|
|
153
|
-
await ensureGit();
|
|
154
143
|
// If file exists in HEAD, use standard git diff HEAD -- <file>
|
|
155
144
|
// This generates a contextual diff that is safer for rebasing
|
|
156
145
|
if (await fileExistsInHead(repoDir, filePath)) {
|
|
@@ -159,76 +148,26 @@ export async function generateFullFilePatch(repoDir, filePath) {
|
|
|
159
148
|
// If file is new/untracked, use the full-file "new file" format
|
|
160
149
|
return generateNewFileDiff(repoDir, filePath);
|
|
161
150
|
}
|
|
162
|
-
/**
|
|
163
|
-
* Generates a unified diff between base content and current file content.
|
|
164
|
-
* @param repoDir - Repository directory
|
|
165
|
-
* @param filePath - Path to the file (relative to repo)
|
|
166
|
-
* @param baseContent - The base content to diff against
|
|
167
|
-
* @returns Unified diff in git format
|
|
168
|
-
*/
|
|
169
|
-
export async function generateModificationDiff(repoDir, filePath, baseContent) {
|
|
170
|
-
const fullPath = join(repoDir, filePath);
|
|
171
|
-
const currentContent = await readText(fullPath);
|
|
172
|
-
// If contents are identical, return empty diff
|
|
173
|
-
if (baseContent === currentContent) {
|
|
174
|
-
return '';
|
|
175
|
-
}
|
|
176
|
-
const tempDir = await mkdtemp(join(tmpdir(), 'fireforge-diff-'));
|
|
177
|
-
const tempFile = join(tempDir, basename(filePath));
|
|
178
|
-
try {
|
|
179
|
-
await writeFile(tempFile, baseContent);
|
|
180
|
-
// git diff --no-index exits code 1 when files differ — that's normal
|
|
181
|
-
const result = await execGitWithAllowedExitCodes(repoDir, ['diff', '--no-index', '--', tempFile, fullPath], [0, 1]);
|
|
182
|
-
const output = result.stdout;
|
|
183
|
-
if (!output) {
|
|
184
|
-
return '';
|
|
185
|
-
}
|
|
186
|
-
// Post-process: fix paths in the diff header only (before the first @@ hunk)
|
|
187
|
-
const lines = output.split('\n');
|
|
188
|
-
let pastHeader = false;
|
|
189
|
-
const fixedLines = lines.map((line) => {
|
|
190
|
-
if (!pastHeader && line.startsWith('@@')) {
|
|
191
|
-
pastHeader = true;
|
|
192
|
-
}
|
|
193
|
-
if (!pastHeader) {
|
|
194
|
-
if (line.startsWith('diff --git')) {
|
|
195
|
-
return `diff --git a/${filePath} b/${filePath}`;
|
|
196
|
-
}
|
|
197
|
-
if (line.startsWith('--- ')) {
|
|
198
|
-
return `--- a/${filePath}`;
|
|
199
|
-
}
|
|
200
|
-
if (line.startsWith('+++ ')) {
|
|
201
|
-
return `+++ b/${filePath}`;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return line;
|
|
205
|
-
});
|
|
206
|
-
return fixedLines.join('\n');
|
|
207
|
-
}
|
|
208
|
-
finally {
|
|
209
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
151
|
/**
|
|
213
152
|
* Gets the diff for all modified files, including untracked (new) files.
|
|
214
153
|
*
|
|
215
|
-
* Tracked binary files round-trip through `git diff --binary
|
|
154
|
+
* Tracked binary files round-trip through `git diff --binary`. Untracked ones
|
|
216
155
|
* go through {@link generateBinaryFilePatch} below. Both arms must stay
|
|
217
|
-
* binary-aware
|
|
156
|
+
* binary-aware. See {@link getFileDiff} for why.
|
|
218
157
|
* @param repoDir - Repository directory
|
|
219
158
|
* @returns Diff content
|
|
220
159
|
*/
|
|
221
160
|
export async function getAllDiff(repoDir) {
|
|
222
|
-
await ensureGit();
|
|
223
161
|
// Get diff for tracked files
|
|
224
162
|
const trackedDiff = await git(['diff', '--binary', 'HEAD'], repoDir);
|
|
225
163
|
// Get untracked files (properly expanded, not directories)
|
|
226
164
|
const untrackedFiles = await getUntrackedFiles(repoDir);
|
|
227
|
-
// Classify first. `
|
|
228
|
-
//
|
|
229
|
-
// `git hash-object` inside `generateNewFileDiff
|
|
230
|
-
//
|
|
231
|
-
// very large number. Hence classify → one batched hash → render.
|
|
165
|
+
// Classify first. `readNewFileContent` reads the file directly and spawns
|
|
166
|
+
// nothing, so the only per-file process in this loop would be the
|
|
167
|
+
// `git hash-object` inside `generateNewFileDiff`: one spawn per untracked
|
|
168
|
+
// text file, uncapped, against a Firefox tree where "untracked" can mean a
|
|
169
|
+
// very large number. Hence classify → one batched hash → render. The
|
|
170
|
+
// classification carries each text file's content so it is read once.
|
|
232
171
|
//
|
|
233
172
|
// Everything else here is deliberately untouched: `git diff HEAD` (with
|
|
234
173
|
// renames, unlike the `--no-renames` scoped sibling), the `ls-files`
|
|
@@ -236,42 +175,35 @@ export async function getAllDiff(repoDir) {
|
|
|
236
175
|
// sentinel are all observable. `getAllDiff`'s output is SHA-256'd into
|
|
237
176
|
// every tree fingerprint (tree-store.ts) and written verbatim into `.patch`
|
|
238
177
|
// files (export-all.ts), so its bytes are a contract.
|
|
239
|
-
const
|
|
240
|
-
const textFiles = [];
|
|
178
|
+
const classified = new Map();
|
|
241
179
|
for (const file of untrackedFiles) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
textFiles.push(file);
|
|
247
|
-
}
|
|
180
|
+
await rejectDirectory(repoDir, file);
|
|
181
|
+
classified.set(file, await readNewFileContent(repoDir, file));
|
|
248
182
|
}
|
|
249
|
-
const textHashes = await hashObjectBatch(repoDir,
|
|
250
|
-
|
|
183
|
+
const textHashes = await hashObjectBatch(repoDir, untrackedFiles
|
|
184
|
+
.filter((file) => classified.get(file)?.binary === false)
|
|
185
|
+
.map((file) => join(repoDir, file)));
|
|
186
|
+
// Binary patches stage into the index and must stay serial. Text patches
|
|
251
187
|
// are pure formatting over the already-batched hashes.
|
|
252
188
|
const binaryDiffs = new Map();
|
|
253
|
-
for (const file of
|
|
254
|
-
|
|
189
|
+
for (const file of untrackedFiles) {
|
|
190
|
+
if (classified.get(file)?.binary === true) {
|
|
191
|
+
binaryDiffs.set(file, await generateBinaryFilePatch(repoDir, file));
|
|
192
|
+
}
|
|
255
193
|
}
|
|
256
194
|
const untrackedDiffs = [];
|
|
257
195
|
for (const file of untrackedFiles) {
|
|
258
|
-
const
|
|
259
|
-
if (
|
|
260
|
-
|
|
196
|
+
const entry = classified.get(file);
|
|
197
|
+
if (entry === undefined || entry.binary) {
|
|
198
|
+
const binary = binaryDiffs.get(file);
|
|
199
|
+
if (binary !== undefined)
|
|
200
|
+
untrackedDiffs.push(binary);
|
|
261
201
|
continue;
|
|
262
202
|
}
|
|
263
203
|
const fullPath = join(repoDir, file);
|
|
264
|
-
|
|
265
|
-
// directory here means a caller bypassed the expansion layers, and its
|
|
266
|
-
// comment records this as a recurring bug class.
|
|
267
|
-
const fileStat = await stat(fullPath);
|
|
268
|
-
if (fileStat.isDirectory()) {
|
|
269
|
-
throw new GitError(`expected a file but found a directory at '${file}' — caller must expand directory entries before diffing`, `hash-object ${file}`);
|
|
270
|
-
}
|
|
271
|
-
const content = await readText(fullPath);
|
|
272
|
-
untrackedDiffs.push(buildNewFileDiffBody(file, content, abbreviateBlobHash(textHashes.get(fullPath))));
|
|
204
|
+
untrackedDiffs.push(buildNewFileDiffBody(file, entry.content, abbreviateBlobHash(textHashes.get(fullPath))));
|
|
273
205
|
}
|
|
274
|
-
// Combine all diffs
|
|
206
|
+
// Combine all diffs. Each already ends with \n, so concatenate directly
|
|
275
207
|
// to avoid inserting blank lines between diff sections.
|
|
276
208
|
const allDiffs = [trackedDiff, ...untrackedDiffs].filter((d) => d.trim().length > 0);
|
|
277
209
|
const combined = allDiffs.join('');
|
|
@@ -283,8 +215,8 @@ export async function getAllDiff(repoDir) {
|
|
|
283
215
|
* to (but not including) the next such line. Boundary detection is anchored to
|
|
284
216
|
* column 0 because every diff *body* line is prefixed by a space, `+`, `-`,
|
|
285
217
|
* `\`, or `@`, so a context or added line that merely contains the text
|
|
286
|
-
* `diff --git` can never be mistaken for a header. Paths are
|
|
287
|
-
*
|
|
218
|
+
* `diff --git` can never be mistaken for a header. Paths are not parsed out
|
|
219
|
+
* of the header here on purpose. See {@link buildTrackedSections}.
|
|
288
220
|
* @param combined - Combined `git diff` stdout
|
|
289
221
|
* @returns File sections in git's emission order
|
|
290
222
|
*/
|
|
@@ -311,18 +243,18 @@ function splitDiffSections(combined) {
|
|
|
311
243
|
*
|
|
312
244
|
* `--binary` is load-bearing: a tracked binary file would otherwise degrade to
|
|
313
245
|
* the un-appliable `Binary files a/x and b/x differ` stub. It expands only the
|
|
314
|
-
* binary section's index line to full hashes, so text sections are
|
|
315
|
-
*
|
|
246
|
+
* binary section's index line to full hashes, so text sections are
|
|
247
|
+
* unaffected. See {@link getFileDiff}.
|
|
316
248
|
*
|
|
317
249
|
* `--no-renames` is load-bearing: a multi-path diff under a user's
|
|
318
250
|
* `diff.renames=true`/`=copies` could otherwise emit a single 2-path rename
|
|
319
251
|
* section (`a/<old> b/<new>`) that a single-path `git diff HEAD -- <file>` can
|
|
320
|
-
* never produce
|
|
252
|
+
* never produce. `--no-renames` re-splits it into the same delete + add bytes
|
|
321
253
|
* the per-file loop emitted.
|
|
322
254
|
*
|
|
323
|
-
* Sections are attributed to paths by
|
|
255
|
+
* Sections are attributed to paths by position against a companion
|
|
324
256
|
* `git diff --no-renames HEAD -z --name-only` (raw, unquoted, NUL-delimited
|
|
325
|
-
* paths, emitted in the same order as the sections)
|
|
257
|
+
* paths, emitted in the same order as the sections), never by parsing the
|
|
326
258
|
* `diff --git` header, which is ambiguous or unparseable under `core.quotePath`
|
|
327
259
|
* (non-ASCII paths are C-quoted), paths containing spaces, or
|
|
328
260
|
* `diff.noprefix`/`diff.mnemonicPrefix`. If the section and name counts ever
|
|
@@ -341,14 +273,14 @@ async function buildTrackedSections(repoDir, trackedFiles) {
|
|
|
341
273
|
const sections = splitDiffSections(combined);
|
|
342
274
|
if (sections.length === names.length) {
|
|
343
275
|
for (let i = 0; i < names.length; i++) {
|
|
344
|
-
// Exact-path keys (raw git bytes, same encoding as the inputs)
|
|
276
|
+
// Exact-path keys (raw git bytes, same encoding as the inputs), never
|
|
345
277
|
// a substring/startsWith match, so `foo.txt` cannot capture
|
|
346
278
|
// `foo.txt.bak`'s section.
|
|
347
279
|
sectionsByPath.set(names[i], sections[i]);
|
|
348
280
|
}
|
|
349
281
|
continue;
|
|
350
282
|
}
|
|
351
|
-
// Counts disagree
|
|
283
|
+
// Counts disagree, so recover the exact pre-batch per-file bytes for this
|
|
352
284
|
// chunk rather than risk dropping or mis-keying a section.
|
|
353
285
|
for (const file of chunk) {
|
|
354
286
|
const diff = await getFileDiff(repoDir, file);
|
|
@@ -361,7 +293,7 @@ async function buildTrackedSections(repoDir, trackedFiles) {
|
|
|
361
293
|
/**
|
|
362
294
|
* Builds a combined diff against HEAD for the provided files without touching
|
|
363
295
|
* the real git index. Tracked files use `git diff --binary HEAD` (binary
|
|
364
|
-
* sections included)
|
|
296
|
+
* sections included). Untracked files use synthesized new-file diffs, or
|
|
365
297
|
* {@link generateBinaryFilePatch} when the file is binary.
|
|
366
298
|
*
|
|
367
299
|
* Performance: the work is batched into a handful of `git` invocations (one
|
|
@@ -376,14 +308,13 @@ async function buildTrackedSections(repoDir, trackedFiles) {
|
|
|
376
308
|
* @returns Combined diff content
|
|
377
309
|
*/
|
|
378
310
|
export async function getDiffForFilesAgainstHead(repoDir, files) {
|
|
379
|
-
await ensureGit();
|
|
380
311
|
// Expand any directory entries (paths ending with `/`) into their
|
|
381
312
|
// individual untracked files before diffing. `git status --porcelain=v1`
|
|
382
313
|
// reports collapsed untracked directories as `?? dir/`, and every caller
|
|
383
314
|
// that feeds the aggregate working-tree state into this function must not
|
|
384
315
|
// trigger an EISDIR when the diff pass reads `dir/` as if it were a file.
|
|
385
316
|
// The caller-side expansion in `lint.ts` and `export-all.ts` covers the
|
|
386
|
-
// common path
|
|
317
|
+
// common path. Guarding here makes a single bad call site harmless.
|
|
387
318
|
const expandedFiles = [];
|
|
388
319
|
for (const file of files) {
|
|
389
320
|
if (file.endsWith('/')) {
|
|
@@ -405,7 +336,7 @@ export async function getDiffForFilesAgainstHead(repoDir, files) {
|
|
|
405
336
|
const trackedSections = await buildTrackedSections(repoDir, uniqueFiles.filter((file) => tracked.has(file)));
|
|
406
337
|
// Classify the non-tracked files. Directory and binary entries keep their
|
|
407
338
|
// per-file handling (rare, and binary patches mutate the index so they must
|
|
408
|
-
// stay serial)
|
|
339
|
+
// stay serial). Plain new text files are collected for a single batched
|
|
409
340
|
// `git hash-object`. Results land in `sectionByFile`, keyed by path, to be
|
|
410
341
|
// emitted in sorted order below.
|
|
411
342
|
const sectionByFile = new Map();
|
|
@@ -422,7 +353,7 @@ export async function getDiffForFilesAgainstHead(repoDir, files) {
|
|
|
422
353
|
// the trailing slash `expandUntrackedDirectoryEntries` would have
|
|
423
354
|
// produced (caller stripped it, submodule entry, tracked-file-replaced-
|
|
424
355
|
// by-dir). Expand it via the same helper used by the slash branch and
|
|
425
|
-
// recurse so each contained file is diffed individually
|
|
356
|
+
// recurse so each contained file is diffed individually. Fail loud when
|
|
426
357
|
// the directory has no readable content rather than silently skipping it.
|
|
427
358
|
const fileStat = await stat(fullPath);
|
|
428
359
|
if (fileStat.isDirectory()) {
|
|
@@ -435,29 +366,31 @@ export async function getDiffForFilesAgainstHead(repoDir, files) {
|
|
|
435
366
|
sectionByFile.set(file, innerDiff);
|
|
436
367
|
continue;
|
|
437
368
|
}
|
|
438
|
-
|
|
369
|
+
// Binary (by git's NUL heuristic or because the bytes are not valid
|
|
370
|
+
// UTF-8) takes the byte-faithful binary-patch arm.
|
|
371
|
+
const newFile = await readNewFileContent(repoDir, file);
|
|
372
|
+
if (newFile.binary) {
|
|
439
373
|
const diff = await generateBinaryFilePatch(repoDir, file);
|
|
440
374
|
if (diff.trim())
|
|
441
375
|
sectionByFile.set(file, diff);
|
|
442
376
|
continue;
|
|
443
377
|
}
|
|
444
|
-
newTextFiles.push(file);
|
|
378
|
+
newTextFiles.push({ file, content: newFile.content });
|
|
445
379
|
}
|
|
446
380
|
// Batch 3: blob hashes for every new text file in one `git hash-object`.
|
|
447
381
|
// A miss (rare: a path became unreadable after the stat above) falls back to
|
|
448
382
|
// the zero hash with the same verbose log the per-file path emitted.
|
|
449
|
-
const blobHashes = await hashObjectBatch(repoDir, newTextFiles.map((file) => join(repoDir, file)));
|
|
450
|
-
for (const file of newTextFiles) {
|
|
451
|
-
const
|
|
452
|
-
const fullHash = blobHashes.get(fullPath);
|
|
383
|
+
const blobHashes = await hashObjectBatch(repoDir, newTextFiles.map(({ file }) => join(repoDir, file)));
|
|
384
|
+
for (const { file, content } of newTextFiles) {
|
|
385
|
+
const fullHash = blobHashes.get(join(repoDir, file));
|
|
453
386
|
if (fullHash === undefined) {
|
|
454
387
|
verbose(`git hash-object failed for ${file}; falling back to zero blob hash`);
|
|
455
388
|
}
|
|
456
|
-
const body = buildNewFileDiffBody(file,
|
|
389
|
+
const body = buildNewFileDiffBody(file, content, abbreviateBlobHash(fullHash));
|
|
457
390
|
if (body.trim())
|
|
458
391
|
sectionByFile.set(file, body);
|
|
459
392
|
}
|
|
460
|
-
// Reassemble in the sorted `uniqueFiles` order
|
|
393
|
+
// Reassemble in the sorted `uniqueFiles` order, not git's section order,
|
|
461
394
|
// which uses git's own collation and diverges from JS `.sort()` for
|
|
462
395
|
// non-ASCII paths. Driving emission off `uniqueFiles` (as the previous
|
|
463
396
|
// per-file loop did) keeps the combined output byte-identical. Do not change
|
|
@@ -484,13 +417,12 @@ export async function getDiffForFilesAgainstHead(repoDir, files) {
|
|
|
484
417
|
* @returns Diff content for the staged files
|
|
485
418
|
*/
|
|
486
419
|
export async function getStagedDiffForFiles(repoDir, files) {
|
|
487
|
-
await ensureGit();
|
|
488
420
|
return git(['diff', '--binary', '--cached', 'HEAD', '--', ...files], repoDir);
|
|
489
421
|
}
|
|
490
422
|
/**
|
|
491
423
|
* Serializes the index-mutating untracked-binary path. The bounded per-patch
|
|
492
424
|
* lint pool can call {@link getDiffForFilesAgainstHead} (and thus this) for
|
|
493
|
-
* several patches at once
|
|
425
|
+
* several patches at once. Two concurrent `git add --intent-to-add` / `git
|
|
494
426
|
* reset` sequences would collide on `.git/index.lock` (a hard failure) or
|
|
495
427
|
* interleave one file's stage with another's unstage. This process-level
|
|
496
428
|
* promise chain runs the staging sequences one at a time. Read-only callers
|
|
@@ -507,28 +439,37 @@ function runWithBinaryStagingLock(task) {
|
|
|
507
439
|
* Generates a GIT binary patch for a binary file.
|
|
508
440
|
* For tracked files, uses `git diff --binary HEAD`.
|
|
509
441
|
* For untracked files, temporarily stages with `--intent-to-add` to produce a diff.
|
|
442
|
+
*
|
|
443
|
+
* Every `git diff` here runs under {@link withForcedBinaryAttribute}: a
|
|
444
|
+
* caller sends a file down this arm because a text body cannot carry its
|
|
445
|
+
* bytes (NUL, or not valid UTF-8), and git's own NUL-only heuristic would
|
|
446
|
+
* otherwise still render the non-UTF-8 case as text.
|
|
510
447
|
* @param repoDir - Repository directory
|
|
511
448
|
* @param filePath - File path (relative to repo root)
|
|
512
449
|
* @returns The binary diff string, or empty string if no diff
|
|
513
450
|
*/
|
|
514
451
|
export async function generateBinaryFilePatch(repoDir, filePath) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
452
|
+
return withForcedBinaryAttribute(filePath, (gitConfigArgs) => generateBinaryFilePatchWithConfig(repoDir, filePath, gitConfigArgs));
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* The body of {@link generateBinaryFilePatch}, with the forced-binary config
|
|
456
|
+
* arguments already resolved.
|
|
457
|
+
* @param repoDir - Repository directory
|
|
458
|
+
* @param filePath - File path (relative to repo root)
|
|
459
|
+
* @param gitConfigArgs - `-c` arguments spliced ahead of every `diff`
|
|
460
|
+
* @returns The binary diff string, or empty string if no diff
|
|
461
|
+
*/
|
|
462
|
+
async function generateBinaryFilePatchWithConfig(repoDir, filePath, gitConfigArgs) {
|
|
463
|
+
// Try tracked file diff first (read-only, so no index lock needed)
|
|
464
|
+
const tracked = await git([...gitConfigArgs, 'diff', '--binary', 'HEAD', '--', filePath], repoDir);
|
|
465
|
+
if (tracked.trim())
|
|
466
|
+
return tracked;
|
|
526
467
|
// The diff for an untracked file has to come from an index entry, so one
|
|
527
|
-
// has to be written. Writing it to a
|
|
468
|
+
// has to be written. Writing it to a private index is what keeps that
|
|
528
469
|
// write invisible: the primary `.git/index` never moves, so a concurrent
|
|
529
470
|
// `fireforge test` fingerprinting `engine/` with `git status` cannot
|
|
530
471
|
// observe the transient `--intent-to-add` entry and void its own verdict
|
|
531
|
-
// on our bookkeeping. That was a real failure mode
|
|
472
|
+
// on our bookkeeping. That was a real failure mode: parallel gate lanes
|
|
532
473
|
// killed three runs with `FAIL reason=inconclusive` on branding PNGs
|
|
533
474
|
// flapping between `A` and `??`.
|
|
534
475
|
//
|
|
@@ -539,9 +480,10 @@ export async function generateBinaryFilePatch(repoDir, filePath) {
|
|
|
539
480
|
const disposable = await mintDisposableGitIndex(repoDir);
|
|
540
481
|
if (disposable !== undefined) {
|
|
541
482
|
try {
|
|
542
|
-
await
|
|
543
|
-
|
|
544
|
-
|
|
483
|
+
await git(['add', '--intent-to-add', '--', filePath], repoDir, { env: disposable.env });
|
|
484
|
+
return await git([...gitConfigArgs, 'diff', '--binary', '--', filePath], repoDir, {
|
|
485
|
+
env: disposable.env,
|
|
486
|
+
});
|
|
545
487
|
}
|
|
546
488
|
finally {
|
|
547
489
|
await disposable.dispose();
|
|
@@ -556,22 +498,16 @@ export async function generateBinaryFilePatch(repoDir, filePath) {
|
|
|
556
498
|
verbose(`Binary patch for ${filePath} is staging on the shared index (no private index).`);
|
|
557
499
|
return runWithBinaryStagingLock(async () => {
|
|
558
500
|
// Snapshot the path's exact index entry before touching it. A blanket
|
|
559
|
-
// `git reset HEAD -- <file>` cleanup restores the path to its HEAD state
|
|
560
|
-
//
|
|
501
|
+
// `git reset HEAD -- <file>` cleanup restores the path to its HEAD state.
|
|
502
|
+
// For a path absent from HEAD that means *removing* whatever entry the
|
|
561
503
|
// index carried, silently discarding any staged state that arrived
|
|
562
504
|
// between the read-only diff above and this staging block (a concurrent
|
|
563
505
|
// writer, or a staged-add whose worktree file was deleted). Restoring
|
|
564
506
|
// the captured entry is exact regardless of how the entry got there.
|
|
565
|
-
const priorEntry =
|
|
507
|
+
const priorEntry = await git(['ls-files', '--stage', '--', filePath], repoDir);
|
|
566
508
|
try {
|
|
567
|
-
await
|
|
568
|
-
|
|
569
|
-
'diff',
|
|
570
|
-
'--binary',
|
|
571
|
-
'--',
|
|
572
|
-
filePath,
|
|
573
|
-
]);
|
|
574
|
-
return diffResult.stdout;
|
|
509
|
+
await git(['add', '--intent-to-add', '--', filePath], repoDir);
|
|
510
|
+
return await git([...gitConfigArgs, 'diff', '--binary', '--', filePath], repoDir);
|
|
575
511
|
}
|
|
576
512
|
finally {
|
|
577
513
|
await restoreIndexEntry(repoDir, filePath, priorEntry);
|
|
@@ -581,11 +517,12 @@ export async function generateBinaryFilePatch(repoDir, filePath) {
|
|
|
581
517
|
/**
|
|
582
518
|
* Restores a path's index entry to a previously captured `ls-files --stage`
|
|
583
519
|
* snapshot after a temporary `--intent-to-add` staging. No prior entry means
|
|
584
|
-
* the temporary entry is dropped via `reset HEAD` (the path's HEAD state
|
|
585
|
-
* "absent"
|
|
520
|
+
* the temporary entry is dropped via `reset HEAD` (the path's HEAD state is
|
|
521
|
+
* "absent", and this branch only runs for files untracked in HEAD). A prior
|
|
586
522
|
* stage-0 entry is re-pointed at its recorded mode and blob. Unmerged entries
|
|
587
|
-
* (stages 1
|
|
588
|
-
* keeps the legacy reset-to-HEAD behavior rather than corrupting the
|
|
523
|
+
* (stages 1 to 3) cannot be rebuilt through `--cacheinfo`. That degenerate
|
|
524
|
+
* state keeps the legacy reset-to-HEAD behavior rather than corrupting the
|
|
525
|
+
* conflict.
|
|
589
526
|
* @param repoDir - Repository directory
|
|
590
527
|
* @param filePath - File path (relative to repo root)
|
|
591
528
|
* @param priorEntry - Raw `git ls-files --stage -- <file>` output from before staging
|
|
@@ -595,13 +532,8 @@ async function restoreIndexEntry(repoDir, filePath, priorEntry) {
|
|
|
595
532
|
const mode = entryMatch?.[1];
|
|
596
533
|
const oid = entryMatch?.[2];
|
|
597
534
|
if (mode === undefined || oid === undefined) {
|
|
598
|
-
await
|
|
535
|
+
await git(['reset', 'HEAD', '--', filePath], repoDir);
|
|
599
536
|
return;
|
|
600
537
|
}
|
|
601
|
-
await
|
|
602
|
-
'update-index',
|
|
603
|
-
'--add',
|
|
604
|
-
'--cacheinfo',
|
|
605
|
-
`${mode},${oid},${filePath}`,
|
|
606
|
-
]);
|
|
538
|
+
await git(['update-index', '--add', '--cacheinfo', `${mode},${oid},${filePath}`], repoDir);
|
|
607
539
|
}
|
|
@@ -33,10 +33,10 @@ export declare function fileExistsInHead(repoDir: string, filePath: string): Pro
|
|
|
33
33
|
/**
|
|
34
34
|
* Batched equivalent of {@link fileExistsInHead}: returns the subset of
|
|
35
35
|
* `files` that are tracked in HEAD, using a single `git ls-tree` per ARG_MAX
|
|
36
|
-
* chunk instead of one spawn per file. This is the cold-run hot path
|
|
37
|
-
* Firefox-sized checkout has hundreds of affected files.
|
|
36
|
+
* chunk instead of one spawn per file. This is the cold-run hot path, and
|
|
37
|
+
* a Firefox-sized checkout has hundreds of affected files.
|
|
38
38
|
*
|
|
39
|
-
* `-r` lists nested blobs by full repo-relative path
|
|
39
|
+
* `-r` lists nested blobs by full repo-relative path. `--name-only -z` makes
|
|
40
40
|
* the output a trivial NUL-split with no quoting to undo. Membership in the
|
|
41
41
|
* returned Set is exactly `await fileExistsInHead(repoDir, file)` for any
|
|
42
42
|
* non-directory `file`. Throws (via {@link git}) when HEAD itself is
|
|
@@ -56,10 +56,10 @@ export declare function listTrackedInHead(repoDir: string, files: string[]): Pro
|
|
|
56
56
|
* Uses {@link import('../utils/process.js').exec} rather than {@link git}
|
|
57
57
|
* (which throws on a non-zero exit) because `git hash-object f1 f2 …` is
|
|
58
58
|
* all-or-nothing: it aborts at the first unreadable path and emits nothing
|
|
59
|
-
* for the rest. To keep the per-file contract
|
|
60
|
-
* only its own index line
|
|
59
|
+
* for the rest. To keep the per-file contract, where one bad path zeroes
|
|
60
|
+
* only its own index line, a chunk that does not return exactly one hash
|
|
61
61
|
* per input falls back to hashing that chunk's paths individually. A path
|
|
62
|
-
* that is still unhashable is left out of the map
|
|
62
|
+
* that is still unhashable is left out of the map. The caller applies the
|
|
63
63
|
* `0000000000` zero-hash fallback for any miss. Hashing stays in git rather
|
|
64
64
|
* than in-process so filters and `.gitattributes` are applied per path and
|
|
65
65
|
* the result cannot diverge under `core.autocrlf`/`text` attributes.
|
|
@@ -77,13 +77,6 @@ export declare function hashObjectBatch(repoDir: string, fullPaths: string[]): P
|
|
|
77
77
|
* @returns File content or null if file doesn't exist at that ref
|
|
78
78
|
*/
|
|
79
79
|
export declare function getFileContentAtRef(repoDir: string, filePath: string, ref?: string): Promise<string | null>;
|
|
80
|
-
/**
|
|
81
|
-
* Gets the content of a file from HEAD commit.
|
|
82
|
-
* @param repoDir - Repository directory
|
|
83
|
-
* @param filePath - Path to the file (relative to repo)
|
|
84
|
-
* @returns File content or null if file doesn't exist in HEAD
|
|
85
|
-
*/
|
|
86
|
-
export declare function getFileContentFromHead(repoDir: string, filePath: string): Promise<string | null>;
|
|
87
80
|
/**
|
|
88
81
|
* Checks if a file is binary by looking for NUL bytes in the first 8KB.
|
|
89
82
|
* Uses the same heuristic as git.
|