MCPcopy Index your code
hub / github.com/kpdecker/jsdiff / parseGitDiffHeader

Function parseGitDiffHeader

src/patch/parse.ts:266–334  ·  view source on GitHub ↗

* Parses the old and new filenames from a `diff --git` header line. * * The format is: * diff --git a/ b/ * * When filenames contain special characters (including newlines, tabs, * backslashes, or double quotes), Git quotes them with C-style escaping: *

(line: string)

Source from the content-addressed store, hash-verified

264 * undefined in the output.
265 */
266 function parseGitDiffHeader(line: string): { oldFileName: string, newFileName: string } | null {
267 // Strip the "diff --git " prefix
268 const rest = line.substring('diff --git '.length);
269
270 // Handle quoted paths: "a/path" "b/path"
271 // Git quotes paths when they contain characters like newlines, tabs,
272 // backslashes, or double quotes (but notably not spaces).
273 if (rest.startsWith('"')) {
274 const oldPath = parseQuotedFileName(rest);
275 if (oldPath === null) { return null; }
276 const afterOld = rest.substring(oldPath.rawLength + 1); // +1 for space
277 let newFileName: string;
278 if (afterOld.startsWith('"')) {
279 const newPath = parseQuotedFileName(afterOld);
280 if (newPath === null) { return null; }
281 newFileName = newPath.fileName;
282 } else {
283 newFileName = afterOld;
284 }
285 return {
286 oldFileName: oldPath.fileName,
287 newFileName
288 };
289 }
290
291 // Check if the second path is quoted
292 // e.g. diff --git a/simple "b/renamed\nnewline.txt"
293 const quoteIdx = rest.indexOf('"');
294 if (quoteIdx > 0) {
295 const oldFileName = rest.substring(0, quoteIdx - 1);
296 const newPath = parseQuotedFileName(rest.substring(quoteIdx));
297 if (newPath === null) { return null; }
298 return {
299 oldFileName,
300 newFileName: newPath.fileName
301 };
302 }
303
304 // Unquoted paths. Try to find the split point.
305 // The format is: a/<old-path> b/<new-path>
306 //
307 // Note the potential ambiguity caused by the possibility of the file paths
308 // themselves containing the substring ` b/`, plus the pathological case
309 // described in the comment above.
310 //
311 // Strategy: find all occurrences of " b/" and split on the middle
312 // one. When old and new names are the same (which is the only case where
313 // we can't rely on extended headers later in the patch so HAVE to get
314 // this right), this will always be the correct split.
315 if (rest.startsWith('a/')) {
316 const splits = [];
317 let idx = 0;
318 while (true) {
319 idx = rest.indexOf(' b/', idx + 1);
320 if (idx === -1) { break; }
321 splits.push(idx);
322 }
323 if (splits.length > 0) {

Callers 1

parseIndexFunction · 0.85

Calls 1

parseQuotedFileNameFunction · 0.85

Tested by

no test coverage detected