@deepseek-ai/dsh-fs-patch 0.2.2-rc.1 → 0.2.2-rc.2
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/lib/types/apply.d.ts.map +1 -0
- package/lib/types/apply.js.map +1 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/parse.d.ts.map +1 -0
- package/lib/types/parse.js.map +1 -0
- package/lib/types/types.d.ts.map +1 -0
- package/lib/types/types.js.map +1 -0
- package/package.json +5 -2
- package/src/apply.ts +116 -0
- package/src/index.ts +5 -0
- package/src/parse.ts +175 -0
- package/src/types.ts +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/apply.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAkD7D;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,SAAS,EAAE,GAAG,gBAAgB,CAmDxF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAEpF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/parse.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAa,cAAc,EAAE,MAAM,YAAY,CAAA;AAa3D,yFAAyF;AACzF,qBAAa,eAAgB,SAAQ,KAAK;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAA3C,UAAU,EAAE,MAAM,EAAW,MAAM,EAAE,MAAM;CAIjE;AA4GD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,EAAE,CAmC1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAEvF,6BAA6B;AAC7B,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,mDAAmD;IACnD,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,2EAA2E;AAC3E,MAAM,MAAM,cAAc,GACtB;IACA,IAAI,EAAE,KAAK,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAA;CAChB,GACC;IACA,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;CACnB,GACC;IACA,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,SAAS,EAAE,CAAA;CACnB,CAAA;AAEH,0FAA0F;AAC1F,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,cAAc,EAAE,MAAM,CAAA;IACtB,+CAA+C;IAC/C,KAAK,EAAE,SAAS,GAAG,UAAU,CAAA;IAC7B,6FAA6F;IAC7F,WAAW,EAAE,MAAM,CAAA;IACnB,oGAAoG;IACpG,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,wFAAwF;AACxF,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,uFAAuF"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-fs-patch",
|
|
3
3
|
"description": "Pure Codex-style patch parser and LF text updater with structured match failures",
|
|
4
|
-
"version": "0.2.2-rc.
|
|
4
|
+
"version": "0.2.2-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"lib/index.js",
|
|
26
|
-
"lib/types/**/*.d.ts"
|
|
26
|
+
"lib/types/**/*.d.ts",
|
|
27
|
+
"lib/types/**/*.d.ts.map",
|
|
28
|
+
"lib/**/*.js.map",
|
|
29
|
+
"src"
|
|
27
30
|
],
|
|
28
31
|
"license": "MIT",
|
|
29
32
|
"peerDependencies": {
|
package/src/apply.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure text updates following OpenAI Codex rust-v0.158.0 NormalizeToLf behavior.
|
|
3
|
+
* Adapted from seek_sequence.rs and file_update.rs with structured match failures.
|
|
4
|
+
* Copyright 2025 OpenAI. Apache-2.0 portions and modification notice: ../LICENSE.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ApplyHunksResult, PatchHunk } from './types.ts'
|
|
8
|
+
|
|
9
|
+
const WHITE_SPACE = /\p{White_Space}/u
|
|
10
|
+
|
|
11
|
+
function trimWhitespace(value: string, leading: boolean): string {
|
|
12
|
+
let start = 0
|
|
13
|
+
let end = value.length
|
|
14
|
+
if (leading) {
|
|
15
|
+
while (start < end && WHITE_SPACE.test(value.charAt(start))) start++
|
|
16
|
+
}
|
|
17
|
+
while (end > start && WHITE_SPACE.test(value.charAt(end - 1))) end--
|
|
18
|
+
return value.slice(start, end)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function normalizePunctuation(value: string): string {
|
|
22
|
+
return trimWhitespace(value, true)
|
|
23
|
+
.replace(/[\u2010-\u2015\u2212]/gu, '-')
|
|
24
|
+
.replace(/[\u2018-\u201B]/gu, "'")
|
|
25
|
+
.replace(/[\u201C-\u201F]/gu, '"')
|
|
26
|
+
.replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/gu, ' ')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const MATCH_PASSES = [
|
|
30
|
+
(value: string) => value,
|
|
31
|
+
(value: string) => trimWhitespace(value, false),
|
|
32
|
+
(value: string) => trimWhitespace(value, true),
|
|
33
|
+
normalizePunctuation,
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
/** NormalizeToLf checks only the tail candidate for EOF, even before the cursor. */
|
|
37
|
+
function seekSequence(lines: readonly string[], pattern: readonly string[], start: number, eof: boolean): number | undefined {
|
|
38
|
+
if (pattern.length === 0) return start
|
|
39
|
+
if (pattern.length > lines.length) return undefined
|
|
40
|
+
const last = lines.length - pattern.length
|
|
41
|
+
const first = eof ? last : start
|
|
42
|
+
for (const normalize of MATCH_PASSES) {
|
|
43
|
+
const expected = pattern.map(normalize)
|
|
44
|
+
for (let index = first; index <= last; index++) {
|
|
45
|
+
if (expected.every((line, offset) => normalize(lines[index + offset] as string) === line)) return index
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface Replacement {
|
|
52
|
+
start: number
|
|
53
|
+
oldLength: number
|
|
54
|
+
newLines: readonly string[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Apply parsed hunks to LF-normalized text without I/O or input mutation.
|
|
59
|
+
* All searches use the original text; a failed search returns no partial text.
|
|
60
|
+
* Successful nonempty output ends in LF, including initially unterminated text.
|
|
61
|
+
* @param before - text normalized by the caller; CR characters receive no line-ending handling.
|
|
62
|
+
* @param hunks - ordered hunks from parsePatch; EOF searches follow NormalizeToLf tail semantics.
|
|
63
|
+
* @returns new text or the first unmatched hunk, without throwing for a match failure.
|
|
64
|
+
*/
|
|
65
|
+
export function applyHunks(before: string, hunks: readonly PatchHunk[]): ApplyHunksResult {
|
|
66
|
+
const original = before.split('\n')
|
|
67
|
+
if (original.at(-1) === '') original.pop()
|
|
68
|
+
const replacements: Replacement[] = []
|
|
69
|
+
let lineIndex = 0
|
|
70
|
+
|
|
71
|
+
for (const hunk of hunks) {
|
|
72
|
+
if (hunk.context !== undefined) {
|
|
73
|
+
const pattern = [hunk.context]
|
|
74
|
+
const found = seekSequence(original, pattern, lineIndex, false)
|
|
75
|
+
if (found === undefined) {
|
|
76
|
+
return { ok: false, failure: { hunkLineNumber: hunk.lineNumber, stage: 'context', searchStart: lineIndex, pattern } }
|
|
77
|
+
}
|
|
78
|
+
lineIndex = found + 1
|
|
79
|
+
}
|
|
80
|
+
if (hunk.oldLines.length === 0) {
|
|
81
|
+
const start = original.at(-1) === '' ? original.length - 1 : original.length
|
|
82
|
+
replacements.push({ start, oldLength: 0, newLines: hunk.newLines })
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let pattern = hunk.oldLines
|
|
87
|
+
let newLines = hunk.newLines
|
|
88
|
+
let found = seekSequence(original, pattern, lineIndex, hunk.isEndOfFile)
|
|
89
|
+
if (found === undefined && pattern.at(-1) === '') {
|
|
90
|
+
pattern = pattern.slice(0, -1)
|
|
91
|
+
if (newLines.at(-1) === '') newLines = newLines.slice(0, -1)
|
|
92
|
+
found = seekSequence(original, pattern, lineIndex, hunk.isEndOfFile)
|
|
93
|
+
}
|
|
94
|
+
if (found === undefined) {
|
|
95
|
+
return {
|
|
96
|
+
ok: false,
|
|
97
|
+
failure: { hunkLineNumber: hunk.lineNumber, stage: 'oldLines', searchStart: lineIndex, pattern: [...hunk.oldLines] },
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
replacements.push({ start: found, oldLength: pattern.length, newLines })
|
|
101
|
+
lineIndex = found + pattern.length
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Stable ordering also preserves patch order for insertions at the same source index.
|
|
105
|
+
replacements.sort((left, right) => left.start - right.start)
|
|
106
|
+
let lines = original
|
|
107
|
+
for (const replacement of replacements.reverse()) {
|
|
108
|
+
lines = [
|
|
109
|
+
...lines.slice(0, replacement.start),
|
|
110
|
+
...replacement.newLines,
|
|
111
|
+
...lines.slice(replacement.start + replacement.oldLength),
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
if (lines.at(-1) !== '') lines.push('')
|
|
115
|
+
return { ok: true, after: lines.join('\n') }
|
|
116
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Pure patch parsing and text application, independent of filesystem providers. */
|
|
2
|
+
|
|
3
|
+
export { parsePatch, PatchParseError } from './parse.ts'
|
|
4
|
+
export { applyHunks } from './apply.ts'
|
|
5
|
+
export type { ApplyHunksResult, HunkApplyFailure, PatchHunk, PatchOperation } from './types.ts'
|
package/src/parse.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch parser following OpenAI Codex rust-v0.158.0 parser.rs and streaming_parser.rs.
|
|
3
|
+
* Adapted into a pure TypeScript parser with original-input diagnostics and no environment routing.
|
|
4
|
+
* Copyright 2025 OpenAI. Apache-2.0 portions and modification notice: ../LICENSE.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { PatchHunk, PatchOperation } from './types.ts'
|
|
8
|
+
|
|
9
|
+
const BEGIN = '*** Begin Patch'
|
|
10
|
+
const END = '*** End Patch'
|
|
11
|
+
const EOF = '*** End of File'
|
|
12
|
+
const MOVE = '*** Move to: '
|
|
13
|
+
const ADD = '*** Add File: '
|
|
14
|
+
const DELETE = '*** Delete File: '
|
|
15
|
+
const UPDATE = '*** Update File: '
|
|
16
|
+
|
|
17
|
+
/** Rust uses Unicode White_Space (all in the BMP); JavaScript trim also removes BOM. */
|
|
18
|
+
const WHITE_SPACE = /\p{White_Space}/u
|
|
19
|
+
|
|
20
|
+
/** Syntax failure with a one-based line in the original input, including any wrapper. */
|
|
21
|
+
export class PatchParseError extends Error {
|
|
22
|
+
constructor(readonly lineNumber: number, readonly reason: string) {
|
|
23
|
+
super(`Invalid patch at line ${lineNumber}: ${reason}`)
|
|
24
|
+
this.name = 'PatchParseError'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Scan the ends to avoid regex backtracking over long interior whitespace. */
|
|
29
|
+
function trim(value: string): string {
|
|
30
|
+
let start = 0
|
|
31
|
+
while (start < value.length && WHITE_SPACE.test(value.charAt(start))) start++
|
|
32
|
+
return trimEnd(value.slice(start))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function trimEnd(value: string): string {
|
|
36
|
+
let end = value.length
|
|
37
|
+
while (end > 0 && WHITE_SPACE.test(value.charAt(end - 1))) end--
|
|
38
|
+
return value.slice(0, end)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface InputLine {
|
|
42
|
+
text: string
|
|
43
|
+
number: number
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function patchLines(patch: string): InputLine[] {
|
|
47
|
+
const leading = patch.slice(0, patch.length - patch.replace(/^\p{White_Space}+/u, '').length)
|
|
48
|
+
const offset = leading.split('\n').length - 1
|
|
49
|
+
let lines = trim(patch).split(/\r?\n/u).map((text, index) => ({ text, number: offset + index + 1 }))
|
|
50
|
+
const first = lines[0] as InputLine
|
|
51
|
+
const last = lines.at(-1) as InputLine
|
|
52
|
+
if (['<<EOF', "<<'EOF'", '<<"EOF"'].includes(first.text) && last.text.endsWith('EOF') && lines.length >= 4) {
|
|
53
|
+
lines = lines.slice(1, -1)
|
|
54
|
+
}
|
|
55
|
+
// split always yields a line; removing a wrapper retains at least two lines.
|
|
56
|
+
const start = lines[0] as InputLine
|
|
57
|
+
const end = lines.at(-1) as InputLine
|
|
58
|
+
if (trim(start.text) !== BEGIN) {
|
|
59
|
+
throw new PatchParseError(start.number, `Expected '${BEGIN}'`)
|
|
60
|
+
}
|
|
61
|
+
if (trim(end.text) !== END) {
|
|
62
|
+
throw new PatchParseError(end.number, `Expected '${END}'`)
|
|
63
|
+
}
|
|
64
|
+
// Codex joins Rust str::lines output, then its streaming parser strips CR before LF again.
|
|
65
|
+
return lines.map((line, index) => index < lines.length - 1
|
|
66
|
+
? { ...line, text: line.text.replace(/\r$/u, '') }
|
|
67
|
+
: line)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function emptyHunk(hunk: PatchHunk): boolean {
|
|
71
|
+
return hunk.oldLines.length === 0 && hunk.newLines.length === 0
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function ensureUpdate(operation: PatchOperation | undefined, lineNumber: number): void {
|
|
75
|
+
if (operation?.kind !== 'update') return
|
|
76
|
+
const last = operation.hunks.at(-1)
|
|
77
|
+
if (last === undefined) {
|
|
78
|
+
throw new PatchParseError(operation.lineNumber, `Update for '${operation.path}' requires at least one hunk`)
|
|
79
|
+
}
|
|
80
|
+
if (emptyHunk(last)) {
|
|
81
|
+
throw new PatchParseError(lineNumber, 'Update hunk must contain context, added, or removed lines')
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function newHunk(lineNumber: number): PatchHunk {
|
|
86
|
+
return { lineNumber, oldLines: [], newLines: [], isEndOfFile: false }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readUpdate(operation: Extract<PatchOperation, { kind: 'update' }>, line: InputLine): void {
|
|
90
|
+
const text = trimEnd(line.text)
|
|
91
|
+
const previous = operation.hunks.at(-1)
|
|
92
|
+
const marker = text === '@@' || text.startsWith('@@ ')
|
|
93
|
+
if (previous?.isEndOfFile) {
|
|
94
|
+
if (text === '') return
|
|
95
|
+
if (!marker) throw new PatchParseError(line.number, "Expected '@@' after '*** End of File'")
|
|
96
|
+
}
|
|
97
|
+
if (previous === undefined && operation.moveTo === undefined && text.startsWith(MOVE)) {
|
|
98
|
+
operation.moveTo = text.slice(MOVE.length)
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
if (marker) {
|
|
102
|
+
if (previous !== undefined && emptyHunk(previous)) {
|
|
103
|
+
throw new PatchParseError(line.number, 'Update hunk must contain context, added, or removed lines')
|
|
104
|
+
}
|
|
105
|
+
const hunk = newHunk(line.number)
|
|
106
|
+
if (text.startsWith('@@ ')) hunk.context = text.slice(3)
|
|
107
|
+
operation.hunks.push(hunk)
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
if (text === EOF) {
|
|
111
|
+
if (previous !== undefined) {
|
|
112
|
+
if (emptyHunk(previous)) {
|
|
113
|
+
throw new PatchParseError(line.number, 'Update hunk must contain context, added, or removed lines')
|
|
114
|
+
}
|
|
115
|
+
previous.isEndOfFile = true
|
|
116
|
+
}
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
const prefix = line.text[0]
|
|
120
|
+
if (line.text !== '' && prefix !== ' ' && prefix !== '+' && prefix !== '-') {
|
|
121
|
+
throw new PatchParseError(line.number, "Expected a context (' '), added ('+'), removed ('-') line, or '@@'")
|
|
122
|
+
}
|
|
123
|
+
const hunk = previous ?? newHunk(line.number)
|
|
124
|
+
if (previous === undefined) operation.hunks.push(hunk)
|
|
125
|
+
const content = line.text.slice(1)
|
|
126
|
+
if (prefix === '+') hunk.newLines.push(content)
|
|
127
|
+
else if (prefix === '-') hunk.oldLines.push(content)
|
|
128
|
+
else {
|
|
129
|
+
hunk.oldLines.push(content)
|
|
130
|
+
hunk.newLines.push(content)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Parse a complete Codex-style patch without reading or modifying files.
|
|
136
|
+
* @param patch - patch text, optionally wrapped in a literal EOF heredoc.
|
|
137
|
+
* @returns ordered, JSON-serializable operations; an empty patch returns an empty array.
|
|
138
|
+
* @throws PatchParseError for malformed syntax or an unsupported Environment ID header.
|
|
139
|
+
*/
|
|
140
|
+
export function parsePatch(patch: string): PatchOperation[] {
|
|
141
|
+
const lines = patchLines(patch)
|
|
142
|
+
const operations: PatchOperation[] = []
|
|
143
|
+
let ended = false
|
|
144
|
+
for (const line of lines.slice(1)) {
|
|
145
|
+
const operation = operations.at(-1)
|
|
146
|
+
// The final marker is trimmed even in update mode by Codex's batch-parser finish step.
|
|
147
|
+
const header = operation?.kind === 'update' && line !== lines.at(-1) ? trimEnd(line.text) : trim(line.text)
|
|
148
|
+
if (ended && line !== lines.at(-1)) {
|
|
149
|
+
if (trim(line.text) !== '') throw new PatchParseError(line.number, `Unexpected content after '${END}'`)
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
152
|
+
if (header === END) {
|
|
153
|
+
ensureUpdate(operation, line.number)
|
|
154
|
+
ended = true
|
|
155
|
+
} else if (header.startsWith(ADD)) {
|
|
156
|
+
ensureUpdate(operation, line.number)
|
|
157
|
+
operations.push({ kind: 'add', path: header.slice(ADD.length), lineNumber: line.number, content: '' })
|
|
158
|
+
} else if (header.startsWith(DELETE)) {
|
|
159
|
+
ensureUpdate(operation, line.number)
|
|
160
|
+
operations.push({ kind: 'delete', path: header.slice(DELETE.length), lineNumber: line.number })
|
|
161
|
+
} else if (header.startsWith(UPDATE)) {
|
|
162
|
+
ensureUpdate(operation, line.number)
|
|
163
|
+
operations.push({ kind: 'update', path: header.slice(UPDATE.length), lineNumber: line.number, hunks: [] })
|
|
164
|
+
} else if (operations.length === 0 && header.startsWith('*** Environment ID:')) {
|
|
165
|
+
throw new PatchParseError(line.number, 'Environment ID headers are unsupported; the caller selects the filesystem provider')
|
|
166
|
+
} else if (operation?.kind === 'add' && line.text.startsWith('+')) {
|
|
167
|
+
operation.content += `${line.text.slice(1)}\n`
|
|
168
|
+
} else if (operation?.kind === 'update') {
|
|
169
|
+
readUpdate(operation, line)
|
|
170
|
+
} else {
|
|
171
|
+
throw new PatchParseError(line.number, 'Expected an Add File, Delete File, or Update File header; added content must start with +')
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return operations
|
|
175
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Serializable patch syntax and text-application results; paths remain unresolved. */
|
|
2
|
+
|
|
3
|
+
/** One contiguous update. */
|
|
4
|
+
export interface PatchHunk {
|
|
5
|
+
/** One-based input line containing the marker or first implicit hunk line. */
|
|
6
|
+
lineNumber: number
|
|
7
|
+
/** Text following `@@ `, used as a search anchor by the text matcher. */
|
|
8
|
+
context?: string
|
|
9
|
+
/** Context and removed lines, without patch prefixes or line endings. */
|
|
10
|
+
oldLines: string[]
|
|
11
|
+
/** Context and added lines, without patch prefixes or line endings. */
|
|
12
|
+
newLines: string[]
|
|
13
|
+
/** Whether `*** End of File` follows this hunk. */
|
|
14
|
+
isEndOfFile: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Ordered file operation; a move is an update with a destination path. */
|
|
18
|
+
export type PatchOperation =
|
|
19
|
+
| {
|
|
20
|
+
kind: 'add'
|
|
21
|
+
path: string
|
|
22
|
+
lineNumber: number
|
|
23
|
+
/** Added lines joined with LF, including a final LF for every added line. */
|
|
24
|
+
content: string
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
kind: 'delete'
|
|
28
|
+
path: string
|
|
29
|
+
lineNumber: number
|
|
30
|
+
}
|
|
31
|
+
| {
|
|
32
|
+
kind: 'update'
|
|
33
|
+
path: string
|
|
34
|
+
lineNumber: number
|
|
35
|
+
moveTo?: string
|
|
36
|
+
hunks: PatchHunk[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The first hunk whose anchor or old lines could not be located in the original text. */
|
|
40
|
+
export interface HunkApplyFailure {
|
|
41
|
+
/** One-based line of the failing hunk in the patch input. */
|
|
42
|
+
hunkLineNumber: number
|
|
43
|
+
/** The failed anchor or old-content search. */
|
|
44
|
+
stage: 'context' | 'oldLines'
|
|
45
|
+
/** Zero-based sequential search cursor; EOF searches override it with the tail candidate. */
|
|
46
|
+
searchStart: number
|
|
47
|
+
/** Original anchor or old lines, including any trailing empty line retried without its sentinel. */
|
|
48
|
+
pattern: string[]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Complete new text or a match failure; failures contain no partially updated text. */
|
|
52
|
+
export type ApplyHunksResult =
|
|
53
|
+
| { ok: true; after: string }
|
|
54
|
+
| { ok: false; failure: HunkApplyFailure }
|