1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add unified diff view to version control tab

This commit is contained in:
Nick O'Leary 2017-10-09 00:11:07 +01:00
parent 51bad3bf3c
commit 10567afbb9
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
6 changed files with 185 additions and 14 deletions

View File

@ -1471,7 +1471,7 @@ RED.diff = (function() {
} }
currentBlock.end = diffLength; currentBlock.end = diffLength;
diffBlocks.push(currentBlock); diffBlocks.push(currentBlock);
console.table(diffBlocks); // console.table(diffBlocks);
var diffRow; var diffRow;
for (var b = 0; b<diffBlocks.length; b++) { for (var b = 0; b<diffBlocks.length; b++) {
currentBlock = diffBlocks[b]; currentBlock = diffBlocks[b];
@ -1502,7 +1502,7 @@ console.table(diffBlocks);
} }
function createExpandLine(start,end,diffLines) { function createExpandLine(start,end,diffLines) {
diffRow = $('<tr class="node-text-diff-expand">'); diffRow = $('<tr class="node-text-diff-header node-text-diff-expand">');
var content = $('<td colspan="4"> <i class="fa fa-arrows-v"></i> </td>').appendTo(diffRow); var content = $('<td colspan="4"> <i class="fa fa-arrows-v"></i> </td>').appendTo(diffRow);
var label = $('<span></span>').appendTo(content); var label = $('<span></span>').appendTo(content);
if (end < diffLines.length-1) { if (end < diffLines.length-1) {
@ -1546,8 +1546,8 @@ console.table(diffBlocks);
var Adiff = diffLine.a; var Adiff = diffLine.a;
var Bdiff = diffLine.b; var Bdiff = diffLine.b;
//console.log(diffLine); //console.log(diffLine);
var cellNo = $("<td>").text(Adiff.type === 2?"":Adiff.i).appendTo(diffRow); var cellNo = $('<td class="lineno">').text(Adiff.type === 2?"":Adiff.i).appendTo(diffRow);
var cellLine = $("<td>").text(Adiff.line).appendTo(diffRow); var cellLine = $('<td class="linetext">').text(Adiff.line).appendTo(diffRow);
if (Adiff.type === 2) { if (Adiff.type === 2) {
cellNo.addClass('blank'); cellNo.addClass('blank');
cellLine.addClass('blank'); cellLine.addClass('blank');
@ -1558,8 +1558,8 @@ console.table(diffBlocks);
cellNo.addClass('removed'); cellNo.addClass('removed');
cellLine.addClass('removed'); cellLine.addClass('removed');
} }
cellNo = $("<td>").text(Bdiff.type === 2?"":Bdiff.i).appendTo(diffRow); cellNo = $('<td class="lineno">').text(Bdiff.type === 2?"":Bdiff.i).appendTo(diffRow);
cellLine = $("<td>").text(Bdiff.line).appendTo(diffRow); cellLine = $('<td class="linetext">').text(Bdiff.line).appendTo(diffRow);
if (Bdiff.type === 2) { if (Bdiff.type === 2) {
cellNo.addClass('blank'); cellNo.addClass('blank');
cellLine.addClass('blank'); cellLine.addClass('blank');
@ -1646,13 +1646,115 @@ console.table(diffBlocks);
return string1 === string2 ? 0 : 1; return string1 === string2 ? 0 : 1;
} }
function showUnifiedDiff(diff,title) {
var hunks = parseUnifiedDiff(diff);
var trayOptions = {
title: title||"Compare Changes", //TODO: nls
width: Infinity,
overlay: true,
buttons: [
{
text: RED._("common.label.done"),
click: function() {
RED.tray.close();
}
}
],
resize: function(dimensions) {
// trayWidth = dimensions.width;
},
open: function(tray) {
var trayBody = tray.find('.editor-tray-body');
var diffPanel = $('<div class="node-text-diff"></div>').appendTo(trayBody);
var codeTable = $("<table>").appendTo(diffPanel);
$('<colgroup><col width="50"><col width="50"><col width="100%"></colgroup>').appendTo(codeTable);
var codeBody = $('<tbody>').appendTo(codeTable);
for (var i=0;i<hunks.length;i++) {
var diffRow = $('<tr class="node-text-diff-header">').appendTo(codeBody);
var content = $('<td colspan="3"></td>').appendTo(diffRow);
var label = $('<span></span>').text(hunks[i].header).appendTo(content);
var localLine = hunks[i].localStartLine;
var remoteLine = hunks[i].remoteStartLine;
for (var j=0;j<hunks[i].lines.length;j++) {
var lineText = hunks[i].lines[j];
diffRow = $('<tr>').appendTo(codeBody);
var localLineNo = $('<td class="lineno">').appendTo(diffRow);
var remoteLineNo = $('<td class="lineno">').appendTo(diffRow);
var line = $('<td class="linetext">').appendTo(diffRow);
$('<span class="prefix">').text(lineText[0]).appendTo(line);
$('<span>').text(lineText.substring(1)).appendTo(line);
if (lineText[0] === '+') {
line.addClass("added");
remoteLineNo.text(remoteLine++);
} else if (lineText[0] === '-') {
line.addClass("removed");
localLineNo.text(localLine++);
} else {
line.addClass("unchanged");
localLineNo.text(localLine++);
remoteLineNo.text(remoteLine++);
}
}
}
},
close: function() {
diffVisible = false;
},
show: function() {
}
}
RED.tray.show(trayOptions);
}
function parseUnifiedDiff(diff) {
var lines = diff.split("\n");
var hunks = [];
var inHunk = false;
var currentHunk;
var hunkHeader = /^@@ -((\d+)(,(\d+))?) \+((\d+)(,(\d+))?) @@ ?(.*)$/;
var comment = /^\\/;
var localChange = /^-/;
var remoteChange = /^\+/;
for (var i=0;i<lines.length;i++) {
var hunkLine = hunkHeader.exec(lines[i]);
if (hunkLine) {
if (inHunk) {
hunks.push(currentHunk);
}
currentHunk = {
header: lines[i],
localStartLine: hunkLine[2],
localLength: hunkLine[4]||1,
remoteStartLine: hunkLine[6],
remoteLength: hunkLine[8]||1,
lines: []
}
inHunk = true;
} else if (inHunk) {
currentHunk.lines.push(lines[i]);
}
}
if (currentHunk) {
hunks.push(currentHunk);
}
return hunks;
}
return { return {
init: init, init: init,
getRemoteDiff: getRemoteDiff, getRemoteDiff: getRemoteDiff,
showRemoteDiff: showRemoteDiff, showRemoteDiff: showRemoteDiff,
showUnifiedDiff: showUnifiedDiff,
mergeDiff: mergeDiff mergeDiff: mergeDiff
} }
})(); })();

View File

@ -41,7 +41,33 @@ RED.sidebar.versionControl = (function() {
var label = $('<span>').appendTo(container); var label = $('<span>').appendTo(container);
var bg = $('<div class="button-group"></div>').appendTo(row); var bg = $('<div class="button-group"></div>').appendTo(row);
$('<button class="editor-button editor-button-small"><i class="fa fa-eye"></i></button>').appendTo(bg); $('<button class="editor-button editor-button-small"><i class="fa fa-eye"></i></button>')
.appendTo(bg)
.click(function(evt) {
evt.preventDefault();
var activeProject = RED.projects.getActiveProject();
utils.sendRequest({
url: "projects/"+activeProject.name+"/diff/"+(unstaged?"tree":"index")+"/"+encodeURIComponent(entry.file),
type: "GET",
responses: {
0: function(error) {
console.log(error);
// done(error,null);
},
200: function(data) {
RED.diff.showUnifiedDiff(data.diff,(unstaged?"Unstaged":"Staged")+" changes : "+entry.file);
// console.log(data.diff);
},
400: {
'unexpected_error': function(error) {
console.log(error);
// done(error,null);
}
},
}
})
})
$('<button class="editor-button editor-button-small"><i class="fa fa-'+(unstaged?"plus":"minus")+'"></i></button>') $('<button class="editor-button editor-button-small"><i class="fa fa-'+(unstaged?"plus":"minus")+'"></i></button>')
.appendTo(bg) .appendTo(bg)
.click(function(evt) { .click(function(evt) {

View File

@ -561,18 +561,24 @@
vertical-align: top; vertical-align: top;
word-wrap: break-word; word-wrap: break-word;
} }
td:nth-child(odd) { td.lineno {
text-align: right; text-align: right;
color: #999; color: #999;
background: #fafafa; background: #fafafa;
padding: 1px 5px; padding: 1px 5px;
} }
td:nth-child(3) { td.lineno:nth-child(3) {
border-left: 1px solid $secondary-border-color; border-left: 1px solid $secondary-border-color;
} }
td:nth-child(even) { td.linetext {
white-space: pre-wrap; white-space: pre-wrap;
padding: 1px 5px; padding: 1px 5px;
span.prefix {
width: 30px;
display: inline-block;
text-align: center;
color: #999;
}
} }
td.blank { td.blank {
background: #f6f6f6; background: #f6f6f6;
@ -583,21 +589,28 @@
td.removed { td.removed {
background: #fadddd; background: #fadddd;
} }
td.unchanged {
color: #999;
}
tr.unchanged { tr.unchanged {
background: #fefefe; background: #fefefe;
} }
tr.start-block { tr.start-block {
border-top: 1px solid #f3f3f3; border-top: 1px solid #f0f0f0;
} }
tr.end-block { tr.end-block {
border-bottom: 1px solid #f3f3f3; border-bottom: 1px solid #f0f0f0;
} }
tr.node-text-diff-expand td { tr.node-text-diff-header td {
text-align: left; text-align: left;
color: #999; color: #999;
background: #ffd; background: #ffd;
height: 30px;
vertical-align: middle;
}
tr.node-text-diff-expand td {
cursor: pointer;
&:hover { &:hover {
cursor: pointer;
background: #ffc; background: #ffc;
} }
} }

View File

@ -188,6 +188,21 @@ module.exports = {
}) })
}); });
app.get(/([^\/]+)\/diff\/([^\/]+)\/(.+)$/, function(req,res) {
var projectName = req.params[0];
var type = req.params[1];
var file = req.params[2];
runtime.storage.projects.getFileDiff(projectName,file,type).then(function(data) {
res.json({
diff: data
})
})
.catch(function(err) {
console.log(err.stack);
res.status(400).json({error:"unexpected_error", message:err.toString()});
})
});
app.get(new RegExp("/([^\/]+)\/files\/(.*)"), function(req,res) { app.get(new RegExp("/([^\/]+)\/files\/(.*)"), function(req,res) {
// Get project file // Get project file
}); });

View File

@ -209,5 +209,15 @@ module.exports = {
commit: function(cwd, message) { commit: function(cwd, message) {
var args = ["commit","-m",message]; var args = ["commit","-m",message];
return runCommand(gitCommand,args,cwd); return runCommand(gitCommand,args,cwd);
},
getFileDiff(cwd,file,type) {
var args = ["diff"];
if (type === "tree") {
// nothing else to do
} else if (type === "index") {
args.push("--cached");
}
args.push(file);
return runCommand(gitCommand,args,cwd);
} }
} }

View File

@ -351,6 +351,10 @@ function commit(project,options) {
var projectPath = fspath.join(projectsDir,project); var projectPath = fspath.join(projectsDir,project);
return gitTools.commit(projectPath,options.message); return gitTools.commit(projectPath,options.message);
} }
function getFileDiff(project,file,type) {
var projectPath = fspath.join(projectsDir,project);
return gitTools.getFileDiff(projectPath,file,type);
}
function getFile(project,path) { function getFile(project,path) {
} }
@ -507,6 +511,7 @@ module.exports = {
stageFile: stageFile, stageFile: stageFile,
unstageFile: unstageFile, unstageFile: unstageFile,
commit: commit, commit: commit,
getFileDiff: getFileDiff,
getFlows: getFlows, getFlows: getFlows,
saveFlows: saveFlows, saveFlows: saveFlows,