summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-11-22 09:08:30 +0000
committerPhil Hughes <me@iamphill.com>2017-11-28 09:23:41 +0000
commitcaa2f10e719e700ae7d51ddb0180e9505fb1ffa6 (patch)
tree4bb4374cbeea17c48a1feb41032a5ff90fd582fd
parenteb8a609519fe45b13aa945e36637381741313aed (diff)
downloadgitlab-ce-caa2f10e719e700ae7d51ddb0180e9505fb1ffa6.tar.gz
change how diffing works
[ci skip]
-rw-r--r--app/assets/javascripts/repo/lib/diff/controller.js30
-rw-r--r--app/assets/javascripts/repo/lib/diff/worker.js103
-rw-r--r--app/assets/javascripts/repo/lib/editor.js25
-rw-r--r--package.json1
-rw-r--r--yarn.lock4
5 files changed, 59 insertions, 104 deletions
diff --git a/app/assets/javascripts/repo/lib/diff/controller.js b/app/assets/javascripts/repo/lib/diff/controller.js
index 39c6cb92e0f..6c97f1cc24d 100644
--- a/app/assets/javascripts/repo/lib/diff/controller.js
+++ b/app/assets/javascripts/repo/lib/diff/controller.js
@@ -1,24 +1,25 @@
/* global monaco */
-import Disposable from '../common/disposable';
import DirtyDiffWorker from './worker';
+import Disposable from '../common/disposable';
import decorationsController from '../decorations/controller';
export const getDiffChangeType = (change) => {
- if (change.originalEndLineNumber === 0) {
+ if (change.modified) {
+ return 'modified';
+ } else if (change.added) {
return 'added';
- } else if (change.modifiedEndLineNumber === 0) {
+ } else if (change.removed) {
return 'removed';
}
- return 'modified';
+ return '';
};
export const getDecorator = change => ({
range: new monaco.Range(
- change.modifiedStartLineNumber,
+ change.lineNumber,
1,
- !change.modifiedEndLineNumber ?
- change.modifiedStartLineNumber : change.modifiedEndLineNumber,
+ change.endLineNumber,
1,
),
options: {
@@ -37,22 +38,15 @@ export default class DirtyDiffController {
this.disposable = new Disposable();
this.editorSimpleWorker = null;
this.modelManager = modelManager;
- this.disposable.add(this.worker = new DirtyDiffWorker());
+ this.dirtyDiffWorker = new DirtyDiffWorker();
}
attachModel(model) {
- if (model.attachedToWorker) return;
-
- [model.getModel(), model.getOriginalModel()].forEach(() => {
- this.worker.attachModel(model);
- });
-
- model.onChange((_, e) => this.computeDiff(model, e));
+ model.onChange(() => this.computeDiff(model));
}
- computeDiff(model, e) {
- this.worker.modelChanged(model, e);
- this.worker.compute(model, changes => decorate(model, changes));
+ computeDiff(model) {
+ decorate(model, this.dirtyDiffWorker.compute(model));
}
// eslint-disable-next-line class-methods-use-this
diff --git a/app/assets/javascripts/repo/lib/diff/worker.js b/app/assets/javascripts/repo/lib/diff/worker.js
index 39047d85507..0007c7060dc 100644
--- a/app/assets/javascripts/repo/lib/diff/worker.js
+++ b/app/assets/javascripts/repo/lib/diff/worker.js
@@ -1,77 +1,34 @@
-/* global monaco */
-import Disposable from '../common/disposable';
+import { diffLines } from 'diff';
export default class DirtyDiffWorker {
- constructor() {
- this.editorSimpleWorker = null;
- this.disposable = new Disposable();
- this.actions = new Set();
-
- // eslint-disable-next-line promise/catch-or-return
- monaco.editor.createWebWorker({
- moduleId: 'vs/editor/common/services/editorSimpleWorker',
- }).getProxy().then((editorSimpleWorker) => {
- this.disposable.add(this.editorSimpleWorker = editorSimpleWorker);
- this.ready();
- });
- }
-
- // loop through all the previous cached actions
- // this way we don't block the user from editing the file
- ready() {
- this.actions.forEach((action) => {
- const methodName = Object.keys(action)[0];
- this[methodName](...action[methodName]);
- });
-
- this.actions.clear();
- }
-
- attachModel(model) {
- if (this.editorSimpleWorker && !model.attachedToWorker) {
- this.editorSimpleWorker.acceptNewModel(model.diffModel);
- this.editorSimpleWorker.acceptNewModel(model.originalDiffModel);
-
- model.setAttachedToWorker(true);
- } else if (!this.editorSimpleWorker) {
- this.actions.add({
- attachModel: [model],
- });
- }
- }
-
- modelChanged(model, e) {
- if (this.editorSimpleWorker) {
- this.editorSimpleWorker.acceptModelChanged(
- model.url,
- e,
- );
- } else {
- this.actions.add({
- modelChanged: [model, e],
- });
- }
- }
-
- compute(model, cb) {
- if (this.editorSimpleWorker) {
- return this.editorSimpleWorker.computeDiff(
- model.originalUrl,
- model.url,
- ).then(cb);
- }
-
- this.actions.add({
- compute: [model, cb],
- });
-
- return null;
- }
-
- dispose() {
- this.actions.clear();
-
- this.disposable.dispose();
- this.editorSimpleWorker = null;
+ // eslint-disable-next-line class-methods-use-this
+ compute(model) {
+ const originalContent = model.getOriginalModel().getValue();
+ const newContent = model.getModel().getValue();
+ const changes = diffLines(originalContent, newContent);
+
+ let lineNumber = 1;
+ return changes.reduce((acc, change) => {
+ const findOnLine = acc.find(c => c.lineNumber === lineNumber);
+
+ if (findOnLine) {
+ Object.assign(findOnLine, change, {
+ modified: true,
+ endLineNumber: change.count > 1 ? lineNumber + change.count : lineNumber,
+ });
+ } else if ('added' in change || 'removed' in change) {
+ acc.push(Object.assign({}, change, {
+ lineNumber,
+ modified: undefined,
+ endLineNumber: change.count > 1 ? lineNumber + change.count : lineNumber,
+ }));
+ }
+
+ if (!change.removed) {
+ lineNumber += change.count;
+ }
+
+ return acc;
+ }, []);
}
}
diff --git a/app/assets/javascripts/repo/lib/editor.js b/app/assets/javascripts/repo/lib/editor.js
index 173eacbd65c..ea3bfe16462 100644
--- a/app/assets/javascripts/repo/lib/editor.js
+++ b/app/assets/javascripts/repo/lib/editor.js
@@ -11,28 +11,27 @@ export default class Editor {
}
constructor() {
- this.diffComputers = new Map();
this.currentModel = null;
this.instance = null;
this.dirtyDiffController = null;
- this.modelManager = new ModelManager();
this.disposable = new Disposable();
- this.disposable.add(this.modelManager);
+ this.disposable.add(
+ this.modelManager = new ModelManager(),
+ );
}
createInstance(domElement) {
if (!this.instance) {
- this.instance = monaco.editor.create(domElement, {
- model: null,
- readOnly: false,
- contextmenu: true,
- scrollBeyondLastLine: false,
- });
-
- this.dirtyDiffController = new DirtyDiffController(this.modelManager);
-
- this.disposable.add(this.dirtyDiffController, this.instance);
+ this.disposable.add(
+ this.instance = monaco.editor.create(domElement, {
+ model: null,
+ readOnly: false,
+ contextmenu: true,
+ scrollBeyondLastLine: false,
+ }),
+ this.dirtyDiffController = new DirtyDiffController(this.modelManager),
+ );
}
}
diff --git a/package.json b/package.json
index 8c1b2c401ed..5b4676bf4ae 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"css-loader": "^0.28.0",
"d3": "^3.5.11",
"deckar01-task_list": "^2.0.0",
+ "diff": "^3.4.0",
"document-register-element": "1.3.0",
"dropzone": "^4.2.0",
"emoji-unicode-version": "^0.2.1",
diff --git a/yarn.lock b/yarn.lock
index 73cc4f11500..2050f9eeed7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1895,6 +1895,10 @@ di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
+diff@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c"
+
diffie-hellman@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"