mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add delete local branch option
This commit is contained in:
parent
d007623347
commit
27f1d3b704
@ -947,8 +947,132 @@ RED.projects.settings = (function() {
|
|||||||
updateForm();
|
updateForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createLocalBranchListSection(activeProject,pane) {
|
||||||
|
var localBranchContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
|
||||||
|
$('<h4></h4>').text("Branches").appendTo(localBranchContainer);
|
||||||
|
|
||||||
|
var row = $('<div class="user-settings-row projects-dialog-branch-list"></div>').appendTo(localBranchContainer);
|
||||||
|
|
||||||
|
|
||||||
|
var branchList = $('<ol>').appendTo(row).editableList({
|
||||||
|
addButton: false,
|
||||||
|
scrollOnAdd: false,
|
||||||
|
addItem: function(row,index,entry) {
|
||||||
|
var container = $('<div class="projects-dialog-branch-list-entry">').appendTo(row);
|
||||||
|
$('<span><i class="fa fa-code-fork"></i></span>').appendTo(container);
|
||||||
|
$('<span class="branch-name">').text(entry.name).appendTo(container);
|
||||||
|
// if (entry.commit) {
|
||||||
|
// $('<span class="commit">').text(entry.commit.sha).appendTo(container);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (entry.remote) {
|
||||||
|
$('<span class="branch-remote-name">').text(entry.remote||"").appendTo(container);
|
||||||
|
if (entry.status.ahead+entry.status.behind > 0) {
|
||||||
|
$('<span class="branch-remote-status">'+
|
||||||
|
'<i class="fa fa-long-arrow-up"></i> <span>'+entry.status.ahead+'</span> '+
|
||||||
|
'<i class="fa fa-long-arrow-down"></i> <span>'+entry.status.behind+'</span>'+
|
||||||
|
'</span>').appendTo(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tools = $('<span class="projects-dialog-branch-list-entry-tools">').appendTo(container);
|
||||||
|
if (entry.current) {
|
||||||
|
tools.text('current');
|
||||||
|
} else {
|
||||||
|
$('<button class="editor-button editor-button-small">delete</button>')
|
||||||
|
.appendTo(tools)
|
||||||
|
.click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var spinner = utils.addSpinnerOverlay(row).addClass('projects-dialog-spinner-contain');
|
||||||
|
var notification = RED.notify("Are you sure you want to delete the local branch '"+entry.name+"'? This cannot be undone.", {
|
||||||
|
type: "warning",
|
||||||
|
modal: true,
|
||||||
|
fixed: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.cancel"),
|
||||||
|
click: function() {
|
||||||
|
spinner.remove();
|
||||||
|
notification.close();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
text: 'Delete branch',
|
||||||
|
click: function() {
|
||||||
|
notification.close();
|
||||||
|
var url = "projects/"+activeProject.name+"/branches/"+entry.name;
|
||||||
|
var options = {
|
||||||
|
url: url,
|
||||||
|
type: "DELETE",
|
||||||
|
responses: {
|
||||||
|
200: function(data) {
|
||||||
|
row.fadeOut(200,function() {
|
||||||
|
branchList.editableList('removeItem',entry);
|
||||||
|
spinner.remove();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
'git_delete_branch_unmerged': function(error) {
|
||||||
|
notification = RED.notify("The local branch '"+entry.name+"' has unmerged changes that will be lost. Are you sure you want to delete it?", {
|
||||||
|
type: "warning",
|
||||||
|
modal: true,
|
||||||
|
fixed: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: RED._("common.label.cancel"),
|
||||||
|
click: function() {
|
||||||
|
spinner.remove();
|
||||||
|
notification.close();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
text: 'Delete unmerged branch',
|
||||||
|
click: function() {
|
||||||
|
options.url += "?force=true";
|
||||||
|
notification.close();
|
||||||
|
utils.sendRequest(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
},
|
||||||
|
'unexpected_error': function(error) {
|
||||||
|
console.log(error);
|
||||||
|
spinner.remove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
utils.sendRequest(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$.getJSON("projects/"+activeProject.name+"/branches",function(result) {
|
||||||
|
if (result.branches) {
|
||||||
|
result.branches.sort(function(A,B) {
|
||||||
|
if (A.current) { return -1 }
|
||||||
|
if (B.current) { return 1 }
|
||||||
|
return A.name.localeCompare(B.name);
|
||||||
|
});
|
||||||
|
result.branches.forEach(function(branch) {
|
||||||
|
branchList.editableList('addItem',branch);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
function createRemoteRepositorySection(activeProject,pane) {
|
function createRemoteRepositorySection(activeProject,pane) {
|
||||||
var title = $('<h3></h3>').text("Version Control").appendTo(pane);
|
$('<h3></h3>').text("Version Control").appendTo(pane);
|
||||||
|
|
||||||
|
createLocalBranchListSection(activeProject,pane);
|
||||||
|
|
||||||
|
var repoContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
|
||||||
|
var title = $('<h4></h4>').text("Git remotes").appendTo(repoContainer);
|
||||||
|
|
||||||
var editRepoButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
|
var editRepoButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>')
|
||||||
.appendTo(title)
|
.appendTo(title)
|
||||||
.click(function(evt) {
|
.click(function(evt) {
|
||||||
@ -959,8 +1083,8 @@ RED.projects.settings = (function() {
|
|||||||
remoteListAddButton.show();
|
remoteListAddButton.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
var repoContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
|
|
||||||
var grTitle = $('<h4></h4>').text("Git remotes").appendTo(repoContainer);
|
|
||||||
|
|
||||||
row = $('<div class="user-settings-row projects-dialog-remote-list"></div>').appendTo(repoContainer);
|
row = $('<div class="user-settings-row projects-dialog-remote-list"></div>').appendTo(repoContainer);
|
||||||
var remotesList = $('<ol>').appendTo(row);
|
var remotesList = $('<ol>').appendTo(row);
|
||||||
|
@ -676,3 +676,44 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.projects-dialog-branch-list {
|
||||||
|
.red-ui-editableList-container li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.projects-dialog-branch-list-entry {
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
span:first-child {
|
||||||
|
text-align: center;
|
||||||
|
min-width: 30px;
|
||||||
|
}
|
||||||
|
.branch-name {
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
.branch-remote-name {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 0.9em;
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
.branch-remote-status {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
.commit {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 2px 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.projects-dialog-branch-list-entry-tools {
|
||||||
|
float: right;
|
||||||
|
margin-right: 20px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -115,7 +115,7 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
// Delete project - tbd
|
// Delete project
|
||||||
app.delete("/:id", needsPermission("projects.write"), function(req,res) {
|
app.delete("/:id", needsPermission("projects.write"), function(req,res) {
|
||||||
runtime.storage.projects.deleteProject(req.user, req.params.id).then(function() {
|
runtime.storage.projects.deleteProject(req.user, req.params.id).then(function() {
|
||||||
res.status(204).end();
|
res.status(204).end();
|
||||||
@ -373,6 +373,23 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Delete a local branch - ?force=true
|
||||||
|
app.delete("/:id/branches/:branchName", needsPermission("projects.write"), function(req, res) {
|
||||||
|
var projectName = req.params.id;
|
||||||
|
var branchName = req.params.branchName;
|
||||||
|
var force = !!req.query.force;
|
||||||
|
runtime.storage.projects.deleteBranch(req.user, projectName, branchName, false, force).then(function(data) {
|
||||||
|
res.status(204).end();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
if (err.code) {
|
||||||
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
|
} else {
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Get a list of remote branches
|
// Get a list of remote branches
|
||||||
app.get("/:id/branches/remote", needsPermission("projects.read"), function(req, res) {
|
app.get("/:id/branches/remote", needsPermission("projects.read"), function(req, res) {
|
||||||
var projectName = req.params.id;
|
var projectName = req.params.id;
|
||||||
@ -380,7 +397,6 @@ module.exports = {
|
|||||||
res.json(data);
|
res.json(data);
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
console.log(err.stack);
|
|
||||||
if (err.code) {
|
if (err.code) {
|
||||||
res.status(400).json({error:err.code, message: err.message});
|
res.status(400).json({error:err.code, message: err.message});
|
||||||
} else {
|
} else {
|
||||||
|
@ -234,7 +234,7 @@ Project.prototype.update = function (user, data) {
|
|||||||
if (data.git.hasOwnProperty('remotes')) {
|
if (data.git.hasOwnProperty('remotes')) {
|
||||||
var remoteNames = Object.keys(data.git.remotes);
|
var remoteNames = Object.keys(data.git.remotes);
|
||||||
var remotesChanged = false;
|
var remotesChanged = false;
|
||||||
var modifyRemotesPromise = when.resolve();
|
var modifyRemotesPromise = Promise.resolve();
|
||||||
remoteNames.forEach(function(name) {
|
remoteNames.forEach(function(name) {
|
||||||
if (data.git.remotes[name].removed) {
|
if (data.git.remotes[name].removed) {
|
||||||
remotesChanged = true;
|
remotesChanged = true;
|
||||||
@ -348,7 +348,7 @@ Project.prototype.status = function(user) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
fetchPromise = when.resolve();
|
fetchPromise = Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
var completeStatus = function(fetchError) {
|
var completeStatus = function(fetchError) {
|
||||||
@ -461,18 +461,23 @@ Project.prototype.getBranches = function (user, isRemote) {
|
|||||||
if (isRemote) {
|
if (isRemote) {
|
||||||
fetchPromise = self.fetch(user);
|
fetchPromise = self.fetch(user);
|
||||||
} else {
|
} else {
|
||||||
fetchPromise = when.resolve();
|
fetchPromise = Promise.resolve();
|
||||||
}
|
}
|
||||||
return fetchPromise.then(function() {
|
return fetchPromise.then(function() {
|
||||||
return gitTools.getBranches(self.path,isRemote);
|
return gitTools.getBranches(self.path,isRemote);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Project.prototype.deleteBranch = function (user, branch, isRemote, force) {
|
||||||
|
// TODO: isRemote==true support
|
||||||
|
// TODO: make sure we don't try to delete active branch
|
||||||
|
return gitTools.deleteBranch(this.path,branch,isRemote, force);
|
||||||
|
};
|
||||||
|
|
||||||
Project.prototype.fetch = function(user,remoteName) {
|
Project.prototype.fetch = function(user,remoteName) {
|
||||||
var username;
|
var username;
|
||||||
if (!user) {
|
if (!user) {
|
||||||
username = "_";
|
username = "_";
|
||||||
console.log(new Error().stack);
|
|
||||||
} else {
|
} else {
|
||||||
username = user.username;
|
username = user.username;
|
||||||
}
|
}
|
||||||
@ -484,7 +489,7 @@ Project.prototype.fetch = function(user,remoteName) {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
var remotes = Object.keys(this.remotes);
|
var remotes = Object.keys(this.remotes);
|
||||||
var promise = when.resolve();
|
var promise = Promise.resolve();
|
||||||
remotes.forEach(function(remote) {
|
remotes.forEach(function(remote) {
|
||||||
promise = promise.then(function() {
|
promise = promise.then(function() {
|
||||||
return gitTools.fetch(project.path,remote,authCache.get(project.name,project.remotes[remote].fetch,username))
|
return gitTools.fetch(project.path,remote,authCache.get(project.name,project.remotes[remote].fetch,username))
|
||||||
@ -661,7 +666,7 @@ function createProject(user, metadata) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var project = metadata.name;
|
var project = metadata.name;
|
||||||
return when.promise(function(resolve,reject) {
|
return new Promise(function(resolve,reject) {
|
||||||
var projectPath = fspath.join(projectsDir,project);
|
var projectPath = fspath.join(projectsDir,project);
|
||||||
fs.stat(projectPath, function(err,stat) {
|
fs.stat(projectPath, function(err,stat) {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
@ -55,10 +55,9 @@ function runGitCommand(args,cwd,env) {
|
|||||||
err.code = "git_local_overwrite";
|
err.code = "git_local_overwrite";
|
||||||
} else if (/CONFLICT/.test(err.stdout)) {
|
} else if (/CONFLICT/.test(err.stdout)) {
|
||||||
err.code = "git_pull_merge_conflict";
|
err.code = "git_pull_merge_conflict";
|
||||||
|
} else if (/not fully merged/.test(stderr)) {
|
||||||
|
err.code = "git_delete_branch_unmerged";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
resolve(stdout);
|
resolve(stdout);
|
||||||
@ -276,8 +275,7 @@ function getBranches(cwd, remote) {
|
|||||||
if (remote) {
|
if (remote) {
|
||||||
args.push('-r');
|
args.push('-r');
|
||||||
}
|
}
|
||||||
//TODO: parse out ahead/behind status (currently m[5] vvv )
|
var branchRE = /^([ \*] )(\S+) +(\S+)(?: \[(\S+?)(?:: (?:ahead (\d+)(?:, )?)?(?:behind (\d+))?)?\])? (.*)$/;
|
||||||
var branchRE = /^([ \*] )(\S+) +(\S+)(?: \[(\S+?)(?:: (.*))?\])? (.*)$/;
|
|
||||||
return runGitCommand(args,cwd).then(function(output) {
|
return runGitCommand(args,cwd).then(function(output) {
|
||||||
var branches = [];
|
var branches = [];
|
||||||
var lines = output.split("\n");
|
var lines = output.split("\n");
|
||||||
@ -288,10 +286,13 @@ function getBranches(cwd, remote) {
|
|||||||
branch = {
|
branch = {
|
||||||
name: m[2],
|
name: m[2],
|
||||||
remote: m[4],
|
remote: m[4],
|
||||||
status: m[5],
|
status: {
|
||||||
|
ahead: m[5]||0,
|
||||||
|
behind: m[6]||0,
|
||||||
|
},
|
||||||
commit: {
|
commit: {
|
||||||
sha: m[3],
|
sha: m[3],
|
||||||
subject: m[6]
|
subject: m[7]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m[1] === '* ') {
|
if (m[1] === '* ') {
|
||||||
@ -516,6 +517,19 @@ module.exports = {
|
|||||||
args.push(branchName);
|
args.push(branchName);
|
||||||
return runGitCommand(args,cwd);
|
return runGitCommand(args,cwd);
|
||||||
},
|
},
|
||||||
|
deleteBranch: function(cwd, branchName, isRemote, force) {
|
||||||
|
if (isRemote) {
|
||||||
|
throw new Error("Deleting remote branches not supported");
|
||||||
|
}
|
||||||
|
var args = ['branch'];
|
||||||
|
if (force) {
|
||||||
|
args.push('-D');
|
||||||
|
} else {
|
||||||
|
args.push('-d');
|
||||||
|
}
|
||||||
|
args.push(branchName);
|
||||||
|
return runGitCommand(args, cwd);
|
||||||
|
},
|
||||||
getBranchStatus: getBranchStatus,
|
getBranchStatus: getBranchStatus,
|
||||||
addRemote: addRemote,
|
addRemote: addRemote,
|
||||||
removeRemote: removeRemote
|
removeRemote: removeRemote
|
||||||
|
@ -212,6 +212,12 @@ function getBranches(user, project,isRemote) {
|
|||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
return activeProject.getBranches(user, isRemote);
|
return activeProject.getBranches(user, isRemote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteBranch(user, project, branch, isRemote, force) {
|
||||||
|
checkActiveProject(project);
|
||||||
|
return activeProject.deleteBranch(user, branch, isRemote, force);
|
||||||
|
}
|
||||||
|
|
||||||
function setBranch(user, project,branchName,isCreate) {
|
function setBranch(user, project,branchName,isCreate) {
|
||||||
checkActiveProject(project);
|
checkActiveProject(project);
|
||||||
return activeProject.setBranch(branchName,isCreate).then(function() {
|
return activeProject.setBranch(branchName,isCreate).then(function() {
|
||||||
@ -419,6 +425,7 @@ module.exports = {
|
|||||||
resolveMerge: resolveMerge,
|
resolveMerge: resolveMerge,
|
||||||
abortMerge: abortMerge,
|
abortMerge: abortMerge,
|
||||||
getBranches: getBranches,
|
getBranches: getBranches,
|
||||||
|
deleteBranch: deleteBranch,
|
||||||
setBranch: setBranch,
|
setBranch: setBranch,
|
||||||
getBranchStatus:getBranchStatus,
|
getBranchStatus:getBranchStatus,
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user