@hominis/fireforge 0.44.4 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +120 -0
- package/dist/bin/fireforge.js +6 -0
- 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 +5 -1
- package/dist/src/cli.js +20 -21
- package/dist/src/commands/bootstrap.js +1 -2
- package/dist/src/commands/build.js +15 -6
- package/dist/src/commands/destructive-decision.d.ts +19 -0
- package/dist/src/commands/destructive-decision.js +31 -0
- package/dist/src/commands/doctor-check-core.d.ts +0 -6
- package/dist/src/commands/doctor-check-core.js +0 -8
- package/dist/src/commands/doctor-orphaned-harness.d.ts +0 -6
- package/dist/src/commands/doctor-orphaned-harness.js +4 -12
- package/dist/src/commands/doctor-post-rebase-audit.js +1 -1
- package/dist/src/commands/doctor-source-pin.d.ts +29 -0
- package/dist/src/commands/doctor-source-pin.js +81 -0
- package/dist/src/commands/doctor.d.ts +2 -0
- package/dist/src/commands/doctor.js +9 -8
- package/dist/src/commands/download.js +35 -24
- package/dist/src/commands/export-all.js +21 -4
- package/dist/src/commands/export-flow.js +15 -60
- package/dist/src/commands/export-placement-conflicts.js +3 -3
- package/dist/src/commands/export-placement-gate.js +2 -8
- package/dist/src/commands/export-placement-policy.js +3 -5
- package/dist/src/commands/export-shared.d.ts +42 -23
- package/dist/src/commands/export-shared.js +4 -19
- package/dist/src/commands/export.js +10 -1
- 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.js +1 -1
- package/dist/src/commands/furnace/create-browser-test.js +3 -8
- package/dist/src/commands/furnace/create-dry-run.js +2 -5
- package/dist/src/commands/furnace/create-templates.d.ts +17 -1
- package/dist/src/commands/furnace/create-templates.js +2 -1
- package/dist/src/commands/furnace/create.js +25 -19
- package/dist/src/commands/furnace/deploy.js +11 -2
- package/dist/src/commands/furnace/init.js +2 -1
- package/dist/src/commands/furnace/override.js +28 -19
- package/dist/src/commands/furnace/refresh.js +9 -1
- package/dist/src/commands/furnace/remove-mutations.d.ts +6 -7
- package/dist/src/commands/furnace/remove-mutations.js +0 -1
- package/dist/src/commands/furnace/remove.js +2 -6
- package/dist/src/commands/furnace/rename-browser-test.js +1 -7
- package/dist/src/commands/furnace/rename.js +29 -29
- package/dist/src/commands/furnace/status.js +12 -9
- 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/validation-output.d.ts +21 -9
- package/dist/src/commands/furnace/validation-output.js +3 -8
- package/dist/src/commands/import.js +2 -9
- package/dist/src/commands/lint-per-patch.d.ts +2 -2
- package/dist/src/commands/lint-per-patch.js +19 -4
- package/dist/src/commands/lint-per-run-checkjs.d.ts +2 -2
- package/dist/src/commands/lint.d.ts +2 -1
- package/dist/src/commands/lint.js +1 -1
- package/dist/src/commands/manifest.js +1 -1
- package/dist/src/commands/package.js +2 -4
- package/dist/src/commands/patch/compact.js +14 -15
- package/dist/src/commands/patch/delete.js +15 -25
- 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 +0 -8
- package/dist/src/commands/patch/lint-ignore.js +19 -29
- package/dist/src/commands/patch/move-files-create.js +24 -10
- package/dist/src/commands/patch/move-files-into.js +38 -37
- package/dist/src/commands/patch/move-files.js +4 -13
- package/dist/src/commands/patch/rename.js +27 -41
- package/dist/src/commands/patch/reorder.js +25 -38
- package/dist/src/commands/patch/split-plan.d.ts +4 -5
- package/dist/src/commands/patch/split-plan.js +4 -11
- package/dist/src/commands/patch/split.js +45 -43
- package/dist/src/commands/patch/staged-dependency.js +16 -22
- package/dist/src/commands/patch/tier.js +15 -25
- 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 +32 -2
- package/dist/src/commands/re-export-adjacent.js +51 -10
- package/dist/src/commands/re-export-bulk-scan.js +6 -10
- package/dist/src/commands/re-export-drift.d.ts +8 -0
- package/dist/src/commands/re-export-drift.js +65 -4
- package/dist/src/commands/re-export-files.d.ts +2 -3
- package/dist/src/commands/re-export-files.js +38 -32
- package/dist/src/commands/re-export-lint.d.ts +3 -4
- package/dist/src/commands/re-export-lint.js +9 -2
- package/dist/src/commands/re-export-options.js +19 -5
- package/dist/src/commands/re-export-register.js +5 -1
- package/dist/src/commands/re-export-scan.js +8 -8
- package/dist/src/commands/re-export-single.d.ts +22 -3
- package/dist/src/commands/re-export-single.js +19 -11
- package/dist/src/commands/re-export.js +44 -27
- package/dist/src/commands/rebase/abort.js +3 -8
- package/dist/src/commands/rebase/continue.js +12 -12
- package/dist/src/commands/rebase/index.js +2 -2
- package/dist/src/commands/rebase/patch-loop.d.ts +2 -2
- package/dist/src/commands/rebase/patch-loop.js +2 -7
- package/dist/src/commands/resolve.js +18 -10
- package/dist/src/commands/run.d.ts +0 -13
- package/dist/src/commands/run.js +12 -25
- package/dist/src/commands/setup-support.d.ts +16 -4
- package/dist/src/commands/setup-support.js +16 -16
- package/dist/src/commands/setup.js +3 -9
- package/dist/src/commands/source.js +8 -1
- package/dist/src/commands/status-check.js +2 -2
- package/dist/src/commands/status-output.js +2 -2
- package/dist/src/commands/status.js +3 -4
- package/dist/src/commands/test-build-phase.d.ts +2 -2
- package/dist/src/commands/test-build-phase.js +33 -8
- package/dist/src/commands/test-diagnose.js +14 -5
- package/dist/src/commands/test-modes.d.ts +2 -2
- package/dist/src/commands/test-modes.js +0 -1
- package/dist/src/commands/test-register.js +6 -3
- package/dist/src/commands/test-run.js +29 -21
- package/dist/src/commands/test-stale-gate.js +8 -5
- package/dist/src/commands/test-verdict.d.ts +16 -2
- package/dist/src/commands/test-verdict.js +18 -3
- package/dist/src/commands/test.js +51 -7
- 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 +17 -1
- package/dist/src/commands/tree.js +7 -2
- package/dist/src/commands/typecheck.js +9 -9
- package/dist/src/commands/wire.js +4 -3
- package/dist/src/core/branding.d.ts +0 -7
- package/dist/src/core/branding.js +3 -2
- package/dist/src/core/browser-wire.js +6 -3
- package/dist/src/core/build-audit-platform.d.ts +29 -0
- package/dist/src/core/build-audit-platform.js +140 -0
- package/dist/src/core/build-audit-registration.js +3 -2
- 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.d.ts +15 -2
- package/dist/src/core/build-audit.js +154 -12
- package/dist/src/core/build-baseline.d.ts +45 -28
- package/dist/src/core/build-baseline.js +6 -29
- package/dist/src/core/build-jar-escalation.d.ts +64 -0
- package/dist/src/core/build-jar-escalation.js +128 -0
- package/dist/src/core/build-overwrite-guard.js +1 -1
- package/dist/src/core/build-prepare.d.ts +5 -2
- package/dist/src/core/build-prepare.js +34 -6
- 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 +1 -19
- 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 +12 -0
- package/dist/src/core/config-validate-file-size.js +65 -0
- 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 +20 -3
- package/dist/src/core/config.d.ts +2 -2
- package/dist/src/core/config.js +11 -15
- package/dist/src/core/coverage-extend.js +4 -4
- package/dist/src/core/discard-baseline.js +7 -7
- package/dist/src/core/engine-precondition.d.ts +1 -9
- package/dist/src/core/engine-precondition.js +3 -8
- package/dist/src/core/engine-session-lock.js +13 -17
- package/dist/src/core/export-moved-code-shape.js +2 -2
- 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 +2 -7
- package/dist/src/core/file-lock.js +40 -91
- package/dist/src/core/firefox-cache.d.ts +13 -1
- package/dist/src/core/firefox-cache.js +59 -34
- package/dist/src/core/firefox-download.d.ts +15 -0
- package/dist/src/core/firefox-download.js +37 -21
- package/dist/src/core/firefox-extract.d.ts +6 -5
- package/dist/src/core/firefox-extract.js +36 -18
- package/dist/src/core/firefox.d.ts +30 -32
- package/dist/src/core/firefox.js +5 -36
- package/dist/src/core/furnace-apply-dry-run.d.ts +1 -6
- package/dist/src/core/furnace-apply-dry-run.js +1 -7
- package/dist/src/core/furnace-apply-helpers.d.ts +0 -11
- package/dist/src/core/furnace-apply-helpers.js +8 -19
- package/dist/src/core/furnace-apply-overwrite-warn.js +4 -2
- package/dist/src/core/furnace-apply.d.ts +1 -1
- package/dist/src/core/furnace-apply.js +30 -10
- package/dist/src/core/furnace-config.d.ts +1 -1
- package/dist/src/core/furnace-config.js +23 -36
- package/dist/src/core/furnace-constants.js +3 -2
- 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-operation.d.ts +2 -0
- package/dist/src/core/furnace-operation.js +3 -1
- package/dist/src/core/furnace-refresh.d.ts +18 -6
- package/dist/src/core/furnace-refresh.js +3 -6
- package/dist/src/core/furnace-registration-ast.d.ts +0 -1
- package/dist/src/core/furnace-registration-ast.js +0 -3
- package/dist/src/core/furnace-registration.d.ts +2 -1
- package/dist/src/core/furnace-registration.js +22 -29
- package/dist/src/core/furnace-scanner.js +3 -6
- package/dist/src/core/furnace-state-persist.d.ts +2 -2
- package/dist/src/core/furnace-validate-registration.js +5 -7
- package/dist/src/core/git-base.d.ts +3 -1
- package/dist/src/core/git-base.js +25 -3
- 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 +9 -9
- package/dist/src/core/git-diff.js +88 -157
- package/dist/src/core/git-file-ops.d.ts +0 -7
- package/dist/src/core/git-file-ops.js +4 -28
- package/dist/src/core/git-readonly-index.d.ts +0 -2
- package/dist/src/core/git-readonly-index.js +0 -4
- package/dist/src/core/git-status.d.ts +7 -0
- package/dist/src/core/git-status.js +21 -9
- package/dist/src/core/git.d.ts +0 -6
- package/dist/src/core/git.js +14 -43
- package/dist/src/core/harness-orphans.d.ts +73 -0
- package/dist/src/core/harness-orphans.js +187 -0
- package/dist/src/core/history-log.d.ts +19 -0
- package/dist/src/core/history-log.js +29 -0
- package/dist/src/core/mach-error-hints.d.ts +0 -5
- package/dist/src/core/mach-error-hints.js +1 -1
- package/dist/src/core/mach-known-noise-filter.d.ts +25 -3
- package/dist/src/core/mach-known-noise-filter.js +31 -10
- package/dist/src/core/mach-mozconfig.js +2 -1
- package/dist/src/core/mach-python.d.ts +2 -0
- package/dist/src/core/mach-python.js +12 -7
- package/dist/src/core/mach-resource-shim.d.ts +13 -1
- package/dist/src/core/mach-resource-shim.js +112 -9
- package/dist/src/core/mach.d.ts +46 -53
- package/dist/src/core/mach.js +31 -83
- package/dist/src/core/marionette-port.d.ts +0 -17
- package/dist/src/core/marionette-port.js +12 -58
- package/dist/src/core/marionette-preflight.js +9 -27
- package/dist/src/core/mochitest-server-port.js +3 -3
- package/dist/src/core/moz-manifest-rules.js +37 -33
- package/dist/src/core/patch-apply-fuzz.js +4 -4
- package/dist/src/core/patch-apply.d.ts +4 -5
- package/dist/src/core/patch-apply.js +55 -32
- 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 +18 -1
- package/dist/src/core/patch-export-update.js +4 -3
- package/dist/src/core/patch-export.d.ts +11 -21
- package/dist/src/core/patch-export.js +44 -66
- package/dist/src/core/patch-files.d.ts +0 -4
- package/dist/src/core/patch-files.js +0 -11
- package/dist/src/core/patch-lint-binary.d.ts +6 -12
- package/dist/src/core/patch-lint-cache.d.ts +17 -1
- package/dist/src/core/patch-lint-cache.js +3 -6
- package/dist/src/core/patch-lint-checkjs.d.ts +33 -16
- package/dist/src/core/patch-lint-checkjs.js +43 -25
- package/dist/src/core/patch-lint-creators.d.ts +2 -6
- package/dist/src/core/patch-lint-cross.d.ts +16 -8
- package/dist/src/core/patch-lint-cross.js +49 -92
- package/dist/src/core/patch-lint-css.js +10 -6
- package/dist/src/core/patch-lint-file-size.d.ts +52 -0
- package/dist/src/core/patch-lint-file-size.js +53 -0
- 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.js +36 -36
- package/dist/src/core/patch-lint-module-registration.d.ts +2 -8
- package/dist/src/core/patch-lint-prettier.d.ts +36 -0
- package/dist/src/core/patch-lint-prettier.js +126 -0
- 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 +106 -0
- package/dist/src/core/patch-lint-unmanaged-companion.js +214 -0
- package/dist/src/core/patch-lint.d.ts +14 -9
- package/dist/src/core/patch-lint.js +27 -27
- package/dist/src/core/patch-lock.js +3 -3
- package/dist/src/core/patch-manifest-io.js +8 -7
- package/dist/src/core/patch-parse.d.ts +19 -8
- package/dist/src/core/patch-parse.js +25 -0
- package/dist/src/core/patch-policy.js +15 -27
- 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 +21 -8
- package/dist/src/core/patch-transform.js +38 -10
- package/dist/src/core/process-cpu-time.js +1 -1
- package/dist/src/core/rebase-session.d.ts +2 -8
- package/dist/src/core/rebase-session.js +5 -17
- 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-scaffold.js +5 -4
- package/dist/src/core/register-shared-css.js +2 -1
- 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 +13 -2
- package/dist/src/core/run-log.js +67 -18
- package/dist/src/core/signal-critical.js +2 -4
- package/dist/src/core/smoke-patterns.d.ts +0 -1
- package/dist/src/core/smoke-patterns.js +18 -11
- package/dist/src/core/state-file.d.ts +12 -1
- package/dist/src/core/state-file.js +14 -1
- package/dist/src/core/status-classify.js +2 -1
- package/dist/src/core/test-changed-prefs.js +26 -11
- package/dist/src/core/test-harness-crash.js +61 -48
- package/dist/src/core/test-harness-verdict-notes.d.ts +55 -0
- package/dist/src/core/test-harness-verdict-notes.js +48 -0
- package/dist/src/core/test-stale-check.d.ts +23 -8
- package/dist/src/core/test-stale-check.js +77 -4
- package/dist/src/core/test-stall-triage.js +37 -19
- 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 +33 -0
- package/dist/src/core/token-category.js +56 -48
- package/dist/src/core/token-dark-mode.js +2 -14
- 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 +1 -1
- package/dist/src/core/token-manager.js +1 -1
- package/dist/src/core/token-variant.js +21 -22
- package/dist/src/core/toolchain-preflight.js +1 -1
- package/dist/src/core/tree-cow.d.ts +0 -2
- package/dist/src/core/tree-cow.js +2 -2
- package/dist/src/core/tree-store.js +4 -5
- package/dist/src/core/typecheck.js +2 -2
- package/dist/src/core/wire-dom-fragment.js +6 -17
- package/dist/src/core/wire-utils.js +5 -17
- package/dist/src/core/xpcshell-appdir.js +2 -4
- package/dist/src/errors/base.d.ts +53 -1
- package/dist/src/errors/base.js +79 -11
- package/dist/src/errors/build.d.ts +28 -0
- package/dist/src/errors/build.js +51 -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.js +8 -9
- package/dist/src/errors/git.d.ts +8 -8
- package/dist/src/errors/git.js +20 -30
- package/dist/src/errors/patch.js +8 -10
- package/dist/src/errors/rebase.js +7 -7
- package/dist/src/types/commands/options.d.ts +96 -123
- package/dist/src/types/commands/patches.d.ts +17 -6
- package/dist/src/types/config.d.ts +75 -2
- package/dist/src/types/index.d.ts +0 -1
- package/dist/src/utils/assert.d.ts +3 -15
- package/dist/src/utils/assert.js +1 -18
- package/dist/src/utils/build-info.d.ts +1 -1
- package/dist/src/utils/child-env.d.ts +2 -1
- package/dist/src/utils/elapsed.js +10 -1
- package/dist/src/utils/fs.d.ts +4 -2
- package/dist/src/utils/fs.js +11 -14
- 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/options.d.ts +1 -7
- package/dist/src/utils/options.js +6 -7
- package/dist/src/utils/package-root.js +3 -12
- package/dist/src/utils/platform.d.ts +0 -4
- package/dist/src/utils/process-group.d.ts +2 -1
- package/dist/src/utils/process-group.js +20 -19
- package/dist/src/utils/process.d.ts +40 -26
- package/dist/src/utils/process.js +115 -166
- package/dist/src/utils/ps-duration.js +3 -3
- package/dist/src/utils/sleep.d.ts +26 -0
- package/dist/src/utils/sleep.js +31 -0
- package/dist/src/utils/validation.d.ts +2 -38
- package/dist/src/utils/validation.js +7 -16
- package/docs/configuration.md +136 -1
- package/docs/exit-codes.md +34 -20
- package/docs/lifecycle-invariants.md +18 -12
- package/docs/machine-output.md +31 -8
- package/docs/patch-workflow.md +2 -1
- package/docs/run-logs.md +44 -4
- package/docs/testing.md +70 -11
- package/package.json +8 -7
- 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,9 +1,9 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { createHash } from 'node:crypto';
|
|
3
2
|
import { readdir } from 'node:fs/promises';
|
|
4
3
|
import { join } from 'node:path';
|
|
5
4
|
import { toError } from '../utils/errors.js';
|
|
6
5
|
import { pathExists, readText } from '../utils/fs.js';
|
|
6
|
+
import { sha256Hex } from '../utils/hash.js';
|
|
7
7
|
import { warn } from '../utils/logger.js';
|
|
8
8
|
import { escapeRegex, stripJsComments } from '../utils/regex.js';
|
|
9
9
|
import { getProjectPaths, loadConfig } from './config.js';
|
|
@@ -129,8 +129,8 @@ export async function checkRegistrationConsistency(root, name, config, ftlDir) {
|
|
|
129
129
|
// comparisons hashed raw bytes, so on a CRLF checkout `furnace status`
|
|
130
130
|
// and `furnace validate` reported drift for files apply had just
|
|
131
131
|
// decided were identical.
|
|
132
|
-
const srcHash =
|
|
133
|
-
const destHash =
|
|
132
|
+
const srcHash = sha256Hex(normalizeForChecksum(srcContent));
|
|
133
|
+
const destHash = sha256Hex(normalizeForChecksum(destContent));
|
|
134
134
|
if (srcHash !== destHash) {
|
|
135
135
|
status.driftedFiles.push(entry.name);
|
|
136
136
|
status.filesInSync = false;
|
|
@@ -155,10 +155,8 @@ export async function checkRegistrationConsistency(root, name, config, ftlDir) {
|
|
|
155
155
|
else {
|
|
156
156
|
const srcContent = await readText(ftlSrc);
|
|
157
157
|
const destContent = await readText(ftlDest);
|
|
158
|
-
const srcHash =
|
|
159
|
-
const destHash =
|
|
160
|
-
.update(normalizeForChecksum(destContent))
|
|
161
|
-
.digest('hex');
|
|
158
|
+
const srcHash = sha256Hex(normalizeForChecksum(srcContent));
|
|
159
|
+
const destHash = sha256Hex(normalizeForChecksum(destContent));
|
|
162
160
|
if (srcHash !== destHash) {
|
|
163
161
|
status.driftedFiles.push(ftlName);
|
|
164
162
|
status.filesInSync = false;
|
|
@@ -47,7 +47,9 @@ export interface GitStatusEntry {
|
|
|
47
47
|
isDeleted: boolean;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Ensures git is available in the system.
|
|
50
|
+
* Ensures git is available in the system. Memoised after the first successful
|
|
51
|
+
* probe; {@link git} calls it, so callers that go through that wrapper do not
|
|
52
|
+
* need to.
|
|
51
53
|
* @throws GitNotFoundError if git is not installed
|
|
52
54
|
*/
|
|
53
55
|
export declare function ensureGit(): Promise<void>;
|
|
@@ -43,12 +43,33 @@ export const GIT_ADD_TIMEOUT_MS = resolveTimeoutFromEnv(GIT_ADD_TIMEOUT_ENV_VAR,
|
|
|
43
43
|
*/
|
|
44
44
|
export const GIT_ADD_CHUNK_TIMEOUT_MS = resolveTimeoutFromEnv(GIT_ADD_CHUNK_TIMEOUT_ENV_VAR, DEFAULT_GIT_ADD_CHUNK_TIMEOUT_MS);
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* In-flight or settled successful `git` availability probe.
|
|
47
|
+
*
|
|
48
|
+
* The probe spawns `which git` (or `where` on Windows), and every git wrapper
|
|
49
|
+
* in this layer used to run it before each command — dozens of extra spawns
|
|
50
|
+
* per `fireforge export`. Only SUCCESS is cached: a rejection clears the slot
|
|
51
|
+
* so a run that installs git mid-flight (or a test that flips the probe) sees
|
|
52
|
+
* the new answer instead of a sticky refusal.
|
|
53
|
+
*/
|
|
54
|
+
let gitAvailability;
|
|
55
|
+
/**
|
|
56
|
+
* Ensures git is available in the system. Memoised after the first successful
|
|
57
|
+
* probe; {@link git} calls it, so callers that go through that wrapper do not
|
|
58
|
+
* need to.
|
|
47
59
|
* @throws GitNotFoundError if git is not installed
|
|
48
60
|
*/
|
|
49
61
|
export async function ensureGit() {
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
gitAvailability ??= (async () => {
|
|
63
|
+
if (!(await executableExists('git'))) {
|
|
64
|
+
throw new GitNotFoundError();
|
|
65
|
+
}
|
|
66
|
+
})();
|
|
67
|
+
try {
|
|
68
|
+
await gitAvailability;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
gitAvailability = undefined;
|
|
72
|
+
throw error;
|
|
52
73
|
}
|
|
53
74
|
}
|
|
54
75
|
/**
|
|
@@ -58,6 +79,7 @@ export async function ensureGit() {
|
|
|
58
79
|
* @returns Command output
|
|
59
80
|
*/
|
|
60
81
|
export async function git(args, cwd, options) {
|
|
82
|
+
await ensureGit();
|
|
61
83
|
const execOptions = { cwd };
|
|
62
84
|
if (options?.timeout !== undefined) {
|
|
63
85
|
execOptions.timeout = options.timeout;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** How a new file is carried in a patch, plus its text when it is text. */
|
|
2
|
+
export type NewFileContent = {
|
|
3
|
+
readonly binary: true;
|
|
4
|
+
} | {
|
|
5
|
+
readonly binary: false;
|
|
6
|
+
readonly content: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Reads a new (untracked) file and classifies it for patch generation.
|
|
10
|
+
*
|
|
11
|
+
* A file is binary when git's NUL-byte heuristic says so
|
|
12
|
+
* ({@link isBinaryFile}) OR when its bytes are not valid UTF-8 — see the
|
|
13
|
+
* module comment for why the second arm exists. Text files come back with
|
|
14
|
+
* their exact decoded content so callers do not read the file twice.
|
|
15
|
+
*
|
|
16
|
+
* @param repoDir - Repository directory
|
|
17
|
+
* @param filePath - File path (relative to repo root)
|
|
18
|
+
* @returns The classification, with content for text files
|
|
19
|
+
*/
|
|
20
|
+
export declare function readNewFileContent(repoDir: string, filePath: string): Promise<NewFileContent>;
|
|
21
|
+
/**
|
|
22
|
+
* Runs `task` with git config arguments that force `filePath` to be diffed
|
|
23
|
+
* as binary.
|
|
24
|
+
*
|
|
25
|
+
* `git diff --binary` only emits a `GIT binary patch` for a file git itself
|
|
26
|
+
* classifies as binary, and git's classifier is the NUL heuristic — a
|
|
27
|
+
* Latin-1 file passes it and comes out as a TEXT diff whose high bytes are
|
|
28
|
+
* then mangled by the UTF-8 decode every subprocess result goes through.
|
|
29
|
+
* The `-diff` attribute is how git is told otherwise, and a throwaway
|
|
30
|
+
* `core.attributesFile` naming just this path is the narrowest way to set it
|
|
31
|
+
* without touching the tree's own `.gitattributes`. (An in-tree attribute
|
|
32
|
+
* that explicitly sets `diff` for the path would still win; the tree's own
|
|
33
|
+
* attributes are its business.)
|
|
34
|
+
*
|
|
35
|
+
* @param filePath - File path (relative to repo root)
|
|
36
|
+
* @param task - Receives `['-c', 'core.attributesFile=...']` to splice ahead
|
|
37
|
+
* of the git subcommand
|
|
38
|
+
* @returns Whatever `task` returns
|
|
39
|
+
*/
|
|
40
|
+
export declare function withForcedBinaryAttribute<T>(filePath: string, task: (gitConfigArgs: string[]) => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Decides how a NEW (untracked) file travels inside a patch: as a synthesized
|
|
4
|
+
* `+`-line text body, or as a `GIT binary patch`.
|
|
5
|
+
*
|
|
6
|
+
* The text body is built from a JavaScript string, and the `index` line next
|
|
7
|
+
* to it comes from `git hash-object` over the file's real bytes. Those two
|
|
8
|
+
* agree only when the bytes decode losslessly as UTF-8. A Latin-1
|
|
9
|
+
* `.properties` or `.rc` file has no NUL byte — git's own binary heuristic
|
|
10
|
+
* calls it text — but a UTF-8 decode turns every high byte into U+FFFD, so
|
|
11
|
+
* the patch body and its blob hash disagree, `git apply` writes different
|
|
12
|
+
* bytes than the tree holds, and every drift check flags the file forever.
|
|
13
|
+
* A binary patch carries the bytes verbatim, so it is the faithful choice for
|
|
14
|
+
* anything that is not valid UTF-8. This module is the single place that
|
|
15
|
+
* decision is made.
|
|
16
|
+
*/
|
|
17
|
+
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { isBinaryFile } from './git-file-ops.js';
|
|
21
|
+
// `ignoreBOM: true` keeps a leading U+FEFF in the output instead of silently
|
|
22
|
+
// consuming it, matching `readFile(path, 'utf-8')`, so a BOM-prefixed file
|
|
23
|
+
// still renders the byte the blob hash was computed over.
|
|
24
|
+
const strictUtf8 = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
25
|
+
/**
|
|
26
|
+
* Decodes bytes as UTF-8, or reports that they are not valid UTF-8.
|
|
27
|
+
* @param bytes - Raw file bytes
|
|
28
|
+
* @returns The decoded text, or undefined when any sequence is malformed
|
|
29
|
+
*/
|
|
30
|
+
function decodeStrictUtf8(bytes) {
|
|
31
|
+
try {
|
|
32
|
+
return strictUtf8.decode(bytes);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
void error;
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Reads a new (untracked) file and classifies it for patch generation.
|
|
41
|
+
*
|
|
42
|
+
* A file is binary when git's NUL-byte heuristic says so
|
|
43
|
+
* ({@link isBinaryFile}) OR when its bytes are not valid UTF-8 — see the
|
|
44
|
+
* module comment for why the second arm exists. Text files come back with
|
|
45
|
+
* their exact decoded content so callers do not read the file twice.
|
|
46
|
+
*
|
|
47
|
+
* @param repoDir - Repository directory
|
|
48
|
+
* @param filePath - File path (relative to repo root)
|
|
49
|
+
* @returns The classification, with content for text files
|
|
50
|
+
*/
|
|
51
|
+
export async function readNewFileContent(repoDir, filePath) {
|
|
52
|
+
if (await isBinaryFile(repoDir, filePath)) {
|
|
53
|
+
return { binary: true };
|
|
54
|
+
}
|
|
55
|
+
const content = decodeStrictUtf8(await readFile(join(repoDir, filePath)));
|
|
56
|
+
if (content === undefined) {
|
|
57
|
+
return { binary: true };
|
|
58
|
+
}
|
|
59
|
+
return { binary: false, content };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Renders one repo-relative path as an anchored, literal gitattributes
|
|
63
|
+
* pattern: the whole thing is C-quoted (which gitattributes accepts for
|
|
64
|
+
* patterns holding spaces or `#`) and glob metacharacters carry a backslash
|
|
65
|
+
* that survives the unquoting, so git matches them literally.
|
|
66
|
+
*
|
|
67
|
+
* Both escapes are applied in a single pass, keyed on the source character.
|
|
68
|
+
* Escaping in two passes would re-escape the backslashes the first pass just
|
|
69
|
+
* added, and a backslash that is part of the filename would have to be
|
|
70
|
+
* escaped for the glob layer as well as the quoting layer — which a
|
|
71
|
+
* glob-only first pass cannot tell apart from one it emitted itself.
|
|
72
|
+
*
|
|
73
|
+
* @param filePath - File path (relative to repo root)
|
|
74
|
+
* @returns A pattern matching exactly that path
|
|
75
|
+
*/
|
|
76
|
+
function toLiteralAttributePattern(filePath) {
|
|
77
|
+
// `"` only needs the quoting layer, so one backslash. A glob
|
|
78
|
+
// metacharacter takes a backslash for the glob layer, which the quoting
|
|
79
|
+
// layer then doubles into two. A literal `\` is both: the glob layer
|
|
80
|
+
// doubles it, then the quoting layer doubles that again, for four.
|
|
81
|
+
const escaped = filePath.replace(/["\\*?[\]]/g, (char) => {
|
|
82
|
+
if (char === '"')
|
|
83
|
+
return '\\"';
|
|
84
|
+
if (char === '\\')
|
|
85
|
+
return '\\\\\\\\';
|
|
86
|
+
return `\\\\${char}`;
|
|
87
|
+
});
|
|
88
|
+
return `"/${escaped}"`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Runs `task` with git config arguments that force `filePath` to be diffed
|
|
92
|
+
* as binary.
|
|
93
|
+
*
|
|
94
|
+
* `git diff --binary` only emits a `GIT binary patch` for a file git itself
|
|
95
|
+
* classifies as binary, and git's classifier is the NUL heuristic — a
|
|
96
|
+
* Latin-1 file passes it and comes out as a TEXT diff whose high bytes are
|
|
97
|
+
* then mangled by the UTF-8 decode every subprocess result goes through.
|
|
98
|
+
* The `-diff` attribute is how git is told otherwise, and a throwaway
|
|
99
|
+
* `core.attributesFile` naming just this path is the narrowest way to set it
|
|
100
|
+
* without touching the tree's own `.gitattributes`. (An in-tree attribute
|
|
101
|
+
* that explicitly sets `diff` for the path would still win; the tree's own
|
|
102
|
+
* attributes are its business.)
|
|
103
|
+
*
|
|
104
|
+
* @param filePath - File path (relative to repo root)
|
|
105
|
+
* @param task - Receives `['-c', 'core.attributesFile=...']` to splice ahead
|
|
106
|
+
* of the git subcommand
|
|
107
|
+
* @returns Whatever `task` returns
|
|
108
|
+
*/
|
|
109
|
+
export async function withForcedBinaryAttribute(filePath, task) {
|
|
110
|
+
const tempDir = await mkdtemp(join(tmpdir(), 'fireforge-attr-'));
|
|
111
|
+
try {
|
|
112
|
+
const attributesFile = join(tempDir, 'attributes');
|
|
113
|
+
await writeFile(attributesFile, `${toLiteralAttributePattern(filePath)} -diff\n`);
|
|
114
|
+
return await task(['-c', `core.attributesFile=${attributesFile}`]);
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export declare function getFileDiff(repoDir: string, filePath: string): Promise<string>;
|
|
14
14
|
/**
|
|
15
|
-
* Generates a unified diff for a new (untracked) file.
|
|
15
|
+
* Generates a unified diff for a new (untracked) file. A file that is binary
|
|
16
|
+
* or not valid UTF-8 (see {@link readNewFileContent}) is routed through
|
|
17
|
+
* {@link generateBinaryFilePatch} instead, because a text body cannot carry
|
|
18
|
+
* its bytes faithfully.
|
|
16
19
|
* @param repoDir - Repository directory
|
|
17
20
|
* @param filePath - Path to the file (relative to repo)
|
|
18
21
|
* @returns Diff content in unified diff format
|
|
@@ -28,14 +31,6 @@ export declare function generateNewFileDiff(repoDir: string, filePath: string):
|
|
|
28
31
|
* @returns Diff content in unified diff format
|
|
29
32
|
*/
|
|
30
33
|
export declare function generateFullFilePatch(repoDir: string, filePath: string): Promise<string>;
|
|
31
|
-
/**
|
|
32
|
-
* Generates a unified diff between base content and current file content.
|
|
33
|
-
* @param repoDir - Repository directory
|
|
34
|
-
* @param filePath - Path to the file (relative to repo)
|
|
35
|
-
* @param baseContent - The base content to diff against
|
|
36
|
-
* @returns Unified diff in git format
|
|
37
|
-
*/
|
|
38
|
-
export declare function generateModificationDiff(repoDir: string, filePath: string, baseContent: string): Promise<string>;
|
|
39
34
|
/**
|
|
40
35
|
* Gets the diff for all modified files, including untracked (new) files.
|
|
41
36
|
*
|
|
@@ -75,6 +70,11 @@ export declare function getStagedDiffForFiles(repoDir: string, files: string[]):
|
|
|
75
70
|
* Generates a GIT binary patch for a binary file.
|
|
76
71
|
* For tracked files, uses `git diff --binary HEAD`.
|
|
77
72
|
* For untracked files, temporarily stages with `--intent-to-add` to produce a diff.
|
|
73
|
+
*
|
|
74
|
+
* Every `git diff` here runs under {@link withForcedBinaryAttribute}: a
|
|
75
|
+
* caller sends a file down this arm because a text body cannot carry its
|
|
76
|
+
* bytes (NUL, or not valid UTF-8), and git's own NUL-only heuristic would
|
|
77
|
+
* otherwise still render the non-UTF-8 case as text.
|
|
78
78
|
* @param repoDir - Repository directory
|
|
79
79
|
* @param filePath - File path (relative to repo root)
|
|
80
80
|
* @returns The binary diff string, or empty string if no diff
|