mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Allow unstaged files to be reverted
This commit is contained in:
parent
604e3068b2
commit
bb59cd5742
@ -72,8 +72,9 @@
|
|||||||
"abort-merge":"Git merge aborted",
|
"abort-merge":"Git merge aborted",
|
||||||
"loaded":"Project '"+msg.project+"' loaded",
|
"loaded":"Project '"+msg.project+"' loaded",
|
||||||
"updated":"Project '"+msg.project+"' updated",
|
"updated":"Project '"+msg.project+"' updated",
|
||||||
"pull":"Project '"+msg.project+"' reloaded"
|
"pull":"Project '"+msg.project+"' reloaded",
|
||||||
}[msg.action]
|
"revert": "Project '"+msg.project+"' reloaded"
|
||||||
|
}[msg.action];
|
||||||
RED.notify(message);
|
RED.notify(message);
|
||||||
RED.sidebar.info.refresh()
|
RED.sidebar.info.refresh()
|
||||||
});
|
});
|
||||||
|
@ -134,6 +134,7 @@ RED.projects.settings = (function() {
|
|||||||
},
|
},
|
||||||
200: function(data) {
|
200: function(data) {
|
||||||
done(null,data);
|
done(null,data);
|
||||||
|
RED.sidebar.versionControl.refresh(true);
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
'unexpected_error': function(error) {
|
'unexpected_error': function(error) {
|
||||||
@ -197,6 +198,7 @@ RED.projects.settings = (function() {
|
|||||||
done(error,null);
|
done(error,null);
|
||||||
},
|
},
|
||||||
200: function(data) {
|
200: function(data) {
|
||||||
|
RED.sidebar.versionControl.refresh(true);
|
||||||
done(null,data);
|
done(null,data);
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
@ -326,6 +328,7 @@ RED.projects.settings = (function() {
|
|||||||
done(error,null);
|
done(error,null);
|
||||||
},
|
},
|
||||||
200: function(data) {
|
200: function(data) {
|
||||||
|
RED.sidebar.versionControl.refresh(true);
|
||||||
done(null,data);
|
done(null,data);
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
@ -900,6 +903,7 @@ RED.projects.settings = (function() {
|
|||||||
},
|
},
|
||||||
200: function(data) {
|
200: function(data) {
|
||||||
activeProject = data;
|
activeProject = data;
|
||||||
|
RED.sidebar.versionControl.refresh(true);
|
||||||
updateForm();
|
updateForm();
|
||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,82 @@ RED.sidebar.versionControl = (function() {
|
|||||||
|
|
||||||
var isMerging;
|
var isMerging;
|
||||||
|
|
||||||
// TODO: DRY projectSummary.js
|
function viewFileDiff(entry,state) {
|
||||||
|
var activeProject = RED.projects.getActiveProject();
|
||||||
|
var diffTarget = (state === 'staged')?"index":"tree";
|
||||||
|
utils.sendRequest({
|
||||||
|
url: "projects/"+activeProject.name+"/diff/"+diffTarget+"/"+encodeURIComponent(entry.file),
|
||||||
|
type: "GET",
|
||||||
|
responses: {
|
||||||
|
0: function(error) {
|
||||||
|
console.log(error);
|
||||||
|
// done(error,null);
|
||||||
|
},
|
||||||
|
200: function(data) {
|
||||||
|
if (mergeConflictNotification) {
|
||||||
|
mergeConflictNotification.close();
|
||||||
|
mergeConflictNotification = null;
|
||||||
|
}
|
||||||
|
var title;
|
||||||
|
if (state === 'unstaged') {
|
||||||
|
title = 'Unstaged changes : '+entry.file
|
||||||
|
} else if (state === 'staged') {
|
||||||
|
title = 'Staged changes : '+entry.file
|
||||||
|
} else {
|
||||||
|
title = 'Resolve conflicts : '+entry.file
|
||||||
|
}
|
||||||
|
var options = {
|
||||||
|
diff: data.diff,
|
||||||
|
title: title,
|
||||||
|
unmerged: state === 'unmerged',
|
||||||
|
project: activeProject
|
||||||
|
}
|
||||||
|
if (state == 'unstaged') {
|
||||||
|
options.oldRevTitle = entry.indexStatus === " "?"HEAD":"Staged";
|
||||||
|
options.newRevTitle = "Unstaged";
|
||||||
|
options.oldRev = entry.indexStatus === " "?"@":":0";
|
||||||
|
options.newRev = "_";
|
||||||
|
} else if (state === 'staged') {
|
||||||
|
options.oldRevTitle = "HEAD";
|
||||||
|
options.newRevTitle = "Staged";
|
||||||
|
options.oldRev = "@";
|
||||||
|
options.newRev = ":0";
|
||||||
|
} else {
|
||||||
|
options.onresolve = function(resolution) {
|
||||||
|
utils.sendRequest({
|
||||||
|
url: "projects/"+activeProject.name+"/resolve/"+encodeURIComponent(entry.file),
|
||||||
|
type: "POST",
|
||||||
|
responses: {
|
||||||
|
0: function(error) {
|
||||||
|
console.log(error);
|
||||||
|
// done(error,null);
|
||||||
|
},
|
||||||
|
200: function(data) {
|
||||||
|
refresh(true);
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
'unexpected_error': function(error) {
|
||||||
|
console.log(error);
|
||||||
|
// done(error,null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},{resolutions:resolution.resolutions[entry.file]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options.oncancel = showMergeConflictNotification;
|
||||||
|
RED.diff.showUnifiedDiff(options);
|
||||||
|
// console.log(data.diff);
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
'unexpected_error': function(error) {
|
||||||
|
console.log(error);
|
||||||
|
// done(error,null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function createChangeEntry(row, entry, status, state) {
|
function createChangeEntry(row, entry, status, state) {
|
||||||
row.addClass("sidebar-version-control-change-entry");
|
row.addClass("sidebar-version-control-change-entry");
|
||||||
@ -52,88 +127,67 @@ RED.sidebar.versionControl = (function() {
|
|||||||
|
|
||||||
|
|
||||||
var icon = $('<i class=""></i>').appendTo(container);
|
var icon = $('<i class=""></i>').appendTo(container);
|
||||||
var label = $('<span>').appendTo(container);
|
var entryLink = $('<a href="#">')
|
||||||
|
.appendTo(container)
|
||||||
|
.click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
viewFileDiff(entry,state);
|
||||||
|
});
|
||||||
|
var label = $('<span>').appendTo(entryLink);
|
||||||
|
|
||||||
var bg = $('<div class="button-group"></div>').appendTo(row);
|
var entryTools = $('<div class="sidebar-version-control-change-entry-tools">').appendTo(row);
|
||||||
var viewDiffButton = $('<button class="editor-button editor-button-small"><i class="fa fa-'+(state==='unmerged'?'columns':'eye')+'"></i></button>')
|
var bg;
|
||||||
.appendTo(bg)
|
var revertButton;
|
||||||
.click(function(evt) {
|
if (state === 'unstaged') {
|
||||||
evt.preventDefault();
|
bg = $('<span class="button-group" style="margin-right: 5px;"></span>').appendTo(entryTools);
|
||||||
var activeProject = RED.projects.getActiveProject();
|
revertButton = $('<button class="editor-button editor-button-small"><i class="fa fa-reply"></i></button>')
|
||||||
var diffTarget = (state === 'staged')?"index":"tree";
|
.appendTo(bg)
|
||||||
utils.sendRequest({
|
.click(function(evt) {
|
||||||
url: "projects/"+activeProject.name+"/diff/"+diffTarget+"/"+encodeURIComponent(entry.file),
|
evt.preventDefault();
|
||||||
type: "GET",
|
var spinner = utils.addSpinnerOverlay(container).addClass('projects-dialog-spinner-contain');
|
||||||
responses: {
|
var notification = RED.notify("Are you sure you want to revert the changes to '"+entry.file+"'? This cannot be undone.", {
|
||||||
0: function(error) {
|
type: "warning",
|
||||||
console.log(error);
|
modal: true,
|
||||||
// done(error,null);
|
fixed: true,
|
||||||
},
|
buttons: [
|
||||||
200: function(data) {
|
{
|
||||||
if (mergeConflictNotification) {
|
text: RED._("common.label.cancel"),
|
||||||
mergeConflictNotification.close();
|
click: function() {
|
||||||
mergeConflictNotification = null;
|
spinner.remove();
|
||||||
}
|
notification.close();
|
||||||
var title;
|
}
|
||||||
if (state === 'unstaged') {
|
},{
|
||||||
title = 'Unstaged changes : '+entry.file
|
text: 'Revert changes',
|
||||||
} else if (state === 'staged') {
|
click: function() {
|
||||||
title = 'Staged changes : '+entry.file
|
notification.close();
|
||||||
} else {
|
var activeProject = RED.projects.getActiveProject();
|
||||||
title = 'Resolve conflicts : '+entry.file
|
var url = "projects/"+activeProject.name+"/files/_/"+entry.file;
|
||||||
}
|
var options = {
|
||||||
var options = {
|
url: url,
|
||||||
diff: data.diff,
|
type: "DELETE",
|
||||||
title: title,
|
|
||||||
unmerged: state === 'unmerged',
|
|
||||||
project: activeProject
|
|
||||||
}
|
|
||||||
if (state == 'unstaged') {
|
|
||||||
options.oldRevTitle = entry.indexStatus === " "?"HEAD":"Staged";
|
|
||||||
options.newRevTitle = "Unstaged";
|
|
||||||
options.oldRev = entry.indexStatus === " "?"@":":0";
|
|
||||||
options.newRev = "_";
|
|
||||||
} else if (state === 'staged') {
|
|
||||||
options.oldRevTitle = "HEAD";
|
|
||||||
options.newRevTitle = "Staged";
|
|
||||||
options.oldRev = "@";
|
|
||||||
options.newRev = ":0";
|
|
||||||
} else {
|
|
||||||
options.onresolve = function(resolution) {
|
|
||||||
utils.sendRequest({
|
|
||||||
url: "projects/"+activeProject.name+"/resolve/"+encodeURIComponent(entry.file),
|
|
||||||
type: "POST",
|
|
||||||
responses: {
|
responses: {
|
||||||
0: function(error) {
|
|
||||||
console.log(error);
|
|
||||||
// done(error,null);
|
|
||||||
},
|
|
||||||
200: function(data) {
|
200: function(data) {
|
||||||
refresh(true);
|
spinner.remove();
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
'unexpected_error': function(error) {
|
'unexpected_error': function(error) {
|
||||||
|
spinner.remove();
|
||||||
console.log(error);
|
console.log(error);
|
||||||
// done(error,null);
|
// done(error,null);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
},{resolutions:resolution.resolutions[entry.file]});
|
}
|
||||||
|
utils.sendRequest(options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
options.oncancel = showMergeConflictNotification;
|
|
||||||
RED.diff.showUnifiedDiff(options);
|
]
|
||||||
// console.log(data.diff);
|
})
|
||||||
},
|
|
||||||
400: {
|
});
|
||||||
'unexpected_error': function(error) {
|
}
|
||||||
console.log(error);
|
bg = $('<span class="button-group"></span>').appendTo(entryTools);
|
||||||
// done(error,null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
if (state !== 'unmerged') {
|
if (state !== 'unmerged') {
|
||||||
$('<button class="editor-button editor-button-small"><i class="fa fa-'+((state==='unstaged')?"plus":"minus")+'"></i></button>')
|
$('<button class="editor-button editor-button-small"><i class="fa fa-'+((state==='unstaged')?"plus":"minus")+'"></i></button>')
|
||||||
.appendTo(bg)
|
.appendTo(bg)
|
||||||
@ -203,11 +257,10 @@ RED.sidebar.versionControl = (function() {
|
|||||||
delete entry.spinner;
|
delete entry.spinner;
|
||||||
}
|
}
|
||||||
|
|
||||||
viewDiffButton.attr("disabled",(status === 'D' || status === '?'));
|
if (revertButton) {
|
||||||
viewDiffButton.find("i")
|
revertButton.toggle(status !== '?');
|
||||||
.toggleClass('fa-eye',!(status === 'D' || status === '?'))
|
}
|
||||||
.toggleClass('fa-eye-slash',(status === 'D' || status === '?'))
|
entryLink.toggleClass("disabled",(status === 'D' || status === '?'));
|
||||||
|
|
||||||
}
|
}
|
||||||
entry["update"+((state==='unstaged')?"Unstaged":"Staged")](entry, status);
|
entry["update"+((state==='unstaged')?"Unstaged":"Staged")](entry, status);
|
||||||
}
|
}
|
||||||
|
@ -444,7 +444,13 @@
|
|||||||
span {
|
span {
|
||||||
margin: 0 6px;
|
margin: 0 6px;
|
||||||
}
|
}
|
||||||
.button-group {
|
a {
|
||||||
|
color: currentColor;
|
||||||
|
&.disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sidebar-version-control-change-entry-tools {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
@ -455,7 +461,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.button-group {
|
.sidebar-version-control-change-entry-tools {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,22 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Revert a file
|
||||||
|
app.delete("/:id/files/_/*", needsPermission("projects.write"), function(req,res) {
|
||||||
|
var projectId = req.params.id;
|
||||||
|
var filePath = req.params[0];
|
||||||
|
|
||||||
|
runtime.storage.projects.revertFile(req.user, projectId,filePath).then(function() {
|
||||||
|
res.status(204).end();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.log(err.stack);
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Stage a file
|
// Stage a file
|
||||||
app.post("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
|
app.post("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
|
||||||
var projectName = req.params.id;
|
var projectName = req.params.id;
|
||||||
|
@ -329,6 +329,14 @@ Project.prototype.getFile = function (filePath,treeish) {
|
|||||||
return fs.readFile(fspath.join(this.path,filePath),"utf8");
|
return fs.readFile(fspath.join(this.path,filePath),"utf8");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Project.prototype.revertFile = function (filePath) {
|
||||||
|
var self = this;
|
||||||
|
return gitTools.revertFile(this.path, filePath).then(function() {
|
||||||
|
return self.load();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Project.prototype.status = function(user) {
|
Project.prototype.status = function(user) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -421,6 +421,10 @@ module.exports = {
|
|||||||
return status.files;
|
return status.files;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
revertFile: function(cwd, filePath) {
|
||||||
|
var args = ["checkout",filePath];
|
||||||
|
return runGitCommand(args,cwd);
|
||||||
|
},
|
||||||
stageFile: function(cwd,file) {
|
stageFile: function(cwd,file) {
|
||||||
var args = ["add"];
|
var args = ["add"];
|
||||||
if (Array.isArray(file)) {
|
if (Array.isArray(file)) {
|
||||||
|
@ -173,7 +173,7 @@ function getFileDiff(user, project,file,type) {
|
|||||||
}
|
}
|
||||||
function getCommits(user, project,options) {
|
function getCommits(user, project,options) {
|
||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
return activeProject.getCommits(options);
|
return activeProject.getCommits(options);
|
||||||
}
|
}
|
||||||
function getCommit(user, project,sha) {
|
function getCommit(user, project,sha) {
|
||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
@ -184,6 +184,12 @@ function getFile(user, project,filePath,sha) {
|
|||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
return activeProject.getFile(filePath,sha);
|
return activeProject.getFile(filePath,sha);
|
||||||
}
|
}
|
||||||
|
function revertFile(user, project,filePath) {
|
||||||
|
checkActiveProject(project);
|
||||||
|
return activeProject.revertFile(filePath).then(function() {
|
||||||
|
return reloadActiveProject("revert");
|
||||||
|
})
|
||||||
|
}
|
||||||
function push(user, project,remoteBranchName,setRemote) {
|
function push(user, project,remoteBranchName,setRemote) {
|
||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
return activeProject.push(user,remoteBranchName,setRemote);
|
return activeProject.push(user,remoteBranchName,setRemote);
|
||||||
@ -413,6 +419,7 @@ module.exports = {
|
|||||||
updateProject: updateProject,
|
updateProject: updateProject,
|
||||||
getFiles: getFiles,
|
getFiles: getFiles,
|
||||||
getFile: getFile,
|
getFile: getFile,
|
||||||
|
revertFile: revertFile,
|
||||||
stageFile: stageFile,
|
stageFile: stageFile,
|
||||||
unstageFile: unstageFile,
|
unstageFile: unstageFile,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
|
Loading…
Reference in New Issue
Block a user