@hominis/fireforge 0.35.0 → 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 +29 -0
- package/README.md +34 -9
- package/dist/bin/fireforge.js +21 -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 +4 -3
- package/dist/src/commands/config.js +30 -10
- package/dist/src/commands/discard.js +18 -3
- 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 +28 -13
- 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 +4 -4
- 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 +85 -86
- 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 +2 -2
- 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 +60 -4
- package/dist/src/core/firefox-download.js +0 -1
- package/dist/src/core/firefox-extract.js +75 -16
- 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 +63 -6
- package/dist/src/core/license-headers.js +0 -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 +0 -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 +101 -18
- 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 +47 -34
- 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 +30 -5
- package/dist/src/core/patch-manifest-query.js +18 -10
- 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 +21 -13
- package/dist/src/core/test-path-scope.js +43 -28
- 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 +31 -10
- package/dist/src/core/toolchain-preflight.js +97 -36
- package/dist/src/core/typecheck-shim.js +13 -1
- 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 +0 -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 +13 -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
|
@@ -14,7 +14,7 @@ import { exec } from '../utils/process.js';
|
|
|
14
14
|
import { applyPatchIdempotent, reversePatch } from './git.js';
|
|
15
15
|
import { getFileContentFromHead } from './git-file-ops.js';
|
|
16
16
|
import { discoverPatches } from './patch-files.js';
|
|
17
|
-
import { findPatchesAffectingFile } from './patch-manifest.js';
|
|
17
|
+
import { findPatchesAffectingFile, loadPatchesManifest } from './patch-manifest.js';
|
|
18
18
|
import { extractAffectedFiles, extractConflictingFiles, isNewFileInPatch } from './patch-parse.js';
|
|
19
19
|
import { applyPatchToContent, extractNewFileContent } from './patch-transform.js';
|
|
20
20
|
// Re-export from split modules so existing import sites continue working
|
|
@@ -27,16 +27,23 @@ export { applyPatchToContent, extractNewFileContent } from './patch-transform.js
|
|
|
27
27
|
* Applies a single patch.
|
|
28
28
|
* @param patch - Patch info
|
|
29
29
|
* @param engineDir - Path to the engine directory
|
|
30
|
+
* @param protectedFiles - Files touched by patches already applied in the
|
|
31
|
+
* current run; the idempotent-recovery reset must not wipe them (see
|
|
32
|
+
* applyPatchIdempotent). Overlapping queues (`--allow-overlap`) share
|
|
33
|
+
* files between patches, and a later patch's recovery used to reset the
|
|
34
|
+
* shared file to HEAD — silently discarding the earlier patch's changes.
|
|
30
35
|
* @returns Patch result
|
|
31
36
|
*/
|
|
32
|
-
async function applySinglePatch(patch, engineDir) {
|
|
37
|
+
async function applySinglePatch(patch, engineDir, protectedFiles) {
|
|
33
38
|
let patchContent = '';
|
|
34
39
|
let affectedFiles = [];
|
|
35
40
|
try {
|
|
36
41
|
patchContent = await readText(patch.path);
|
|
37
42
|
affectedFiles = extractAffectedFiles(patchContent);
|
|
38
43
|
await validatePatchTargets(patch, affectedFiles, engineDir);
|
|
39
|
-
await applyPatchIdempotent(patch.path, engineDir
|
|
44
|
+
await applyPatchIdempotent(patch.path, engineDir, {
|
|
45
|
+
...(protectedFiles ? { protectedFiles } : {}),
|
|
46
|
+
});
|
|
40
47
|
return { patch, success: true };
|
|
41
48
|
}
|
|
42
49
|
catch (error) {
|
|
@@ -48,21 +55,39 @@ async function applySinglePatch(patch, engineDir) {
|
|
|
48
55
|
let resolvedNewFiles = false;
|
|
49
56
|
// Save original content for files we might overwrite, so we can restore on failure
|
|
50
57
|
const savedContents = new Map();
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
try {
|
|
59
|
+
for (const file of affectedFiles) {
|
|
60
|
+
if (isNewFileInPatch(patchContent, file)) {
|
|
61
|
+
const targetPath = join(engineDir, file);
|
|
62
|
+
if (await pathExists(targetPath)) {
|
|
63
|
+
savedContents.set(file, await readText(targetPath));
|
|
64
|
+
const content = await extractNewFileContent(patch.path, file);
|
|
65
|
+
await writeText(targetPath, content);
|
|
66
|
+
resolvedNewFiles = true;
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
70
|
}
|
|
71
|
+
catch (extractError) {
|
|
72
|
+
// extractNewFileContent threw for a LATER target (e.g. a binary
|
|
73
|
+
// section) after earlier targets were already overwritten — restore
|
|
74
|
+
// them before reporting failure, instead of letting the exception
|
|
75
|
+
// skip the restore loop entirely and crash the whole import.
|
|
76
|
+
for (const [file, originalContent] of savedContents) {
|
|
77
|
+
await writeText(join(engineDir, file), originalContent);
|
|
78
|
+
}
|
|
79
|
+
return { patch, success: false, error: toError(extractError).message };
|
|
80
|
+
}
|
|
62
81
|
if (resolvedNewFiles) {
|
|
63
82
|
try {
|
|
64
|
-
await applyPatchIdempotent(patch.path, engineDir
|
|
65
|
-
|
|
83
|
+
await applyPatchIdempotent(patch.path, engineDir, {
|
|
84
|
+
...(protectedFiles ? { protectedFiles } : {}),
|
|
85
|
+
});
|
|
86
|
+
// Keep the originals: rollbackPatches needs them if a LATER patch
|
|
87
|
+
// fails, since reverse-applying this new-file patch deletes the
|
|
88
|
+
// target and would otherwise permanently discard the pre-existing
|
|
89
|
+
// content (recoverable from git only if it was tracked at HEAD).
|
|
90
|
+
return { patch, success: true, autoResolved: true, autoResolvedOriginals: savedContents };
|
|
66
91
|
}
|
|
67
92
|
catch (retryError) {
|
|
68
93
|
verbose(`Auto-resolved new-file retry failed for ${patch.filename}: ${toError(retryError).message}`);
|
|
@@ -76,7 +101,10 @@ async function applySinglePatch(patch, engineDir) {
|
|
|
76
101
|
let errorMessage = applyError.message;
|
|
77
102
|
try {
|
|
78
103
|
// Use --reject to apply what we can and create .rej files for what we can't
|
|
79
|
-
await applyPatchIdempotent(patch.path, engineDir, {
|
|
104
|
+
await applyPatchIdempotent(patch.path, engineDir, {
|
|
105
|
+
reject: true,
|
|
106
|
+
...(protectedFiles ? { protectedFiles } : {}),
|
|
107
|
+
});
|
|
80
108
|
// If this somehow succeeds with --reject but failed without, it still shouldn't
|
|
81
109
|
// happen because applyPatch first runs --check which would fail.
|
|
82
110
|
// But if it did succeed, we should still return failure because manual fix is needed
|
|
@@ -105,6 +133,19 @@ async function rollbackPatches(results, engineDir) {
|
|
|
105
133
|
catch (rollbackError) {
|
|
106
134
|
verbose(`Failed to roll back ${result.patch.filename}: ${toError(rollbackError).message}`);
|
|
107
135
|
}
|
|
136
|
+
// Reversing an auto-resolved new-file patch deletes the target; put
|
|
137
|
+
// back the pre-existing content the auto-resolve overwrote.
|
|
138
|
+
if (result.autoResolvedOriginals) {
|
|
139
|
+
for (const [file, originalContent] of result.autoResolvedOriginals) {
|
|
140
|
+
try {
|
|
141
|
+
await writeText(join(engineDir, file), originalContent);
|
|
142
|
+
verbose(`Restored pre-existing content of ${file} after rollback`);
|
|
143
|
+
}
|
|
144
|
+
catch (restoreError) {
|
|
145
|
+
verbose(`Could not restore ${file}: ${toError(restoreError).message}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
108
149
|
}
|
|
109
150
|
}
|
|
110
151
|
/**
|
|
@@ -117,9 +158,15 @@ async function rollbackPatches(results, engineDir) {
|
|
|
117
158
|
export async function applyPatches(patchesDir, engineDir) {
|
|
118
159
|
const patches = await discoverPatches(patchesDir);
|
|
119
160
|
const results = [];
|
|
161
|
+
const appliedFiles = new Set();
|
|
120
162
|
for (const patch of patches) {
|
|
121
|
-
const result = await applySinglePatch(patch, engineDir);
|
|
163
|
+
const result = await applySinglePatch(patch, engineDir, appliedFiles);
|
|
122
164
|
results.push(result);
|
|
165
|
+
if (result.success) {
|
|
166
|
+
for (const file of extractAffectedFiles(await readText(patch.path))) {
|
|
167
|
+
appliedFiles.add(file);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
123
170
|
// Stop on first failure and roll back all previously applied patches
|
|
124
171
|
if (!result.success) {
|
|
125
172
|
const succeeded = results.filter((r) => r.success);
|
|
@@ -237,7 +284,7 @@ async function resolvePatchWriteDestination(targetPath) {
|
|
|
237
284
|
* short-circuit was kept behind the numeric gate so the match stays
|
|
238
285
|
* single-meaning per identifier.
|
|
239
286
|
*/
|
|
240
|
-
function matchesUntilFilename(patchFilename, needle) {
|
|
287
|
+
export function matchesUntilFilename(patchFilename, needle) {
|
|
241
288
|
const isNumeric = /^\d+$/.test(needle);
|
|
242
289
|
if (isNumeric) {
|
|
243
290
|
const order = parseInt(needle, 10);
|
|
@@ -298,6 +345,7 @@ export async function applyPatchesWithContinue(patchesDir, engineDir, optionsOrC
|
|
|
298
345
|
const succeeded = [];
|
|
299
346
|
const failed = [];
|
|
300
347
|
const skipped = [];
|
|
348
|
+
const appliedFiles = new Set();
|
|
301
349
|
for (let i = 0; i < patches.length; i++) {
|
|
302
350
|
const patch = patches[i];
|
|
303
351
|
if (!patch)
|
|
@@ -309,9 +357,12 @@ export async function applyPatchesWithContinue(patchesDir, engineDir, optionsOrC
|
|
|
309
357
|
skipped.push(patch);
|
|
310
358
|
continue;
|
|
311
359
|
}
|
|
312
|
-
const result = await applySinglePatch(patch, engineDir);
|
|
360
|
+
const result = await applySinglePatch(patch, engineDir, appliedFiles);
|
|
313
361
|
if (result.success) {
|
|
314
362
|
succeeded.push(result);
|
|
363
|
+
for (const file of extractAffectedFiles(await readText(patch.path))) {
|
|
364
|
+
appliedFiles.add(file);
|
|
365
|
+
}
|
|
315
366
|
}
|
|
316
367
|
else {
|
|
317
368
|
// Try to extract conflicting files from error message
|
|
@@ -362,4 +413,36 @@ export async function computePatchedContent(patchesDir, engineDir, filePath) {
|
|
|
362
413
|
}
|
|
363
414
|
return content;
|
|
364
415
|
}
|
|
365
|
-
|
|
416
|
+
/**
|
|
417
|
+
* Builds a batched variant of {@link computePatchedContent} that loads the
|
|
418
|
+
* manifest and discovers patch files ONCE for many lookups. The per-call
|
|
419
|
+
* function re-runs `loadPatchesManifest` + `discoverPatches` for every
|
|
420
|
+
* file — O(dirtyFiles × patches) redundant IO when classifying a broad
|
|
421
|
+
* engine edit session during `import`.
|
|
422
|
+
*/
|
|
423
|
+
export async function createPatchedContentComputer(patchesDir, engineDir) {
|
|
424
|
+
const manifest = await loadPatchesManifest(patchesDir);
|
|
425
|
+
const patches = await discoverPatches(patchesDir);
|
|
426
|
+
const patchByFilename = new Map(patches.map((p) => [p.filename, p]));
|
|
427
|
+
const affectingByFile = new Map();
|
|
428
|
+
for (const metadata of manifest?.patches ?? []) {
|
|
429
|
+
const patch = patchByFilename.get(metadata.filename);
|
|
430
|
+
if (!patch)
|
|
431
|
+
continue;
|
|
432
|
+
for (const file of metadata.filesAffected) {
|
|
433
|
+
const list = affectingByFile.get(file) ?? [];
|
|
434
|
+
list.push(patch);
|
|
435
|
+
affectingByFile.set(file, list);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
for (const list of affectingByFile.values()) {
|
|
439
|
+
list.sort((a, b) => a.order - b.order);
|
|
440
|
+
}
|
|
441
|
+
return async (filePath) => {
|
|
442
|
+
let content = await getFileContentFromHead(engineDir, filePath);
|
|
443
|
+
for (const patch of affectingByFile.get(filePath) ?? []) {
|
|
444
|
+
content = await applyPatchToContent(content, patch.path, filePath);
|
|
445
|
+
}
|
|
446
|
+
return content;
|
|
447
|
+
};
|
|
448
|
+
}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Normalizes generated patch files before they are written to disk.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Currently the identity function, kept as a narrow chokepoint for future
|
|
5
|
+
* artifact-level fixes so every export path (`commitExportedPatch`,
|
|
6
|
+
* `commitPlacementExport`, `updatePatch`, `patch split`) funnels through
|
|
7
|
+
* one place.
|
|
8
|
+
*
|
|
9
|
+
* History: this used to strip marker lines whose payload was pure
|
|
10
|
+
* whitespace (`/^[ +-]\s+$/` → bare marker) to appease repository
|
|
11
|
+
* trailing-whitespace checks. That corrupted real content — Firefox
|
|
12
|
+
* sources contain whitespace-only lines, so a ` `/`-` line whose payload
|
|
13
|
+
* was e.g. two spaces no longer matched the pristine tree (the freshly
|
|
14
|
+
* exported patch failed `git apply --check`), and a `+` line silently
|
|
15
|
+
* changed what the patch produces, making re-import diverge from the
|
|
16
|
+
* engine state it was exported from (2026-07-05 review, finding M2).
|
|
17
|
+
* The whitespace check itself excludes `patches/*.patch`
|
|
18
|
+
* (scripts/check-worktree-whitespace.mjs), so the trimming had no
|
|
19
|
+
* remaining justification. Patch bodies are now written byte-for-byte as
|
|
20
|
+
* git produced them — including the single-space rendering of blank
|
|
21
|
+
* context lines, which `re-export.integration.test.ts` pins.
|
|
9
22
|
*/
|
|
10
23
|
export declare function normalizePatchArtifact(content: string): string;
|
|
@@ -2,21 +2,25 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Normalizes generated patch files before they are written to disk.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Currently the identity function, kept as a narrow chokepoint for future
|
|
6
|
+
* artifact-level fixes so every export path (`commitExportedPatch`,
|
|
7
|
+
* `commitPlacementExport`, `updatePatch`, `patch split`) funnels through
|
|
8
|
+
* one place.
|
|
9
|
+
*
|
|
10
|
+
* History: this used to strip marker lines whose payload was pure
|
|
11
|
+
* whitespace (`/^[ +-]\s+$/` → bare marker) to appease repository
|
|
12
|
+
* trailing-whitespace checks. That corrupted real content — Firefox
|
|
13
|
+
* sources contain whitespace-only lines, so a ` `/`-` line whose payload
|
|
14
|
+
* was e.g. two spaces no longer matched the pristine tree (the freshly
|
|
15
|
+
* exported patch failed `git apply --check`), and a `+` line silently
|
|
16
|
+
* changed what the patch produces, making re-import diverge from the
|
|
17
|
+
* engine state it was exported from (2026-07-05 review, finding M2).
|
|
18
|
+
* The whitespace check itself excludes `patches/*.patch`
|
|
19
|
+
* (scripts/check-worktree-whitespace.mjs), so the trimming had no
|
|
20
|
+
* remaining justification. Patch bodies are now written byte-for-byte as
|
|
21
|
+
* git produced them — including the single-space rendering of blank
|
|
22
|
+
* context lines, which `re-export.integration.test.ts` pins.
|
|
10
23
|
*/
|
|
11
24
|
export function normalizePatchArtifact(content) {
|
|
12
|
-
return content
|
|
13
|
-
.split('\n')
|
|
14
|
-
.map((line) => {
|
|
15
|
-
if (/^[ +-]\s+$/.test(line)) {
|
|
16
|
-
return line[0] ?? line;
|
|
17
|
-
}
|
|
18
|
-
return line;
|
|
19
|
-
})
|
|
20
|
-
.join('\n');
|
|
25
|
+
return content;
|
|
21
26
|
}
|
|
22
|
-
//# sourceMappingURL=patch-artifact-normalize.js.map
|
|
@@ -5,7 +5,7 @@ import { pathExists, readText, writeText } from '../utils/fs.js';
|
|
|
5
5
|
import { warn } from '../utils/logger.js';
|
|
6
6
|
import { withPatchDirectoryLock } from './patch-apply.js';
|
|
7
7
|
import { normalizePatchArtifact } from './patch-artifact-normalize.js';
|
|
8
|
-
import {
|
|
8
|
+
import { loadPatchesManifestForWrite, mutatePatchRowsInManifest } from './patch-manifest.js';
|
|
9
9
|
import { buildProjectedManifest, enforcePatchPolicy } from './patch-policy.js';
|
|
10
10
|
/**
|
|
11
11
|
* Updates a patch file body and its manifest row under the same patch
|
|
@@ -14,7 +14,7 @@ import { buildProjectedManifest, enforcePatchPolicy } from './patch-policy.js';
|
|
|
14
14
|
*/
|
|
15
15
|
export async function updatePatchAndMetadata(patchesDir, filename, newContent, updates, onCommitted, policyGate) {
|
|
16
16
|
await withPatchDirectoryLock(patchesDir, async () => {
|
|
17
|
-
const manifest = await
|
|
17
|
+
const manifest = await loadPatchesManifestForWrite(patchesDir);
|
|
18
18
|
if (!manifest) {
|
|
19
19
|
throw new Error('Cannot update patch metadata: patches.json is missing.');
|
|
20
20
|
}
|
|
@@ -65,4 +65,3 @@ export async function updatePatchAndMetadata(patchesDir, filename, newContent, u
|
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
|
-
//# sourceMappingURL=patch-export-update.js.map
|
|
@@ -30,6 +30,8 @@ export declare function sanitizeName(name: string): string;
|
|
|
30
30
|
* double-prefix incident) also collapses. Exported for direct testing.
|
|
31
31
|
*/
|
|
32
32
|
export declare function stripRedundantCategoryPrefix(sanitizedName: string, category: string): string;
|
|
33
|
+
/** Sanitizes a patch name and drops redundant category/full-stem prefixes. */
|
|
34
|
+
export declare function patchNameSlug(name: string, category: string): string;
|
|
33
35
|
/**
|
|
34
36
|
* Generates the next patch filename with category.
|
|
35
37
|
* @param patchesDir - Path to the patches directory
|
|
@@ -99,12 +101,6 @@ export declare function findExistingPatchForFile(patchesDir: string, filePath: s
|
|
|
99
101
|
* @param newContent - New patch content
|
|
100
102
|
*/
|
|
101
103
|
export declare function updatePatch(patchPath: string, newContent: string): Promise<void>;
|
|
102
|
-
/**
|
|
103
|
-
* Deletes a patch file and removes it from the manifest.
|
|
104
|
-
* @param patchesDir - Path to the patches directory
|
|
105
|
-
* @param filename - Patch filename to delete
|
|
106
|
-
*/
|
|
107
|
-
export declare function deletePatch(patchesDir: string, filename: string): Promise<void>;
|
|
108
104
|
/**
|
|
109
105
|
* Fully computed plan for a pending export. Returned from
|
|
110
106
|
* {@link planExport} so that `--dry-run` previews can render the full
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
-
import { unlink } from 'node:fs/promises';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { toError } from '../utils/errors.js';
|
|
5
4
|
import { pathExists, readText, removeFile, writeText } from '../utils/fs.js';
|
|
@@ -8,7 +7,7 @@ import { PATCH_CATEGORIES } from '../utils/validation.js';
|
|
|
8
7
|
import { discoverPatches, withPatchDirectoryLock } from './patch-apply.js';
|
|
9
8
|
import { normalizePatchArtifact } from './patch-artifact-normalize.js';
|
|
10
9
|
import { findAllPatchesForFilesWithDetails, } from './patch-export-coverage.js';
|
|
11
|
-
import { addPatchToManifest,
|
|
10
|
+
import { addPatchToManifest, loadPatchesManifestForWrite, PATCHES_MANIFEST, savePatchesManifest, } from './patch-manifest.js';
|
|
12
11
|
import { allocatePolicyOrder, enforcePatchPolicy } from './patch-policy.js';
|
|
13
12
|
export { findAllPatchesForFiles, findAllPatchesForFilesWithDetails, findSupersededPatches, isPatchFullyCovered, } from './patch-export-coverage.js';
|
|
14
13
|
export { mutatePatchMetadata, updatePatchMetadata, } from './patch-export-metadata.js';
|
|
@@ -46,6 +45,9 @@ export function sanitizeName(name) {
|
|
|
46
45
|
.replace(/^-+|-+$/g, '')
|
|
47
46
|
.slice(0, 50);
|
|
48
47
|
}
|
|
48
|
+
function escapeRegExp(value) {
|
|
49
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
50
|
+
}
|
|
49
51
|
/**
|
|
50
52
|
* Strips a leading `NNN-<category>-` prefix from a sanitized name slug.
|
|
51
53
|
* Operators frequently pass the DESIRED FILENAME stem to `--name`
|
|
@@ -56,15 +58,25 @@ export function sanitizeName(name) {
|
|
|
56
58
|
* double-prefix incident) also collapses. Exported for direct testing.
|
|
57
59
|
*/
|
|
58
60
|
export function stripRedundantCategoryPrefix(sanitizedName, category) {
|
|
59
|
-
const
|
|
61
|
+
const prefixes = [
|
|
62
|
+
new RegExp(`^\\d+-${escapeRegExp(category)}-`),
|
|
63
|
+
new RegExp(`^${escapeRegExp(category)}-`),
|
|
64
|
+
];
|
|
60
65
|
let stripped = sanitizedName;
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
let changed = true;
|
|
67
|
+
while (changed) {
|
|
68
|
+
changed = false;
|
|
69
|
+
for (const prefix of prefixes) {
|
|
70
|
+
if (prefix.test(stripped)) {
|
|
71
|
+
stripped = stripped.replace(prefix, '');
|
|
72
|
+
changed = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
63
75
|
}
|
|
64
76
|
return stripped.length > 0 ? stripped : sanitizedName;
|
|
65
77
|
}
|
|
66
|
-
/** Sanitizes a patch name and drops
|
|
67
|
-
function patchNameSlug(name, category) {
|
|
78
|
+
/** Sanitizes a patch name and drops redundant category/full-stem prefixes. */
|
|
79
|
+
export function patchNameSlug(name, category) {
|
|
68
80
|
return stripRedundantCategoryPrefix(sanitizeName(name), category);
|
|
69
81
|
}
|
|
70
82
|
/**
|
|
@@ -221,45 +233,6 @@ export async function findExistingPatchForFile(patchesDir, filePath) {
|
|
|
221
233
|
export async function updatePatch(patchPath, newContent) {
|
|
222
234
|
await writeText(patchPath, normalizePatchArtifact(newContent));
|
|
223
235
|
}
|
|
224
|
-
/**
|
|
225
|
-
* Deletes a patch file and removes it from the manifest.
|
|
226
|
-
* @param patchesDir - Path to the patches directory
|
|
227
|
-
* @param filename - Patch filename to delete
|
|
228
|
-
*/
|
|
229
|
-
export async function deletePatch(patchesDir, filename) {
|
|
230
|
-
await withPatchDirectoryLock(patchesDir, async () => {
|
|
231
|
-
const patchPath = join(patchesDir, filename);
|
|
232
|
-
const manifest = await loadPatchesManifest(patchesDir);
|
|
233
|
-
const updatedManifest = manifest
|
|
234
|
-
? {
|
|
235
|
-
...manifest,
|
|
236
|
-
patches: manifest.patches.filter((patch) => patch.filename !== filename),
|
|
237
|
-
}
|
|
238
|
-
: null;
|
|
239
|
-
// Update manifest first so interrupted deletions leave an explicit repairable
|
|
240
|
-
// extra patch file rather than silently dropping metadata for an absent file.
|
|
241
|
-
if (updatedManifest) {
|
|
242
|
-
await savePatchesManifest(patchesDir, updatedManifest);
|
|
243
|
-
}
|
|
244
|
-
if (!(await pathExists(patchPath))) {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
try {
|
|
248
|
-
await unlink(patchPath);
|
|
249
|
-
}
|
|
250
|
-
catch (error) {
|
|
251
|
-
if (manifest) {
|
|
252
|
-
try {
|
|
253
|
-
await savePatchesManifest(patchesDir, manifest);
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
warn(`Failed to restore manifest after patch deletion error for "${filename}": ${toError(error).message}`);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
throw error;
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
236
|
/**
|
|
264
237
|
* Internal planning helper. Does NOT take the patch directory lock — the
|
|
265
238
|
* caller must already hold it — because the two public entry points
|
|
@@ -269,7 +242,11 @@ export async function deletePatch(patchesDir, filename) {
|
|
|
269
242
|
* instead of by parallel implementations that can drift.
|
|
270
243
|
*/
|
|
271
244
|
async function computeExportPlanUnderLock(input) {
|
|
272
|
-
|
|
245
|
+
// ForWrite: a corrupt manifest read as null here would produce a
|
|
246
|
+
// manifestAfter containing ONLY the new patch — committing that plan
|
|
247
|
+
// wipes the queue metadata, and the rollback path would then delete
|
|
248
|
+
// patches.json entirely because manifestBefore looked absent.
|
|
249
|
+
const manifestBefore = await loadPatchesManifestForWrite(input.patchesDir);
|
|
273
250
|
const policyOrder = input.config !== undefined
|
|
274
251
|
? allocatePolicyOrder(input.config, manifestBefore?.patches ?? [], input.category)
|
|
275
252
|
: null;
|
|
@@ -341,4 +318,3 @@ export async function planExport(input) {
|
|
|
341
318
|
};
|
|
342
319
|
});
|
|
343
320
|
}
|
|
344
|
-
//# sourceMappingURL=patch-export.js.map
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* cross-patch lint body (in `patch-lint-cross.ts`) can both depend on
|
|
7
7
|
* the same diff walkers without inducing a circular import. Callers
|
|
8
8
|
* should keep importing these through `patch-lint.ts` — this file is
|
|
9
|
-
* an implementation detail.
|
|
9
|
+
* an implementation detail. The actual line-walking lives in
|
|
10
|
+
* `parseDiffSections` (patch-parse.ts), the codebase's single diff walker.
|
|
10
11
|
*/
|
|
11
12
|
/**
|
|
12
13
|
* Extracts new-file paths from a unified diff by scanning for `new file mode` markers.
|
|
@@ -7,23 +7,18 @@
|
|
|
7
7
|
* cross-patch lint body (in `patch-lint-cross.ts`) can both depend on
|
|
8
8
|
* the same diff walkers without inducing a circular import. Callers
|
|
9
9
|
* should keep importing these through `patch-lint.ts` — this file is
|
|
10
|
-
* an implementation detail.
|
|
10
|
+
* an implementation detail. The actual line-walking lives in
|
|
11
|
+
* `parseDiffSections` (patch-parse.ts), the codebase's single diff walker.
|
|
11
12
|
*/
|
|
13
|
+
import { parseDiffSections } from './patch-parse.js';
|
|
12
14
|
/**
|
|
13
15
|
* Extracts new-file paths from a unified diff by scanning for `new file mode` markers.
|
|
14
16
|
*/
|
|
15
17
|
export function detectNewFilesInDiff(diffContent) {
|
|
16
18
|
const newFiles = new Set();
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (line.startsWith('diff --git')) {
|
|
21
|
-
const match = /^diff --git a\/.+ b\/(.+)$/.exec(line);
|
|
22
|
-
currentFile = match?.[1] ?? null;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
if (line.startsWith('new file mode') && currentFile) {
|
|
26
|
-
newFiles.add(currentFile);
|
|
19
|
+
for (const section of parseDiffSections(diffContent)) {
|
|
20
|
+
if (section.isNewFile) {
|
|
21
|
+
newFiles.add(section.targetPath);
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
24
|
return newFiles;
|
|
@@ -34,27 +29,18 @@ export function detectNewFilesInDiff(diffContent) {
|
|
|
34
29
|
*/
|
|
35
30
|
export function extractAddedLinesPerFile(diffContent) {
|
|
36
31
|
const result = new Map();
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
inHunk = true;
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (inHunk && currentFile && line.startsWith('+') && !line.startsWith('+++')) {
|
|
52
|
-
let arr = result.get(currentFile);
|
|
53
|
-
if (!arr) {
|
|
54
|
-
arr = [];
|
|
55
|
-
result.set(currentFile, arr);
|
|
32
|
+
for (const section of parseDiffSections(diffContent)) {
|
|
33
|
+
for (const hunk of section.hunks) {
|
|
34
|
+
for (const line of hunk.lines) {
|
|
35
|
+
if (!line.startsWith('+'))
|
|
36
|
+
continue;
|
|
37
|
+
let arr = result.get(section.targetPath);
|
|
38
|
+
if (!arr) {
|
|
39
|
+
arr = [];
|
|
40
|
+
result.set(section.targetPath, arr);
|
|
41
|
+
}
|
|
42
|
+
arr.push(line.slice(1));
|
|
56
43
|
}
|
|
57
|
-
arr.push(line.slice(1));
|
|
58
44
|
}
|
|
59
45
|
}
|
|
60
46
|
return result;
|
|
@@ -81,4 +67,3 @@ export function buildModifiedFileAdditionsFromDiff(diff) {
|
|
|
81
67
|
}
|
|
82
68
|
return result;
|
|
83
69
|
}
|
|
84
|
-
//# sourceMappingURL=patch-lint-diff.js.map
|
|
@@ -67,4 +67,3 @@ export function resolvePatchOwnedSysMjs(currentNewFiles, patchQueueCtx) {
|
|
|
67
67
|
export function resolvePatchOwnedChromeScripts(currentNewFiles, patchQueueCtx) {
|
|
68
68
|
return resolveOwned(currentNewFiles, patchQueueCtx, (file) => file.endsWith('.js') && !file.endsWith('.sys.mjs'));
|
|
69
69
|
}
|
|
70
|
-
//# sourceMappingURL=patch-lint-ownership.js.map
|
|
@@ -5,4 +5,3 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export { buildPatchQueueContext, collectForwardImportEdges, collectNewFileCreatorsByPath, extractImportSpecifiers, extractImportSpecifiersWithLines, findForwardImportIgnoreLines, FORWARD_IMPORT_IGNORE_MARKER, isForwardImportableFile, lintPatchQueue, lintPatchQueueDuplicateCreations, lintPatchQueueForwardImports, } from './patch-lint-cross.js';
|
|
7
7
|
export { buildModifiedFileAdditionsFromDiff, detectNewFilesInDiff } from './patch-lint-diff.js';
|
|
8
|
-
//# sourceMappingURL=patch-lint-reexports.js.map
|