File Explorer

/proc/self/root/proc/1/cwd/node24/lib/node_modules/npm/node_modules/diff/libesm/patch

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

create.js9.3 KB · 229 lines
import { diffLines } from '../diff/line.js';export const INCLUDE_HEADERS = {    includeIndex: true,    includeUnderline: true,    includeFileHeaders: true};export const FILE_HEADERS_ONLY = {    includeIndex: false,    includeUnderline: false,    includeFileHeaders: true};export const OMIT_HEADERS = {    includeIndex: false,    includeUnderline: false,    includeFileHeaders: false};export function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {    let optionsObj;    if (!options) {        optionsObj = {};    }    else if (typeof options === 'function') {        optionsObj = { callback: options };    }    else {        optionsObj = options;    }    if (typeof optionsObj.context === 'undefined') {        optionsObj.context = 4;    }    // We copy this into its own variable to placate TypeScript, which thinks    // optionsObj.context might be undefined in the callbacks below.    const context = optionsObj.context;    // @ts-expect-error (runtime check for something that is correctly a static type error)    if (optionsObj.newlineIsToken) {        throw new Error('newlineIsToken may not be used with patch-generation functions, only with diffing functions');    }    if (!optionsObj.callback) {        return diffLinesResultToPatch(diffLines(oldStr, newStr, optionsObj));    }    else {        const { callback } = optionsObj;        diffLines(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff) => {                const patch = diffLinesResultToPatch(diff);                // TypeScript is unhappy without the cast because it does not understand that `patch` may                // be undefined here only if `callback` is StructuredPatchCallbackAbortable:                callback(patch);            } }));    }    function diffLinesResultToPatch(diff) {        // STEP 1: Build up the patch with no "\ No newline at end of file" lines and with the arrays        //         of lines containing trailing newline characters. We'll tidy up later...        if (!diff) {            return;        }        diff.push({ value: '', lines: [] }); // Append an empty value to make cleanup easier        function contextLines(lines) {            return lines.map(function (entry) { return ' ' + entry; });        }        const hunks = [];        let oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1;        for (let i = 0; i < diff.length; i++) {            const current = diff[i], lines = current.lines || splitLines(current.value);            current.lines = lines;            if (current.added || current.removed) {                // If we have previous context, start with that                if (!oldRangeStart) {                    const prev = diff[i - 1];                    oldRangeStart = oldLine;                    newRangeStart = newLine;                    if (prev) {                        curRange = context > 0 ? contextLines(prev.lines.slice(-context)) : [];                        oldRangeStart -= curRange.length;                        newRangeStart -= curRange.length;                    }                }                // Output our changes                for (const line of lines) {                    curRange.push((current.added ? '+' : '-') + line);                }                // Track the updated file position                if (current.added) {                    newLine += lines.length;                }                else {                    oldLine += lines.length;                }            }            else {                // Identical context lines. Track line changes                if (oldRangeStart) {                    // Close out any changes that have been output (or join overlapping)                    if (lines.length <= context * 2 && i < diff.length - 2) {                        // Overlapping                        for (const line of contextLines(lines)) {                            curRange.push(line);                        }                    }                    else {                        // end the range and output                        const contextSize = Math.min(lines.length, context);                        for (const line of contextLines(lines.slice(0, contextSize))) {                            curRange.push(line);                        }                        const hunk = {                            oldStart: oldRangeStart,                            oldLines: (oldLine - oldRangeStart + contextSize),                            newStart: newRangeStart,                            newLines: (newLine - newRangeStart + contextSize),                            lines: curRange                        };                        hunks.push(hunk);                        oldRangeStart = 0;                        newRangeStart = 0;                        curRange = [];                    }                }                oldLine += lines.length;                newLine += lines.length;            }        }        // Step 2: eliminate the trailing `\n` from each line of each hunk, and, where needed, add        //         "\ No newline at end of file".        for (const hunk of hunks) {            for (let i = 0; i < hunk.lines.length; i++) {                if (hunk.lines[i].endsWith('\n')) {                    hunk.lines[i] = hunk.lines[i].slice(0, -1);                }                else {                    hunk.lines.splice(i + 1, 0, '\\ No newline at end of file');                    i++; // Skip the line we just added, then continue iterating                }            }        }        return {            oldFileName: oldFileName, newFileName: newFileName,            oldHeader: oldHeader, newHeader: newHeader,            hunks: hunks        };    }}/** * creates a unified diff patch. * @param patch either a single structured patch object (as returned by `structuredPatch`) or an array of them (as returned by `parsePatch`) */export function formatPatch(patch, headerOptions) {    if (!headerOptions) {        headerOptions = INCLUDE_HEADERS;    }    if (Array.isArray(patch)) {        if (patch.length > 1 && !headerOptions.includeFileHeaders) {            throw new Error('Cannot omit file headers on a multi-file patch. '                + '(The result would be unparseable; how would a tool trying to apply '                + 'the patch know which changes are to which file?)');        }        return patch.map(p => formatPatch(p, headerOptions)).join('\n');    }    const ret = [];    if (headerOptions.includeIndex && patch.oldFileName == patch.newFileName) {        ret.push('Index: ' + patch.oldFileName);    }    if (headerOptions.includeUnderline) {        ret.push('===================================================================');    }    if (headerOptions.includeFileHeaders) {        ret.push('--- ' + patch.oldFileName + (typeof patch.oldHeader === 'undefined' ? '' : '\t' + patch.oldHeader));        ret.push('+++ ' + patch.newFileName + (typeof patch.newHeader === 'undefined' ? '' : '\t' + patch.newHeader));    }    for (let i = 0; i < patch.hunks.length; i++) {        const hunk = patch.hunks[i];        // Unified Diff Format quirk: If the chunk size is 0,        // the first number is one lower than one would expect.        // https://www.artima.com/weblogs/viewpost.jsp?thread=164293        if (hunk.oldLines === 0) {            hunk.oldStart -= 1;        }        if (hunk.newLines === 0) {            hunk.newStart -= 1;        }        ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines            + ' +' + hunk.newStart + ',' + hunk.newLines            + ' @@');        for (const line of hunk.lines) {            ret.push(line);        }    }    return ret.join('\n') + '\n';}export function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {    if (typeof options === 'function') {        options = { callback: options };    }    if (!(options === null || options === void 0 ? void 0 : options.callback)) {        const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);        if (!patchObj) {            return;        }        return formatPatch(patchObj, options === null || options === void 0 ? void 0 : options.headerOptions);    }    else {        const { callback } = options;        structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options), { callback: patchObj => {                if (!patchObj) {                    callback(undefined);                }                else {                    callback(formatPatch(patchObj, options.headerOptions));                }            } }));    }}export function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {    return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);}/** * Split `text` into an array of lines, including the trailing newline character (where present) */function splitLines(text) {    const hasTrailingNl = text.endsWith('\n');    const result = text.split('\n').map(line => line + '\n');    if (hasTrailingNl) {        result.pop();    }    else {        result.push(result.pop().slice(0, -1));    }    return result;}