Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 5x 5x 5x 5x 7x 43x 25x 9x 5x 24x 5x 13x 4x 9x 9x 9x 9x 9x 9x 9x 227x 9x 5x 5x 11x 11x 5x 2x 2x 5x 7x 7x 5x 25x 4x 11x 2x 7x 1x 5x 25x | /* eslint-disable @gitlab/require-i18n-strings */
import { createTwoFilesPatch } from 'diff';
import { commitActionTypes } from '~/ide/constants';
const DEV_NULL = '/dev/null';
const DEFAULT_MODE = '100644';
const NO_NEW_LINE = '\\ No newline at end of file';
const NEW_LINE = '\n';
/**
* Cleans patch generated by `diff` package.
*
* - Removes "=======" separator added at the beginning
*/
const cleanTwoFilesPatch = (text) => text.replace(/^(=+\s*)/, '');
const endsWithNewLine = (val) => !val || val[val.length - 1] === NEW_LINE;
const addEndingNewLine = (val) => (endsWithNewLine(val) ? val : val + NEW_LINE);
const removeEndingNewLine = (val) => (endsWithNewLine(val) ? val.substr(0, val.length - 1) : val);
const diffHead = (prevPath, newPath = '') =>
`diff --git "a/${prevPath}" "b/${newPath || prevPath}"`;
const createDiffBody = (path, content, isCreate) => {
if (!content) {
return '';
}
const prefix = isCreate ? '+' : '-';
const fromPath = isCreate ? DEV_NULL : `a/${path}`;
const toPath = isCreate ? `b/${path}` : DEV_NULL;
const hasNewLine = endsWithNewLine(content);
const lines = removeEndingNewLine(content).split(NEW_LINE);
const chunkHead = isCreate ? `@@ -0,0 +1,${lines.length} @@` : `@@ -1,${lines.length} +0,0 @@`;
const chunk = lines
.map((line) => `${prefix}${line}`)
.concat(!hasNewLine ? [NO_NEW_LINE] : [])
.join(NEW_LINE);
return `--- ${fromPath}
+++ ${toPath}
${chunkHead}
${chunk}`;
};
const createMoveFileDiff = (prevPath, newPath) => `${diffHead(prevPath, newPath)}
rename from ${prevPath}
rename to ${newPath}`;
const createNewFileDiff = (path, content) => {
const diff = createDiffBody(path, content, true);
return `${diffHead(path)}
new file mode ${DEFAULT_MODE}
${diff}`;
};
const createDeleteFileDiff = (path, content) => {
const diff = createDiffBody(path, content, false);
return `${diffHead(path)}
deleted file mode ${DEFAULT_MODE}
${diff}`;
};
const createUpdateFileDiff = (path, oldContent, newContent) => {
const patch = createTwoFilesPatch(`a/${path}`, `b/${path}`, oldContent, newContent);
return `${diffHead(path)}
${cleanTwoFilesPatch(patch)}`;
};
const createFileDiffRaw = (file, action) => {
switch (action) {
case commitActionTypes.move:
return createMoveFileDiff(file.prevPath, file.path);
case commitActionTypes.create:
return createNewFileDiff(file.path, file.content);
case commitActionTypes.delete:
return createDeleteFileDiff(file.path, file.content);
case commitActionTypes.update:
return createUpdateFileDiff(file.path, file.raw || '', file.content);
default:
return '';
}
};
/**
* Create a git diff for a single IDE file.
*
* ## Notes:
* When called with `commitActionType.move`, it assumes that the move
* is a 100% similarity move. No diff will be generated. This is because
* generating a move with changes is not support by the current IDE, since
* the source file might not have it's content loaded yet.
*
* When called with `commitActionType.delete`, it does not support
* deleting files with a mode different than 100644. For the IDE mirror, this
* isn't needed because deleting is handled outside the unified patch.
*
* ## References:
* - https://git-scm.com/docs/git-diff#_generating_patches_with_p
*/
const createFileDiff = (file, action) =>
// It's important that the file diff ends in a new line - git expects this.
addEndingNewLine(createFileDiffRaw(file, action));
export default createFileDiff;
|