@hominis/fireforge 0.34.2 → 0.36.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 +48 -0
- package/README.md +43 -5
- package/dist/bin/fireforge.d.ts +4 -0
- package/dist/bin/fireforge.js +25 -6
- package/dist/src/cli.js +22 -5
- package/dist/src/commands/bootstrap-checks.js +0 -1
- package/dist/src/commands/bootstrap.d.ts +2 -1
- package/dist/src/commands/bootstrap.js +16 -7
- package/dist/src/commands/build.js +17 -3
- package/dist/src/commands/config.js +30 -10
- package/dist/src/commands/discard.js +24 -5
- package/dist/src/commands/doctor/post-rebase-audit.js +0 -1
- package/dist/src/commands/doctor-check-core.js +0 -1
- package/dist/src/commands/doctor-external-toolchains.d.ts +3 -0
- package/dist/src/commands/doctor-external-toolchains.js +54 -0
- package/dist/src/commands/doctor-furnace-jar.js +0 -1
- package/dist/src/commands/doctor-furnace-manifest-sync.js +0 -1
- package/dist/src/commands/doctor-furnace.js +2 -2
- package/dist/src/commands/doctor-working-tree.js +0 -1
- package/dist/src/commands/doctor.js +4 -1
- package/dist/src/commands/download.js +51 -15
- package/dist/src/commands/export-all.js +5 -3
- package/dist/src/commands/export-flow.js +12 -7
- package/dist/src/commands/export-placement-gate.js +0 -1
- package/dist/src/commands/export-placement-policy.js +0 -1
- package/dist/src/commands/export-shared.d.ts +5 -1
- package/dist/src/commands/export-shared.js +18 -6
- package/dist/src/commands/export.js +15 -10
- package/dist/src/commands/furnace/apply.js +22 -6
- package/dist/src/commands/furnace/chrome-doc-remove.js +0 -1
- package/dist/src/commands/furnace/chrome-doc-templates.js +0 -1
- package/dist/src/commands/furnace/chrome-doc-tests.js +0 -1
- package/dist/src/commands/furnace/chrome-doc.js +0 -1
- package/dist/src/commands/furnace/create-browser-test.js +0 -1
- package/dist/src/commands/furnace/create-dry-run.js +0 -1
- package/dist/src/commands/furnace/create-features.js +0 -1
- package/dist/src/commands/furnace/create-mochikit.js +0 -1
- package/dist/src/commands/furnace/create-readback.js +0 -1
- package/dist/src/commands/furnace/create-templates.js +0 -1
- package/dist/src/commands/furnace/create-validation.js +0 -1
- package/dist/src/commands/furnace/create-xpcshell.js +0 -1
- package/dist/src/commands/furnace/create.js +0 -1
- package/dist/src/commands/furnace/deploy.js +7 -83
- package/dist/src/commands/furnace/diff.js +0 -1
- package/dist/src/commands/furnace/index.js +59 -25
- package/dist/src/commands/furnace/init.js +0 -1
- package/dist/src/commands/furnace/list.js +0 -1
- package/dist/src/commands/furnace/override.js +0 -1
- package/dist/src/commands/furnace/preview.js +3 -3
- package/dist/src/commands/furnace/refresh.js +0 -1
- package/dist/src/commands/furnace/remove-state.d.ts +15 -0
- package/dist/src/commands/furnace/remove-state.js +47 -1
- package/dist/src/commands/furnace/remove.js +3 -9
- package/dist/src/commands/furnace/rename-browser-test.js +1 -5
- package/dist/src/commands/furnace/rename-helpers.d.ts +6 -0
- package/dist/src/commands/furnace/rename-helpers.js +30 -1
- package/dist/src/commands/furnace/rename-xpcshell.js +7 -6
- package/dist/src/commands/furnace/rename.js +15 -36
- package/dist/src/commands/furnace/scan.js +0 -1
- package/dist/src/commands/furnace/status.js +0 -1
- package/dist/src/commands/furnace/sync.js +76 -4
- package/dist/src/commands/furnace/validate.js +0 -1
- package/dist/src/commands/furnace/validation-output.js +0 -1
- package/dist/src/commands/import.js +35 -9
- package/dist/src/commands/lint-per-patch.js +19 -7
- package/dist/src/commands/lint.js +13 -3
- package/dist/src/commands/manifest.js +1 -2
- package/dist/src/commands/package.js +2 -1
- package/dist/src/commands/patch/compact.js +1 -1
- package/dist/src/commands/patch/delete.js +1 -1
- package/dist/src/commands/patch/index.js +1 -1
- package/dist/src/commands/patch/lint-ignore.js +21 -6
- package/dist/src/commands/patch/move-files.js +1 -1
- package/dist/src/commands/patch/patch-context.js +0 -1
- package/dist/src/commands/patch/rename.js +4 -4
- package/dist/src/commands/patch/reorder.js +3 -4
- package/dist/src/commands/patch/split-plan.js +2 -1
- package/dist/src/commands/patch/split.js +4 -4
- package/dist/src/commands/patch/staged-dependency.js +1 -1
- package/dist/src/commands/patch/tier.js +18 -5
- package/dist/src/commands/re-export-bulk-scan.js +0 -1
- package/dist/src/commands/re-export-files.js +1 -1
- package/dist/src/commands/re-export-options.js +0 -1
- package/dist/src/commands/re-export-scan.js +0 -1
- package/dist/src/commands/re-export.js +6 -4
- package/dist/src/commands/rebase/abort.js +2 -9
- package/dist/src/commands/rebase/confirm.js +0 -1
- package/dist/src/commands/rebase/conflict-summary.js +0 -1
- package/dist/src/commands/rebase/continue.js +0 -1
- package/dist/src/commands/rebase/index.d.ts +1 -1
- package/dist/src/commands/rebase/index.js +10 -15
- package/dist/src/commands/rebase/patch-loop.js +38 -7
- package/dist/src/commands/rebase/summary.js +2 -3
- package/dist/src/commands/rebase.js +0 -1
- package/dist/src/commands/register.js +1 -1
- package/dist/src/commands/reset.js +16 -9
- package/dist/src/commands/resolve.js +2 -2
- package/dist/src/commands/run.js +18 -6
- package/dist/src/commands/setup-support.js +0 -1
- package/dist/src/commands/setup.js +1 -2
- package/dist/src/commands/source.js +1 -2
- package/dist/src/commands/status-output.js +1 -12
- package/dist/src/commands/status.js +147 -133
- package/dist/src/commands/test-appdir.js +0 -1
- package/dist/src/commands/test-diagnose.js +18 -2
- package/dist/src/commands/test-modes.d.ts +15 -0
- package/dist/src/commands/test-modes.js +61 -0
- package/dist/src/commands/test-register.d.ts +4 -0
- package/dist/src/commands/test-register.js +64 -0
- package/dist/src/commands/test-run.d.ts +23 -7
- package/dist/src/commands/test-run.js +15 -14
- package/dist/src/commands/test.d.ts +0 -4
- package/dist/src/commands/test.js +95 -56
- package/dist/src/commands/token-coverage.js +0 -1
- package/dist/src/commands/token.js +1 -2
- package/dist/src/commands/typecheck.js +1 -1
- package/dist/src/commands/verify.js +3 -9
- package/dist/src/commands/watch.js +5 -1
- package/dist/src/commands/wire.js +1 -1
- package/dist/src/core/ast-utils.js +0 -1
- package/dist/src/core/brand-validation.js +0 -1
- package/dist/src/core/branding.js +0 -1
- package/dist/src/core/browser-wire.js +0 -1
- package/dist/src/core/build-audit-platform.js +0 -1
- package/dist/src/core/build-audit-registration.js +0 -1
- package/dist/src/core/build-audit-resolve.js +0 -1
- package/dist/src/core/build-audit-transforms.js +0 -1
- package/dist/src/core/build-audit.js +0 -1
- package/dist/src/core/build-baseline-types.js +0 -1
- package/dist/src/core/build-baseline.js +0 -1
- package/dist/src/core/build-prepare.js +21 -7
- package/dist/src/core/config-mutate.js +0 -1
- package/dist/src/core/config-paths.d.ts +2 -2
- package/dist/src/core/config-paths.js +6 -1
- package/dist/src/core/config-state.js +0 -1
- package/dist/src/core/config-validate-patch-policy.js +0 -1
- package/dist/src/core/config-validate-test-toolchains.d.ts +8 -0
- package/dist/src/core/config-validate-test-toolchains.js +105 -0
- package/dist/src/core/config-validate.js +3 -1
- package/dist/src/core/config.js +0 -1
- package/dist/src/core/destructive.js +0 -1
- package/dist/src/core/diff-hunks.js +13 -7
- package/dist/src/core/engine-changes.js +0 -1
- package/dist/src/core/engine-session-lock.d.ts +12 -0
- package/dist/src/core/engine-session-lock.js +45 -0
- package/dist/src/core/file-lock.d.ts +8 -0
- package/dist/src/core/file-lock.js +157 -48
- package/dist/src/core/firefox-archive.d.ts +4 -0
- package/dist/src/core/firefox-archive.js +6 -1
- package/dist/src/core/firefox-cache.js +67 -8
- package/dist/src/core/firefox-download.js +0 -1
- package/dist/src/core/firefox-extract.d.ts +21 -1
- package/dist/src/core/firefox-extract.js +178 -9
- package/dist/src/core/firefox-ignorefile.js +0 -1
- package/dist/src/core/firefox.d.ts +12 -0
- package/dist/src/core/firefox.js +64 -2
- package/dist/src/core/furnace-apply-dry-run.js +0 -1
- package/dist/src/core/furnace-apply-ftl.d.ts +7 -3
- package/dist/src/core/furnace-apply-ftl.js +10 -5
- package/dist/src/core/furnace-apply-helpers.js +0 -1
- package/dist/src/core/furnace-apply-output.js +2 -2
- package/dist/src/core/furnace-apply.d.ts +7 -1
- package/dist/src/core/furnace-apply.js +47 -13
- package/dist/src/core/furnace-checksum-utils.js +0 -1
- package/dist/src/core/furnace-config-array-utils.js +0 -1
- package/dist/src/core/furnace-config-custom.js +0 -1
- package/dist/src/core/furnace-config-order.js +0 -1
- package/dist/src/core/furnace-config-tokens.js +0 -1
- package/dist/src/core/furnace-config-validate.js +0 -1
- package/dist/src/core/furnace-config.d.ts +11 -0
- package/dist/src/core/furnace-config.js +37 -1
- package/dist/src/core/furnace-constants.js +0 -1
- package/dist/src/core/furnace-css-fragments.js +0 -1
- package/dist/src/core/furnace-graph-utils.js +0 -1
- package/dist/src/core/furnace-jsconfig.d.ts +2 -3
- package/dist/src/core/furnace-jsconfig.js +25 -18
- package/dist/src/core/furnace-marker.js +0 -1
- package/dist/src/core/furnace-operation.js +0 -1
- package/dist/src/core/furnace-refresh.js +0 -1
- package/dist/src/core/furnace-registration-ast.d.ts +14 -0
- package/dist/src/core/furnace-registration-ast.js +1 -2
- package/dist/src/core/furnace-registration-remove.js +0 -1
- package/dist/src/core/furnace-registration-validate.js +1 -5
- package/dist/src/core/furnace-registration.js +0 -1
- package/dist/src/core/furnace-rollback.js +0 -1
- package/dist/src/core/furnace-scanner.js +0 -1
- package/dist/src/core/furnace-staleness.js +0 -1
- package/dist/src/core/furnace-state-persist.d.ts +72 -0
- package/dist/src/core/furnace-state-persist.js +118 -0
- package/dist/src/core/furnace-step-errors.d.ts +23 -0
- package/dist/src/core/furnace-step-errors.js +25 -0
- package/dist/src/core/furnace-stories.js +0 -1
- package/dist/src/core/furnace-validate-accessibility.js +0 -1
- package/dist/src/core/furnace-validate-checks.js +0 -1
- package/dist/src/core/furnace-validate-compatibility.js +0 -1
- package/dist/src/core/furnace-validate-helpers.js +0 -1
- package/dist/src/core/furnace-validate-registration.js +7 -7
- package/dist/src/core/furnace-validate-structure.d.ts +8 -0
- package/dist/src/core/furnace-validate-structure.js +11 -2
- package/dist/src/core/furnace-validate.js +0 -1
- package/dist/src/core/furnace-version-drift.d.ts +6 -3
- package/dist/src/core/furnace-version-drift.js +6 -4
- package/dist/src/core/git-base.js +0 -1
- package/dist/src/core/git-diff.js +0 -1
- package/dist/src/core/git-file-ops.js +0 -1
- package/dist/src/core/git-status.d.ts +13 -0
- package/dist/src/core/git-status.js +32 -2
- package/dist/src/core/git.d.ts +10 -1
- package/dist/src/core/git.js +65 -8
- package/dist/src/core/license-headers.d.ts +16 -0
- package/dist/src/core/license-headers.js +19 -1
- package/dist/src/core/lint-cache.js +0 -1
- package/dist/src/core/lint-projection.js +0 -1
- package/dist/src/core/mach-build-artifacts.js +0 -1
- package/dist/src/core/mach-error-hints.js +27 -1
- package/dist/src/core/mach-mozconfig.js +0 -1
- package/dist/src/core/mach-python.js +0 -1
- package/dist/src/core/mach-resource-shim.js +0 -1
- package/dist/src/core/mach.js +0 -1
- package/dist/src/core/manifest-helpers.js +0 -1
- package/dist/src/core/manifest-register.js +0 -1
- package/dist/src/core/manifest-rules.js +0 -1
- package/dist/src/core/manifest-tokenizers.js +0 -1
- package/dist/src/core/marionette-port.d.ts +8 -0
- package/dist/src/core/marionette-port.js +34 -3
- package/dist/src/core/marionette-preflight.js +0 -1
- package/dist/src/core/markdown-table.js +0 -1
- package/dist/src/core/ownership-table.js +2 -9
- package/dist/src/core/parser-fallback.js +0 -1
- package/dist/src/core/patch-apply-fuzz.d.ts +27 -9
- package/dist/src/core/patch-apply-fuzz.js +71 -34
- package/dist/src/core/patch-apply.d.ts +30 -0
- package/dist/src/core/patch-apply.js +152 -39
- package/dist/src/core/patch-artifact-normalize.d.ts +18 -5
- package/dist/src/core/patch-artifact-normalize.js +19 -15
- package/dist/src/core/patch-export-coverage.js +0 -1
- package/dist/src/core/patch-export-metadata.js +0 -1
- package/dist/src/core/patch-export-update.js +2 -3
- package/dist/src/core/patch-export.d.ts +2 -6
- package/dist/src/core/patch-export.js +24 -48
- package/dist/src/core/patch-files.js +0 -1
- package/dist/src/core/patch-identifier-suggest.js +0 -1
- package/dist/src/core/patch-lint-checkjs.js +0 -1
- package/dist/src/core/patch-lint-chrome-jsdoc.js +0 -1
- package/dist/src/core/patch-lint-cross.js +0 -1
- package/dist/src/core/patch-lint-css.js +0 -1
- package/dist/src/core/patch-lint-diff-tag.js +0 -1
- package/dist/src/core/patch-lint-diff.d.ts +2 -1
- package/dist/src/core/patch-lint-diff.js +17 -32
- package/dist/src/core/patch-lint-imports.js +0 -1
- package/dist/src/core/patch-lint-jsdoc.js +0 -1
- package/dist/src/core/patch-lint-observer.js +0 -1
- package/dist/src/core/patch-lint-ownership.js +0 -1
- package/dist/src/core/patch-lint-reexports.js +0 -1
- package/dist/src/core/patch-lint.d.ts +37 -2
- package/dist/src/core/patch-lint.js +48 -24
- package/dist/src/core/patch-lock.js +0 -1
- package/dist/src/core/patch-manifest-consistency.js +9 -1
- package/dist/src/core/patch-manifest-io.d.ts +16 -0
- package/dist/src/core/patch-manifest-io.js +37 -12
- package/dist/src/core/patch-manifest-query.d.ts +6 -0
- package/dist/src/core/patch-manifest-query.js +27 -12
- package/dist/src/core/patch-manifest-resolve.js +0 -1
- package/dist/src/core/patch-manifest-validate.js +0 -1
- package/dist/src/core/patch-manifest.d.ts +1 -1
- package/dist/src/core/patch-manifest.js +1 -2
- package/dist/src/core/patch-parse.d.ts +59 -0
- package/dist/src/core/patch-parse.js +209 -92
- package/dist/src/core/patch-policy.js +0 -1
- package/dist/src/core/patch-registration-refs.js +16 -26
- package/dist/src/core/patch-source-metadata.js +0 -1
- package/dist/src/core/patch-transform.d.ts +4 -0
- package/dist/src/core/patch-transform.js +30 -38
- package/dist/src/core/rebase-session.js +0 -1
- package/dist/src/core/register-browser-content.js +0 -1
- package/dist/src/core/register-module.js +0 -1
- package/dist/src/core/register-result.js +0 -1
- package/dist/src/core/register-scaffold.js +0 -1
- package/dist/src/core/register-shared-css.js +0 -1
- package/dist/src/core/register-test-manifest.js +0 -1
- package/dist/src/core/register-xpcshell-test.js +0 -1
- package/dist/src/core/shared-ftl.js +0 -1
- package/dist/src/core/signal-critical.js +0 -1
- package/dist/src/core/smoke-patterns.js +0 -1
- package/dist/src/core/state-file.js +0 -1
- package/dist/src/core/status-classify.d.ts +16 -0
- package/dist/src/core/status-classify.js +24 -16
- package/dist/src/core/test-harness-crash.d.ts +64 -7
- package/dist/src/core/test-harness-crash.js +196 -15
- package/dist/src/core/test-harness-output.js +0 -1
- package/dist/src/core/test-path-scope.d.ts +62 -0
- package/dist/src/core/test-path-scope.js +148 -0
- package/dist/src/core/test-stale-check.js +0 -1
- package/dist/src/core/test-stale-symlink.js +0 -1
- package/dist/src/core/test-xpcshell-retry.js +0 -1
- package/dist/src/core/token-coverage.js +0 -1
- package/dist/src/core/token-dark-mode.js +0 -1
- package/dist/src/core/token-docs.js +0 -1
- package/dist/src/core/token-manager.js +0 -1
- package/dist/src/core/token-scaffold.js +0 -1
- package/dist/src/core/token-variant.js +0 -1
- package/dist/src/core/toolchain-preflight.d.ts +85 -0
- package/dist/src/core/toolchain-preflight.js +256 -0
- package/dist/src/core/typecheck-shim.d.ts +4 -1
- package/dist/src/core/typecheck-shim.js +61 -18
- package/dist/src/core/typecheck.js +0 -1
- package/dist/src/core/wire-destroy.js +0 -1
- package/dist/src/core/wire-dom-fragment.js +0 -1
- package/dist/src/core/wire-init.js +0 -1
- package/dist/src/core/wire-subscript.js +0 -1
- package/dist/src/core/wire-targets.js +0 -1
- package/dist/src/core/wire-utils.js +0 -1
- package/dist/src/core/xpcshell-appdir.js +1 -4
- package/dist/src/errors/base.d.ts +29 -0
- package/dist/src/errors/base.js +35 -1
- package/dist/src/errors/build.js +0 -1
- package/dist/src/errors/codes.d.ts +6 -0
- package/dist/src/errors/codes.js +6 -1
- package/dist/src/errors/config.js +0 -1
- package/dist/src/errors/download.js +2 -1
- package/dist/src/errors/furnace.d.ts +11 -1
- package/dist/src/errors/furnace.js +6 -5
- package/dist/src/errors/git.js +0 -1
- package/dist/src/errors/patch.d.ts +17 -0
- package/dist/src/errors/patch.js +29 -1
- package/dist/src/errors/rebase.js +0 -1
- package/dist/src/errors/run.js +1 -1
- package/dist/src/index.js +0 -1
- package/dist/src/types/cli.js +0 -1
- package/dist/src/types/commands/index.js +0 -1
- package/dist/src/types/commands/options.d.ts +20 -5
- package/dist/src/types/commands/options.js +0 -1
- package/dist/src/types/commands/patches.d.ts +8 -0
- package/dist/src/types/commands/patches.js +0 -1
- package/dist/src/types/commands/project.d.ts +11 -2
- package/dist/src/types/commands/project.js +0 -1
- package/dist/src/types/config.d.ts +32 -0
- package/dist/src/types/config.js +0 -1
- package/dist/src/types/furnace.d.ts +10 -0
- package/dist/src/types/furnace.js +0 -1
- package/dist/src/types/index.js +0 -1
- package/dist/src/types/typecheck.js +0 -1
- package/dist/src/utils/elapsed.js +0 -1
- package/dist/src/utils/errors.js +0 -1
- package/dist/src/utils/fs.js +37 -5
- package/dist/src/utils/logger.d.ts +7 -0
- package/dist/src/utils/logger.js +85 -3
- package/dist/src/utils/options.d.ts +15 -0
- package/dist/src/utils/options.js +25 -1
- package/dist/src/utils/package-root.js +11 -4
- package/dist/src/utils/parse.js +0 -1
- package/dist/src/utils/paths.js +0 -1
- package/dist/src/utils/platform.js +0 -1
- package/dist/src/utils/process.d.ts +33 -4
- package/dist/src/utils/process.js +183 -28
- package/dist/src/utils/regex.d.ts +13 -3
- package/dist/src/utils/regex.js +53 -4
- package/dist/src/utils/validation.d.ts +0 -12
- package/dist/src/utils/validation.js +13 -26
- package/package.json +8 -7
|
@@ -12,8 +12,9 @@ import { rename } from 'node:fs/promises';
|
|
|
12
12
|
import { join } from 'node:path';
|
|
13
13
|
import { FireForgeError } from '../errors/base.js';
|
|
14
14
|
import { ExitCode } from '../errors/codes.js';
|
|
15
|
+
import { PatchManifestCorruptError } from '../errors/patch.js';
|
|
15
16
|
import { toError } from '../utils/errors.js';
|
|
16
|
-
import {
|
|
17
|
+
import { pathExistsStrict, readJson, removeFile, writeJson } from '../utils/fs.js';
|
|
17
18
|
import { warn } from '../utils/logger.js';
|
|
18
19
|
import { isArray, isObject } from '../utils/validation.js';
|
|
19
20
|
import { validatePatchesManifest } from './patch-manifest-validate.js';
|
|
@@ -25,7 +26,7 @@ export const PATCHES_MANIFEST = 'patches.json';
|
|
|
25
26
|
*/
|
|
26
27
|
export async function loadPatchesManifestState(patchesDir) {
|
|
27
28
|
const manifestPath = join(patchesDir, PATCHES_MANIFEST);
|
|
28
|
-
if (!(await
|
|
29
|
+
if (!(await pathExistsStrict(manifestPath))) {
|
|
29
30
|
return { exists: false, manifest: null, parseError: undefined };
|
|
30
31
|
}
|
|
31
32
|
try {
|
|
@@ -46,6 +47,13 @@ export async function loadPatchesManifestState(patchesDir) {
|
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Loads the patches manifest if it exists.
|
|
50
|
+
*
|
|
51
|
+
* READ-ONLY callers only: this collapses "absent" and "corrupt" into null.
|
|
52
|
+
* Any code path that will WRITE the manifest (or delete patch files based
|
|
53
|
+
* on its content) must use {@link loadPatchesManifestForWrite} instead —
|
|
54
|
+
* treating a corrupt manifest as empty and then saving destroys every
|
|
55
|
+
* existing patch's metadata.
|
|
56
|
+
*
|
|
49
57
|
* @param patchesDir - Path to the patches directory
|
|
50
58
|
* @returns PatchesManifest or null if not found
|
|
51
59
|
*/
|
|
@@ -53,6 +61,21 @@ export async function loadPatchesManifest(patchesDir) {
|
|
|
53
61
|
const state = await loadPatchesManifestState(patchesDir);
|
|
54
62
|
return state.manifest;
|
|
55
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Loads the patches manifest for a mutating operation.
|
|
66
|
+
*
|
|
67
|
+
* Returns null only when the manifest genuinely does not exist; a manifest
|
|
68
|
+
* that exists but fails to parse/validate throws
|
|
69
|
+
* {@link PatchManifestCorruptError} so the caller aborts instead of
|
|
70
|
+
* rebuilding an empty queue over the top of the corrupt file.
|
|
71
|
+
*/
|
|
72
|
+
export async function loadPatchesManifestForWrite(patchesDir) {
|
|
73
|
+
const state = await loadPatchesManifestState(patchesDir);
|
|
74
|
+
if (state.exists && state.manifest === null) {
|
|
75
|
+
throw new PatchManifestCorruptError(join(patchesDir, PATCHES_MANIFEST), state.parseError);
|
|
76
|
+
}
|
|
77
|
+
return state.manifest;
|
|
78
|
+
}
|
|
56
79
|
/**
|
|
57
80
|
* Saves the patches manifest.
|
|
58
81
|
* @param patchesDir - Path to the patches directory
|
|
@@ -70,7 +93,7 @@ export async function savePatchesManifest(patchesDir, manifest) {
|
|
|
70
93
|
*/
|
|
71
94
|
export async function mutatePatchRowsInManifest(patchesDir, filenames, mutator) {
|
|
72
95
|
const manifestPath = join(patchesDir, PATCHES_MANIFEST);
|
|
73
|
-
if (!(await
|
|
96
|
+
if (!(await pathExistsStrict(manifestPath)))
|
|
74
97
|
return null;
|
|
75
98
|
const rawManifest = await readJson(manifestPath);
|
|
76
99
|
const beforeManifest = validatePatchesManifest(rawManifest);
|
|
@@ -125,7 +148,8 @@ export async function mutatePatchRowsInManifest(patchesDir, filenames, mutator)
|
|
|
125
148
|
* @param removeFilenames - Optional filenames to remove in the same read-modify-write cycle
|
|
126
149
|
*/
|
|
127
150
|
export async function addPatchToManifest(patchesDir, metadata, removeFilenames) {
|
|
128
|
-
|
|
151
|
+
// ForWrite: a corrupt manifest must abort here, not be rebuilt as empty.
|
|
152
|
+
const manifest = (await loadPatchesManifestForWrite(patchesDir)) ?? {
|
|
129
153
|
version: 1,
|
|
130
154
|
patches: [],
|
|
131
155
|
};
|
|
@@ -156,7 +180,7 @@ export async function addPatchToManifest(patchesDir, metadata, removeFilenames)
|
|
|
156
180
|
* false when no matching entry existed
|
|
157
181
|
*/
|
|
158
182
|
export async function removePatchFromManifest(patchesDir, filename) {
|
|
159
|
-
const manifest = await
|
|
183
|
+
const manifest = await loadPatchesManifestForWrite(patchesDir);
|
|
160
184
|
if (!manifest)
|
|
161
185
|
return false;
|
|
162
186
|
const originalLength = manifest.patches.length;
|
|
@@ -240,7 +264,7 @@ export function rewriteStagedDependencyOwners(patch, renameLookup) {
|
|
|
240
264
|
export async function renumberPatchesInManifest(patchesDir, renameMap) {
|
|
241
265
|
if (renameMap.size === 0)
|
|
242
266
|
return;
|
|
243
|
-
const manifest = await
|
|
267
|
+
const manifest = await loadPatchesManifestForWrite(patchesDir);
|
|
244
268
|
if (!manifest) {
|
|
245
269
|
throw new Error('Cannot renumber patches: patches.json is missing.');
|
|
246
270
|
}
|
|
@@ -252,7 +276,7 @@ export async function renumberPatchesInManifest(patchesDir, renameMap) {
|
|
|
252
276
|
try {
|
|
253
277
|
for (const [oldFilename, entry] of renameMap) {
|
|
254
278
|
const oldPath = join(patchesDir, oldFilename);
|
|
255
|
-
if (!(await
|
|
279
|
+
if (!(await pathExistsStrict(oldPath))) {
|
|
256
280
|
throw new Error(`Cannot renumber: patch file is missing on disk: ${oldFilename}`);
|
|
257
281
|
}
|
|
258
282
|
const stagedName = `.fireforge-renumber-${stagingId}-${oldFilename}`;
|
|
@@ -280,7 +304,7 @@ export async function renumberPatchesInManifest(patchesDir, renameMap) {
|
|
|
280
304
|
for (const stagedEntry of stagedRenames) {
|
|
281
305
|
const { staged, toEntry } = stagedEntry;
|
|
282
306
|
const targetPath = join(patchesDir, toEntry.newFilename);
|
|
283
|
-
if (await
|
|
307
|
+
if (await pathExistsStrict(targetPath)) {
|
|
284
308
|
throw new Error(`Cannot renumber: target patch filename already exists on disk: ${toEntry.newFilename}`);
|
|
285
309
|
}
|
|
286
310
|
await rename(join(patchesDir, staged), targetPath);
|
|
@@ -291,7 +315,7 @@ export async function renumberPatchesInManifest(patchesDir, renameMap) {
|
|
|
291
315
|
// described: manifest rewrote to new filenames while the old
|
|
292
316
|
// files stayed on disk. If the assert ever fires, the Phase 2
|
|
293
317
|
// rollback will undo prior moves before re-throwing.
|
|
294
|
-
if (!(await
|
|
318
|
+
if (!(await pathExistsStrict(targetPath))) {
|
|
295
319
|
throw new Error(`Rename postcondition failed: expected ${toEntry.newFilename} to exist after rename, but it was not found on disk.`);
|
|
296
320
|
}
|
|
297
321
|
completedFinalRenames.push(stagedEntry);
|
|
@@ -425,10 +449,12 @@ export class PatchDeleteRollbackError extends FireForgeError {
|
|
|
425
449
|
*/
|
|
426
450
|
export async function removePatchFileAndManifest(patchesDir, filename) {
|
|
427
451
|
const patchPath = join(patchesDir, filename);
|
|
428
|
-
|
|
452
|
+
// ForWrite: deleting the patch FILE while a corrupt manifest still
|
|
453
|
+
// references it would strand the queue; abort on corruption instead.
|
|
454
|
+
const originalManifest = await loadPatchesManifestForWrite(patchesDir);
|
|
429
455
|
const removedFromManifest = await removePatchFromManifest(patchesDir, filename);
|
|
430
456
|
try {
|
|
431
|
-
if (await
|
|
457
|
+
if (await pathExistsStrict(patchPath)) {
|
|
432
458
|
await removeFile(patchPath);
|
|
433
459
|
}
|
|
434
460
|
}
|
|
@@ -451,4 +477,3 @@ export async function removePatchFileAndManifest(patchesDir, filename) {
|
|
|
451
477
|
throw deleteError;
|
|
452
478
|
}
|
|
453
479
|
}
|
|
454
|
-
//# sourceMappingURL=patch-manifest-io.js.map
|
|
@@ -42,6 +42,12 @@ export declare function validatePatchIntegrity(patchesDir: string, engineDir: st
|
|
|
42
42
|
/**
|
|
43
43
|
* Stamps multiple patches with a new source version in a single
|
|
44
44
|
* manifest read-modify-write cycle.
|
|
45
|
+
*
|
|
46
|
+
* Acquires the shared patch-directory lock for the read-modify-write, so a
|
|
47
|
+
* concurrent export/reorder/metadata update cannot interleave with the stamp.
|
|
48
|
+
* The lock is not reentrant — callers must NOT invoke this while already
|
|
49
|
+
* holding {@link withPatchDirectoryLock} on the same patches directory.
|
|
50
|
+
*
|
|
45
51
|
* @param patchesDir - Path to the patches directory
|
|
46
52
|
* @param filenames - Patch filenames to update
|
|
47
53
|
* @param newVersion - Version string to set (e.g. "140.9.0esr")
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Query helpers: finding patches by file, integrity checks, version compat, stamping.
|
|
4
4
|
*/
|
|
5
5
|
import { readText } from '../utils/fs.js';
|
|
6
|
-
import {
|
|
6
|
+
import { listTrackedInHead } from './git-file-ops.js';
|
|
7
7
|
import { discoverPatches, getAllTargetFilesFromPatch } from './patch-files.js';
|
|
8
|
+
import { withPatchDirectoryLock } from './patch-lock.js';
|
|
8
9
|
import { loadPatchesManifest, mutatePatchRowsInManifest } from './patch-manifest-io.js';
|
|
9
10
|
import { isNewFileInPatch } from './patch-parse.js';
|
|
10
11
|
/**
|
|
@@ -78,6 +79,12 @@ export async function findPatchesAffectingFile(patchesDir, filePath) {
|
|
|
78
79
|
export async function validatePatchIntegrity(patchesDir, engineDir) {
|
|
79
80
|
const issues = [];
|
|
80
81
|
const patches = await discoverPatches(patchesDir);
|
|
82
|
+
// Collect every modification target first, then resolve HEAD existence in
|
|
83
|
+
// ONE batched ls-tree pass (chunked for ARG_MAX). The per-file
|
|
84
|
+
// fileExistsInHead fan-out spawned one git process per (patch × target) on
|
|
85
|
+
// every import — a 56-file branding patch alone cost ~56 spawns before a
|
|
86
|
+
// single patch was applied.
|
|
87
|
+
const modificationTargets = [];
|
|
81
88
|
for (const patch of patches) {
|
|
82
89
|
// Check all files in the patch (supports multi-file patches)
|
|
83
90
|
const patchContent = await readText(patch.path);
|
|
@@ -86,14 +93,17 @@ export async function validatePatchIntegrity(patchesDir, engineDir) {
|
|
|
86
93
|
// Skip new-file sections — they don't need to exist in HEAD
|
|
87
94
|
if (isNewFileInPatch(patchContent, targetFile))
|
|
88
95
|
continue;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
modificationTargets.push({ filename: patch.filename, targetFile });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const tracked = await listTrackedInHead(engineDir, modificationTargets.map((t) => t.targetFile));
|
|
100
|
+
for (const { filename, targetFile } of modificationTargets) {
|
|
101
|
+
if (!tracked.has(targetFile)) {
|
|
102
|
+
issues.push({
|
|
103
|
+
filename,
|
|
104
|
+
message: `Modification patch for file that doesn't exist in source. Re-export with: fireforge export ${targetFile}`,
|
|
105
|
+
targetFile,
|
|
106
|
+
});
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
return issues;
|
|
@@ -101,12 +111,18 @@ export async function validatePatchIntegrity(patchesDir, engineDir) {
|
|
|
101
111
|
/**
|
|
102
112
|
* Stamps multiple patches with a new source version in a single
|
|
103
113
|
* manifest read-modify-write cycle.
|
|
114
|
+
*
|
|
115
|
+
* Acquires the shared patch-directory lock for the read-modify-write, so a
|
|
116
|
+
* concurrent export/reorder/metadata update cannot interleave with the stamp.
|
|
117
|
+
* The lock is not reentrant — callers must NOT invoke this while already
|
|
118
|
+
* holding {@link withPatchDirectoryLock} on the same patches directory.
|
|
119
|
+
*
|
|
104
120
|
* @param patchesDir - Path to the patches directory
|
|
105
121
|
* @param filenames - Patch filenames to update
|
|
106
122
|
* @param newVersion - Version string to set (e.g. "140.9.0esr")
|
|
107
123
|
*/
|
|
108
124
|
export async function stampPatchVersions(patchesDir, filenames, newVersion, newProduct) {
|
|
109
|
-
await mutatePatchRowsInManifest(patchesDir, filenames, (patch, rawPatch) => {
|
|
125
|
+
await withPatchDirectoryLock(patchesDir, () => mutatePatchRowsInManifest(patchesDir, filenames, (patch, rawPatch) => {
|
|
110
126
|
if (patch.sourceEsrVersion !== newVersion ||
|
|
111
127
|
rawPatch['sourceVersion'] !== newVersion ||
|
|
112
128
|
(newProduct !== undefined && rawPatch['sourceProduct'] !== newProduct)) {
|
|
@@ -119,6 +135,5 @@ export async function stampPatchVersions(patchesDir, filenames, newVersion, newP
|
|
|
119
135
|
};
|
|
120
136
|
}
|
|
121
137
|
return null;
|
|
122
|
-
});
|
|
138
|
+
}));
|
|
123
139
|
}
|
|
124
|
-
//# sourceMappingURL=patch-manifest-query.js.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* is an implementation detail.
|
|
6
6
|
*/
|
|
7
7
|
export { rebuildPatchesManifest, validatePatchesManifestConsistency, } from './patch-manifest-consistency.js';
|
|
8
|
-
export { addPatchToManifest, loadPatchesManifest, mutatePatchRowsInManifest, PATCHES_MANIFEST, type PatchManifestRowMutation, type PatchManifestRowMutationResult, type PatchRenameEntry, removePatchFileAndManifest, renumberPatchesInManifest, rewriteStagedDependencyOwners, savePatchesManifest, } from './patch-manifest-io.js';
|
|
8
|
+
export { addPatchToManifest, loadPatchesManifest, loadPatchesManifestForWrite, mutatePatchRowsInManifest, PATCHES_MANIFEST, type PatchManifestRowMutation, type PatchManifestRowMutationResult, type PatchRenameEntry, removePatchFileAndManifest, renumberPatchesInManifest, rewriteStagedDependencyOwners, savePatchesManifest, } from './patch-manifest-io.js';
|
|
9
9
|
export { checkVersionCompatibility, findPatchesAffectingFile, getClaimedFiles, stampPatchVersions, validatePatchIntegrity, } from './patch-manifest-query.js';
|
|
10
10
|
export { resolvePatchIdentifier } from './patch-manifest-resolve.js';
|
|
11
11
|
export { validatePatchesManifest } from './patch-manifest-validate.js';
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
* is an implementation detail.
|
|
7
7
|
*/
|
|
8
8
|
export { rebuildPatchesManifest, validatePatchesManifestConsistency, } from './patch-manifest-consistency.js';
|
|
9
|
-
export { addPatchToManifest, loadPatchesManifest, mutatePatchRowsInManifest, PATCHES_MANIFEST, removePatchFileAndManifest, renumberPatchesInManifest, rewriteStagedDependencyOwners, savePatchesManifest, } from './patch-manifest-io.js';
|
|
9
|
+
export { addPatchToManifest, loadPatchesManifest, loadPatchesManifestForWrite, mutatePatchRowsInManifest, PATCHES_MANIFEST, removePatchFileAndManifest, renumberPatchesInManifest, rewriteStagedDependencyOwners, savePatchesManifest, } from './patch-manifest-io.js';
|
|
10
10
|
export { checkVersionCompatibility, findPatchesAffectingFile, getClaimedFiles, stampPatchVersions, validatePatchIntegrity, } from './patch-manifest-query.js';
|
|
11
11
|
export { resolvePatchIdentifier } from './patch-manifest-resolve.js';
|
|
12
12
|
export { validatePatchesManifest } from './patch-manifest-validate.js';
|
|
13
|
-
//# sourceMappingURL=patch-manifest.js.map
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pure parsing functions for extracting information from patch files.
|
|
3
3
|
* All functions are synchronous and operate on string content.
|
|
4
|
+
*
|
|
5
|
+
* This module is the ONE unified-diff walker in the codebase. Before
|
|
6
|
+
* {@link parseDiffSections} existed, six hand-rolled `diff --git` walkers
|
|
7
|
+
* lived across patch-parse, patch-lint-diff, patch-registration-refs, and
|
|
8
|
+
* patch-transform — with divergent CRLF handling (a CRLF-saved patch file
|
|
9
|
+
* silently failed target-file matching and `\ No newline` detection on
|
|
10
|
+
* Windows), no quoted-path support, and greedy path captures that
|
|
11
|
+
* mis-split any path containing ` b/`. New diff-shaped parsing must build
|
|
12
|
+
* on {@link parseDiffSections} rather than re-walking lines.
|
|
4
13
|
*/
|
|
5
14
|
/**
|
|
6
15
|
* Extracts the order number from a patch filename.
|
|
@@ -9,6 +18,56 @@
|
|
|
9
18
|
* @returns Order number, or Infinity if no prefix
|
|
10
19
|
*/
|
|
11
20
|
export declare function extractOrder(filename: string): number;
|
|
21
|
+
/**
|
|
22
|
+
* A parsed `diff --git` header: both sides' paths, unquoted and with any
|
|
23
|
+
* CRLF residue stripped.
|
|
24
|
+
*/
|
|
25
|
+
export interface DiffGitHeader {
|
|
26
|
+
/** Old-side (`a/`) path. */
|
|
27
|
+
sourcePath: string;
|
|
28
|
+
/** New-side (`b/`) path — the file the patch produces. */
|
|
29
|
+
targetPath: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parses a `diff --git` line into its two paths.
|
|
33
|
+
*
|
|
34
|
+
* Handles the quoted form git emits for paths with special characters
|
|
35
|
+
* (`diff --git "a/x y" "b/x y"`), and disambiguates the unquoted form for
|
|
36
|
+
* paths that themselves contain ` b/`: for the overwhelmingly common
|
|
37
|
+
* non-rename case the two paths are identical, so a symmetric split
|
|
38
|
+
* (`a/<p> b/<p>`) is tried first — the previous greedy regex
|
|
39
|
+
* (`a\/.+ b\/(.+)$`) split such lines at the LAST ` b/` and returned a
|
|
40
|
+
* truncated path. Falls back to a non-greedy split for renames.
|
|
41
|
+
*
|
|
42
|
+
* @returns null when the line is not a diff --git header.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseDiffGitHeader(line: string): DiffGitHeader | null;
|
|
45
|
+
/**
|
|
46
|
+
* One `diff --git` section of a unified diff, fully structured.
|
|
47
|
+
*/
|
|
48
|
+
export interface DiffSection {
|
|
49
|
+
/** New-side (`b/`) path — the file this section produces. */
|
|
50
|
+
targetPath: string;
|
|
51
|
+
/** Old-side (`a/`) path. */
|
|
52
|
+
sourcePath: string;
|
|
53
|
+
/** True when the section carries a `new file mode` marker. */
|
|
54
|
+
isNewFile: boolean;
|
|
55
|
+
/** True when the section carries a `deleted file mode` marker. */
|
|
56
|
+
isDeletedFile: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* True for binary sections (`GIT binary patch` or `Binary files … differ`).
|
|
59
|
+
* Binary sections have no parseable hunks; text-oriented consumers must
|
|
60
|
+
* refuse them rather than treat base85 lines starting with `+` as content.
|
|
61
|
+
*/
|
|
62
|
+
isBinary: boolean;
|
|
63
|
+
/** Parsed hunks, in file order. Empty for binary or metadata-only sections. */
|
|
64
|
+
hunks: ParsedHunk[];
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parses a unified diff into structured per-file sections — the single
|
|
68
|
+
* shared walker every diff consumer builds on.
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseDiffSections(diffContent: string): DiffSection[];
|
|
12
71
|
/**
|
|
13
72
|
* Checks whether a specific file is a new-file addition within a patch.
|
|
14
73
|
* For multi-file patches, only inspects the section belonging to targetFile.
|