mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Allow committer details to be set per-user
This commit is contained in:
		| @@ -68,7 +68,7 @@ | ||||
|                                     console.log(msg); | ||||
|                                     var project = RED.projects.getActiveProject(); | ||||
|                                     var message = { | ||||
|                                         "change-branch":"Change to local branch '"+project.branches.local+"'", | ||||
|                                         "change-branch":"Change to local branch '"+project.git.branches.local+"'", | ||||
|                                         "abort-merge":"Git merge aborted", | ||||
|                                         "loaded":"Project '"+msg.project+"' loaded", | ||||
|                                         "updated":"Project '"+msg.project+"' updated", | ||||
|   | ||||
| @@ -75,7 +75,7 @@ | ||||
|                         addLabel = 'add'; | ||||
|                     } | ||||
|                 } | ||||
|                 $('<a href="#" class="editor-button editor-button-small" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>') | ||||
|                 $('<a href="#" class="editor-button editor-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>') | ||||
|                     .appendTo(this.topContainer) | ||||
|                     .click(function(evt) { | ||||
|                         evt.preventDefault(); | ||||
|   | ||||
| @@ -60,6 +60,7 @@ RED.projects.settings = (function() { | ||||
|             }, | ||||
|             open: function(tray) { | ||||
|                 var project = RED.projects.getActiveProject(); | ||||
|  | ||||
|                 var trayBody = tray.find('.editor-tray-body'); | ||||
|                 var settingsContent = $('<div></div>').appendTo(trayBody); | ||||
|                 var tabContainer = $('<div></div>',{id:"user-settings-tabs-container"}).appendTo(settingsContent); | ||||
| @@ -148,7 +149,12 @@ RED.projects.settings = (function() { | ||||
|     } | ||||
|     function updateProjectDescription(activeProject, container) { | ||||
|         container.empty(); | ||||
|         var desc = marked(activeProject.description||""); | ||||
|         var desc; | ||||
|         if (activeProject.description) { | ||||
|             desc = marked(activeProject.description); | ||||
|         } else { | ||||
|             desc = '<span class="node-info-none">'+'No description available'+'</span>'; | ||||
|         } | ||||
|         var description = addTargetToExternalLinks($('<span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(desc)+'">'+desc+'</span>')).appendTo(container); | ||||
|         description.find(".bidiAware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" ); | ||||
|     } | ||||
| @@ -280,7 +286,7 @@ RED.projects.settings = (function() { | ||||
|             } | ||||
|         } | ||||
|         if (unknownCount > 0) { | ||||
|             depsList.editableList('addItem',{index:1, label:"Unknown Dependencies"}); // TODO: nls | ||||
|             depsList.editableList('addItem',{index:1, label:"Unlisted dependencies"}); // TODO: nls | ||||
|         } | ||||
|         if (unusedCount > 0) { | ||||
|             depsList.editableList('addItem',{index:3, label:"Unused dependencies"}); // TODO: nls | ||||
| @@ -418,15 +424,18 @@ RED.projects.settings = (function() { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function showProjectFileListing(row,activeProject,current,done) { | ||||
|     function showProjectFileListing(row,activeProject,current,filter,done) { | ||||
|         var dialog; | ||||
|         var dialogBody; | ||||
|         var filesList; | ||||
|         var selected; | ||||
|         var container = $('<div class="project-file-listing-container"></div>',{style:"position: relative; min-height: 175px; height: 175px;"}).hide().appendTo(row); | ||||
|         var spinner = utils.addSpinnerOverlay(container); | ||||
|         $.getJSON("/projects/"+activeProject.name+"/files",function(result) { | ||||
|         $.getJSON("projects/"+activeProject.name+"/files",function(result) { | ||||
|             var fileNames = Object.keys(result); | ||||
|             fileNames = fileNames.filter(function(fn) { | ||||
|                 return !result[fn].status || !/D/.test(result[fn].status); | ||||
|             }) | ||||
|             var files = {}; | ||||
|             fileNames.sort(); | ||||
|             fileNames.forEach(function(file) { | ||||
| @@ -459,13 +468,13 @@ RED.projects.settings = (function() { | ||||
|                 return result; | ||||
|             } | ||||
|             var files = sortFiles("",files,""); | ||||
|             createFileSubList(container,files.children,current,done,"height: 175px"); | ||||
|             createFileSubList(container,files.children,current,filter,done,"height: 175px"); | ||||
|             spinner.remove(); | ||||
|         }); | ||||
|         return container; | ||||
|     } | ||||
|  | ||||
|     function createFileSubList(container, files, current, onselect, style) { | ||||
|     function createFileSubList(container, files, current, filter, onselect, style) { | ||||
|         style = style || ""; | ||||
|         var list = $('<ol>',{class:"projects-dialog-file-list", style:style}).appendTo(container).editableList({ | ||||
|             addButton: false, | ||||
| @@ -481,7 +490,7 @@ RED.projects.settings = (function() { | ||||
|                         } else { | ||||
|                             children.hide(); | ||||
|                         } | ||||
|                         createFileSubList(children,entry.children,current,onselect); | ||||
|                         createFileSubList(children,entry.children,current,filter,onselect); | ||||
|                         header.addClass("selectable"); | ||||
|                         header.click(function(e) { | ||||
|                             if ($(this).hasClass("expanded")) { | ||||
| @@ -507,19 +516,23 @@ RED.projects.settings = (function() { | ||||
|                         header.addClass("projects-dialog-file-list-entry-file-type-git"); | ||||
|                     } | ||||
|                     $('<span class="projects-dialog-file-list-entry-file"> <i class="fa '+fileIcon+'"></i></span>').appendTo(header); | ||||
|                     header.addClass("selectable"); | ||||
|                     if (entry.path === current) { | ||||
|                         header.addClass("selected"); | ||||
|                     if (filter.test(entry.name)) { | ||||
|                         header.addClass("selectable"); | ||||
|                         if (entry.path === current) { | ||||
|                             header.addClass("selected"); | ||||
|                         } | ||||
|                         header.click(function(e) { | ||||
|                             $(".projects-dialog-file-list-entry.selected").removeClass("selected"); | ||||
|                             $(this).addClass("selected"); | ||||
|                             onselect(entry.path); | ||||
|                         }) | ||||
|                         header.dblclick(function(e) { | ||||
|                             e.preventDefault(); | ||||
|                             onselect(entry.path,true); | ||||
|                         }) | ||||
|                     } else { | ||||
|                         header.addClass("unselectable"); | ||||
|                     } | ||||
|                     header.click(function(e) { | ||||
|                         $(".projects-dialog-file-list-entry.selected").removeClass("selected"); | ||||
|                         $(this).addClass("selected"); | ||||
|                         onselect(entry.path); | ||||
|                     }) | ||||
|                     header.dblclick(function(e) { | ||||
|                         e.preventDefault(); | ||||
|                         onselect(entry.path,true); | ||||
|                     }) | ||||
|                 } | ||||
|                 $('<span class="projects-dialog-file-list-entry-name" style=""></span>').text(entry.name).appendTo(header); | ||||
|             } | ||||
| @@ -657,7 +670,7 @@ RED.projects.settings = (function() { | ||||
|                 } else { | ||||
|                     $(this).addClass('selected'); | ||||
|                     flowFileLabel.css('color','inherit'); | ||||
|                     var fileList = showProjectFileListing(flowFileLabel,activeProject,flowFileInput.val(),function(result,isDblClick) { | ||||
|                     var fileList = showProjectFileListing(flowFileLabel,activeProject,flowFileInput.val(), /.*\.json$/,function(result,isDblClick) { | ||||
|                         if (result) { | ||||
|                             flowFileInput.val(result); | ||||
|                         } | ||||
| @@ -887,7 +900,6 @@ RED.projects.settings = (function() { | ||||
|                         }, | ||||
|                         200: function(data) { | ||||
|                             activeProject = data; | ||||
|                             console.log("updating form"); | ||||
|                             updateForm(); | ||||
|                             done(); | ||||
|                         }, | ||||
| @@ -935,191 +947,218 @@ RED.projects.settings = (function() { | ||||
|         updateForm(); | ||||
|     } | ||||
|  | ||||
|     function createLocalRepositorySection(activeProject,pane) { | ||||
|         var title = $('<h3></h3>').text("Local Repository").appendTo(pane); | ||||
|         var repoContainer = $('<div class="user-settings-section"></div>').appendTo(pane); | ||||
|         var editRepoButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>') | ||||
|             .appendTo(title) | ||||
|             .click(function(evt) { | ||||
|                 editRepoButton.hide(); | ||||
|                 localRepoSearch.show(); | ||||
|                 formButtons.show(); | ||||
|             }); | ||||
|  | ||||
|         var row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|         $('<label for=""></label>').text('Branch').appendTo(row); | ||||
|         var localRepoLabel = $('<div class="uneditable-input" style="padding:0">').appendTo(row); | ||||
|  | ||||
|         var hideLocalRepoBranchList = function() { | ||||
|             localRepoSearch.removeClass('selected'); | ||||
|             localRepoLabel.css('height',''); | ||||
|             localRepoBranchListRow.slideUp(100); | ||||
|         } | ||||
|         var localRepoText = $('<span style="display:inline-block; padding: 6px">').text(activeProject.branches.local).appendTo(localRepoLabel); | ||||
|         var localRepoSearch = $('<button class="editor-button" style="border-top-right-radius: 4px; border-bottom-right-radius: 4px; width: 36px; height: 34px; position: absolute; top: -1px; right: -1px;"><i class="fa fa-code-fork"></i></button>') | ||||
|             .hide() | ||||
|             .appendTo(localRepoLabel) | ||||
|             .click(function(e) { | ||||
|                 e.preventDefault(); | ||||
|                 if ($(this).hasClass('selected')) { | ||||
|                     hideLocalRepoBranchList(); | ||||
|                 } else { | ||||
|                     $(this).addClass('selected'); | ||||
|                     localRepoLabel.css('height','auto'); | ||||
|                     localRepoBranchListRow.slideDown(100); | ||||
|                     localRepoBranchList.refresh("/projects/"+activeProject.name+"/branches"); | ||||
|                     localRepoBranchList.focus(); | ||||
|                 } | ||||
|  | ||||
|             }); | ||||
|  | ||||
|         var localRepoBranchListRow = $('<div>').hide().appendTo(localRepoLabel); | ||||
|         var localRepoBranchList = utils.createBranchList({ | ||||
|             current: function() { | ||||
|                 return  activeProject.branches.local | ||||
|             }, | ||||
|             placeholder: "Find or create a branch", | ||||
|             container: localRepoBranchListRow, | ||||
|             onselect: function(body) { | ||||
|                 localRepoText.text(body.name); | ||||
|                 hideLocalRepoBranchList(); | ||||
|             } | ||||
|         }) | ||||
|  | ||||
|         var hideEditForm = function() { | ||||
|             editRepoButton.show(); | ||||
|             localRepoSearch.hide(); | ||||
|             formButtons.hide(); | ||||
|             localRepoBranchListRow.slideUp(100); | ||||
|             localRepoSearch.removeClass('selected'); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         var formButtons = $('<span class="button-group" style="position: relative; float: right; margin-right:0;"></span>').hide().appendTo(repoContainer); | ||||
|         $('<button class="editor-button">Cancel</button>') | ||||
|             .appendTo(formButtons) | ||||
|             .click(function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 hideEditForm(); | ||||
|             }); | ||||
|         var saveButton = $('<button class="editor-button">Save</button>') | ||||
|             .appendTo(formButtons) | ||||
|             .click(function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 hideEditForm(); | ||||
|             }); | ||||
|         var updateForm = function() { | ||||
|             // if (activeProject.settings.credentialSecretInvalid) { | ||||
|             //     credentialStateLabel.find(".user-settings-credentials-state-icon").removeClass().addClass("user-settings-credentials-state-icon fa fa-warning"); | ||||
|             //     credentialStateLabel.find(".user-settings-credentials-state").text("Invalid encryption key"); | ||||
|             // } else if (activeProject.settings.credentialsEncrypted) { | ||||
|             //     credentialStateLabel.find(".user-settings-credentials-state-icon").removeClass().addClass("user-settings-credentials-state-icon fa fa-lock"); | ||||
|             //     credentialStateLabel.find(".user-settings-credentials-state").text("Encryption enabled"); | ||||
|             // } else { | ||||
|             //     credentialStateLabel.find(".user-settings-credentials-state-icon").removeClass().addClass("user-settings-credentials-state-icon fa fa-unlock"); | ||||
|             //     credentialStateLabel.find(".user-settings-credentials-state").text("Encryption disabled"); | ||||
|             // } | ||||
|             // credentialSecretResetButton.toggleClass('disabled',!activeProject.settings.credentialsEncrypted); | ||||
|             // credentialSecretResetButton.prop('disabled',!activeProject.settings.credentialsEncrypted); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function createRemoteRepositorySection(activeProject,pane) { | ||||
|         var title = $('<h3></h3>').text("Git Remotes").appendTo(pane); | ||||
|         var repoContainer = $('<div class="user-settings-section"></div>').appendTo(pane); | ||||
|         var title = $('<h3></h3>').text("Version Control").appendTo(pane); | ||||
|         var editRepoButton = $('<button class="editor-button editor-button-small" style="float: right;">edit</button>') | ||||
|             .appendTo(title) | ||||
|             .click(function(evt) { | ||||
|                 editRepoButton.hide(); | ||||
|                 formButtons.show(); | ||||
|  | ||||
|                 $('.projects-dialog-remote-list-entry-delete').show(); | ||||
|                 remoteListAddButton.show(); | ||||
|  | ||||
|                 gitUsernameLabel.hide(); | ||||
|                 gitUsernameInput.show(); | ||||
|                 gitEmailLabel.hide(); | ||||
|                 gitEmailInput.show(); | ||||
|             }); | ||||
|  | ||||
|         var repoContainer = $('<div class="user-settings-section"></div>').appendTo(pane); | ||||
|         var subtitle = $('<h4></h4>').text("Committer Details").appendTo(repoContainer); | ||||
|         $('<div style="display: inline-block; margin-left: 20px;"><small style="color:#aaa;"></small></div>').appendTo(subtitle).find('small').text("Leave blank to use system default"); | ||||
|  | ||||
|         var row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|         $('<label for=""></label>').text('Username').appendTo(row); | ||||
|         var gitUsernameLabel = $('<div class="uneditable-input">').appendTo(row); | ||||
|         var gitUsernameInput = $('<input type="text">').hide().appendTo(row); | ||||
|  | ||||
|         row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|         $('<label for=""></label>').text('Email').appendTo(row); | ||||
|         var gitEmailLabel = $('<div class="uneditable-input">').appendTo(row); | ||||
|         var gitEmailInput = $('<input type="text">').hide().appendTo(row); | ||||
|  | ||||
|         if (activeProject.git.user) { | ||||
|             gitUsernameLabel.text(activeProject.git.user.name); | ||||
|             gitUsernameInput.val(activeProject.git.user.name); | ||||
|  | ||||
|             gitEmailLabel.text(activeProject.git.user.email); | ||||
|             gitEmailInput.val(activeProject.git.user.email); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         var remotesList = $("<ol>",{style:"height: 320px"}).appendTo(row); | ||||
|         var grTitle = $('<h4></h4>').text("Git remotes").appendTo(repoContainer); | ||||
|  | ||||
|  | ||||
|         row = $('<div class="user-settings-row projects-dialog-remote-list"></div>').appendTo(repoContainer); | ||||
|         var remotesList = $('<ol>').appendTo(row); | ||||
|         remotesList.editableList({ | ||||
|             addButton: "remote", | ||||
|             addButton: 'add remote repository', | ||||
|             height: 'auto', | ||||
|             addItem: function(outer,index,entry) { | ||||
|                 var row = $('<div class="user-settings-row"></div>').appendTo(outer); | ||||
|                 $('<label for=""></label>').text('Name').appendTo(row); | ||||
|                 $('<div class="uneditable-input">').text(entry.name).appendTo(row); | ||||
|                 row = $('<div class="user-settings-row"></div>').appendTo(outer); | ||||
|                 $('<label for=""></label>').text('Fetch URL').appendTo(row); | ||||
|                 $('<div class="uneditable-input">').text(entry.urls.fetch).appendTo(row); | ||||
|                 row = $('<div class="user-settings-row"></div>').appendTo(outer); | ||||
|                 $('<label for=""></label>').text('Push URL').appendTo(row); | ||||
|                 $('<div class="uneditable-input">').text(entry.urls.push).appendTo(row); | ||||
|  | ||||
|                 var header = $('<div class="projects-dialog-remote-list-entry-header"></div>').appendTo(outer); | ||||
|                 entry.header = $('<span>').text(entry.name||"Add new remote").appendTo(header); | ||||
|                 var body = $('<div>').appendTo(outer); | ||||
|                 entry.body = body; | ||||
|                 if (entry.name) { | ||||
|                     entry.removeButton = $('<button class="editor-button editor-button-small projects-dialog-remote-list-entry-delete">remove</button>') | ||||
|                         .hide() | ||||
|                         .appendTo(header) | ||||
|                         .click(function(e) { | ||||
|                             entry.removed = true; | ||||
|                             body.fadeOut(100); | ||||
|                             entry.header.css("text-decoration","line-through") | ||||
|                             entry.header.css("font-style","italic") | ||||
|                             $(this).hide(); | ||||
|                         }); | ||||
|                     if (entry.urls.fetch === entry.urls.push) { | ||||
|                         row = $('<div class="user-settings-row"></div>').appendTo(body); | ||||
|                         $('<label for=""></label>').text('URL').appendTo(row); | ||||
|                         $('<div class="uneditable-input">').text(entry.urls.fetch).appendTo(row); | ||||
|                     } else { | ||||
|                         row = $('<div class="user-settings-row"></div>').appendTo(body); | ||||
|                         $('<label for=""></label>').text('Fetch URL').appendTo(row); | ||||
|                         $('<div class="uneditable-input">').text(entry.urls.fetch).appendTo(row); | ||||
|                         row = $('<div class="user-settings-row"></div>').appendTo(body); | ||||
|                         $('<label for=""></label>').text('Push URL').appendTo(row); | ||||
|                         $('<div class="uneditable-input">').text(entry.urls.push).appendTo(row); | ||||
|                     } | ||||
|                 } else { | ||||
|                     row = $('<div class="user-settings-row"></div>').appendTo(body); | ||||
|                     $('<label for=""></label>').text('Remote name').appendTo(row); | ||||
|                     entry.nameInput = $('<input type="text">').appendTo(row); | ||||
|  | ||||
|                     row = $('<div class="user-settings-row"></div>').appendTo(body); | ||||
|                     var fetchLabel = $('<label for=""></label>').text('URL').appendTo(row); | ||||
|                     entry.urlInput = $('<input type="text">').appendTo(row); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         if (activeProject.hasOwnProperty('remotes')) { | ||||
|             for (var name in activeProject.remotes) { | ||||
|                 if (activeProject.remotes.hasOwnProperty(name)) { | ||||
|                     remotesList.editableList('addItem',{name:name,urls:activeProject.remotes[name]}); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         // row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|  | ||||
|         // if (activeProject.hasOwnProperty('remotes')) { | ||||
|         //     $('<label for=""></label>').text('URL').appendTo(row); | ||||
|         //     for (var name in activeProject.remotes) { | ||||
|         //         if (activeProject.remotes.hasOwnProperty(name)) { | ||||
|         //             var repos = activeProject.remotes[name]; | ||||
|         //             if (repos.fetch === repos.push) { | ||||
|         //                 $('<div class="uneditable-input">').text(repos.fetch).appendTo(row); | ||||
|         //                 $('<div class="projects-edit-form-sublabel"><small></small></div>').appendTo(row).find('small').text(name+" fetch/push"); | ||||
|         //             } else { | ||||
|         //                 $('<div class="uneditable-input">').text(repos.fetch).appendTo(row); | ||||
|         //                 $('<div class="projects-edit-form-sublabel"><small></small></div>').appendTo(row).find('small').text(name+" fetch"); | ||||
|         //                 $('<label for=""></label>').appendTo(row); | ||||
|         //                 $('<div class="uneditable-input">').text(repos.push).appendTo(row); | ||||
|         //                 $('<div class="projects-edit-form-sublabel"><small></small></div>').appendTo(row).find('small').text(name+" push"); | ||||
|         //                 // $('<span>').text(repos.fetch+" (fetch)").appendTo(repoRow); | ||||
|         //                 // $('<span>').text(repos.push+" (push)").appendTo(repoRow); | ||||
|         //             } | ||||
|         //         } | ||||
|         //     } | ||||
|         //     if (activeProject.branches.hasOwnProperty('remote')) { | ||||
|         //         row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|         //         $('<label for="" style="text-align: right;box-sizing: border-box; padding-right: 25px;">Branch</label>').appendTo(row); | ||||
|         //         $('<div class="uneditable-input">').text(activeProject.branches.remote).appendTo(row); | ||||
|         // | ||||
|         //         row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|         //         $('<label for="" style="text-align: right;box-sizing: border-box; padding-right: 25px;">Username</label>').appendTo(row); | ||||
|         //         $('<div class="uneditable-input">').appendTo(row); | ||||
|         // | ||||
|         //         row = $('<div class="user-settings-row"></div>').appendTo(repoContainer); | ||||
|         //         $('<label for="" style="text-align: right;box-sizing: border-box; padding-right: 25px;">Password</label>').appendTo(row); | ||||
|         //         $('<div class="uneditable-input">').html("• • • • • • • •").appendTo(row); | ||||
|         //     } | ||||
|         // } else { | ||||
|         // | ||||
|         // | ||||
|         // } | ||||
|         var remoteListAddButton = row.find(".red-ui-editableList-addButton").hide(); | ||||
|  | ||||
|         var hideEditForm = function() { | ||||
|             editRepoButton.show(); | ||||
|             formButtons.hide(); | ||||
|             $('.projects-dialog-remote-list-entry-delete').hide(); | ||||
|             remoteListAddButton.hide(); | ||||
|  | ||||
|             gitUsernameLabel.show(); | ||||
|             gitUsernameInput.hide(); | ||||
|             gitEmailLabel.show(); | ||||
|             gitEmailInput.hide(); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         var formButtons = $('<span class="button-group" style="position: relative; float: right; margin-right:0;"></span>').hide().appendTo(repoContainer); | ||||
|         var formButtons = $('<span class="button-group" style="position: relative; float: right; margin-right:0;"></span>') | ||||
|             .hide().appendTo(repoContainer); | ||||
|         $('<button class="editor-button">Cancel</button>') | ||||
|             .appendTo(formButtons) | ||||
|             .click(function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|  | ||||
|                 var items = remotesList.editableList('items'); | ||||
|                 items.each(function() { | ||||
|                     var data = $(this).data('data'); | ||||
|                     if (!data.name) { | ||||
|                         remotesList.editableList('removeItem',data); | ||||
|                     } else if (data.removed) { | ||||
|                         delete data.removed; | ||||
|                         data.body.show(); | ||||
|                         data.header.css("text-decoration",""); | ||||
|                         data.header.css("font-style",""); | ||||
|                     } | ||||
|                 }) | ||||
|  | ||||
|  | ||||
|                 hideEditForm(); | ||||
|             }); | ||||
|         var saveButton = $('<button class="editor-button">Save</button>') | ||||
|             .appendTo(formButtons) | ||||
|             .click(function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 hideEditForm(); | ||||
|                 var spinner = utils.addSpinnerOverlay(repoContainer); | ||||
|  | ||||
|                 var body = { | ||||
|                     user: { | ||||
|                         name: gitUsernameInput.val(), | ||||
|                         email: gitEmailInput.val() | ||||
|                     }, | ||||
|                     remotes: {} | ||||
|                 } | ||||
|  | ||||
|                 var items = remotesList.editableList('items'); | ||||
|                 items.each(function() { | ||||
|                     var data = $(this).data('data'); | ||||
|                     if (!data.name) { | ||||
|                         body.remotes[data.nameInput.val()] = { | ||||
|                             url: data.urlInput.val() | ||||
|                         }; | ||||
|                         remotesList.editableList('removeItem',data); | ||||
|                     } else if (data.removed) { | ||||
|                         body.remotes[data.name] = { | ||||
|                             removed: true | ||||
|                         }; | ||||
|                         delete data.removed; | ||||
|                         data.body.show(); | ||||
|                         data.header.css("text-decoration",""); | ||||
|                         data.header.css("font-style",""); | ||||
|                     } | ||||
|                 }) | ||||
|  | ||||
|                 var done = function(err) { | ||||
|                     spinner.remove(); | ||||
|                     if (err) { | ||||
|                         console.log(err); | ||||
|                         return; | ||||
|                     } | ||||
|                     hideEditForm(); | ||||
|                 } | ||||
|                 var payload = { git: body }; | ||||
|  | ||||
|                 // console.log(JSON.stringify(payload,null,4)); | ||||
|                 RED.deploy.setDeployInflight(true); | ||||
|                 utils.sendRequest({ | ||||
|                     url: "projects/"+activeProject.name, | ||||
|                     type: "PUT", | ||||
|                     responses: { | ||||
|                         0: function(error) { | ||||
|                             done(error); | ||||
|                         }, | ||||
|                         200: function(data) { | ||||
|                             activeProject.git.remotes = data.git.remotes; | ||||
|                             activeProject.git.user = data.git.user; | ||||
|                             if (activeProject.git.user) { | ||||
|                                 gitUsernameLabel.text(activeProject.git.user.name); | ||||
|                                 gitUsernameInput.val(activeProject.git.user.name); | ||||
|                                 gitEmailLabel.text(activeProject.git.user.email); | ||||
|                                 gitEmailInput.val(activeProject.git.user.email); | ||||
|                             } | ||||
|  | ||||
|                             updateForm(); | ||||
|                             done(); | ||||
|                         }, | ||||
|                         400: { | ||||
|                             'unexpected_error': function(error) { | ||||
|                                 console.log(error); | ||||
|                                 done(error); | ||||
|                             } | ||||
|                         }, | ||||
|                     } | ||||
|                 },payload); | ||||
|             }); | ||||
|         var updateForm = function() { } | ||||
|         var updateForm = function() { | ||||
|             remotesList.editableList('empty'); | ||||
|             if (activeProject.git.hasOwnProperty('remotes')) { | ||||
|                 for (var name in activeProject.git.remotes) { | ||||
|                     if (activeProject.git.remotes.hasOwnProperty(name)) { | ||||
|                         remotesList.editableList('addItem',{name:name,urls:activeProject.git.remotes[name]}); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         updateForm(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -397,12 +397,14 @@ RED.projects = (function() { | ||||
|                                     projectData.copy = copyProject.name; | ||||
|                                 } else if (projectType === 'clone') { | ||||
|                                     // projectData.credentialSecret = projectSecretInput.val(); | ||||
|                                     projectData.remote = { | ||||
|                                         // name: projectRepoRemoteName.val()||'origin', | ||||
|                                         // branch: projectRepoBranch.val()||'master', | ||||
|                                         url: projectRepoInput.val(), | ||||
|                                         username: projectRepoUserInput.val(), | ||||
|                                         password: projectRepoPasswordInput.val() | ||||
|                                     projectData.git = { | ||||
|                                         remotes: { | ||||
|                                             'origin': { | ||||
|                                                 url: projectRepoInput.val(), | ||||
|                                                 username: projectRepoUserInput.val(), | ||||
|                                                 password: projectRepoPasswordInput.val() | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|  | ||||
| @@ -632,7 +634,7 @@ RED.projects = (function() { | ||||
|  | ||||
|     function sendRequest(options,body) { | ||||
|         // dialogBody.hide(); | ||||
|         console.log(options.url); | ||||
|         console.log(options.url,body); | ||||
|  | ||||
|         if (options.requireCleanWorkspace && RED.nodes.dirty()) { | ||||
|             var message = 'You have undeployed changes that will be lost. Do you want to continue?'; | ||||
| @@ -698,7 +700,7 @@ RED.projects = (function() { | ||||
|                     resultCallbackArgs = {error:responses.statusText}; | ||||
|                     return; | ||||
|                 } else if (options.handleAuthFail !== false && xhr.responseJSON.error === 'git_auth_failed') { | ||||
|                     var url = activeProject.remotes.origin.fetch; | ||||
|                     var url = activeProject.git.remotes.origin.fetch; | ||||
|                     var message = $('<div>'+ | ||||
|                         '<div class="form-row">Authentication required for repository:</div>'+ | ||||
|                         '<div class="form-row"><div style="margin-left: 20px;">'+url+'</div></div>'+ | ||||
| @@ -723,6 +725,11 @@ RED.projects = (function() { | ||||
|                                     var username = $('#projects-user-auth-username').val(); | ||||
|                                     var password = $('#projects-user-auth-password').val(); | ||||
|                                     body = body || {}; | ||||
|                                     var authBody = {git:{remotes:{}}}; | ||||
|                                     authBody.git.remotes[options.remote||'origin'] = { | ||||
|                                         username: username, | ||||
|                                         password: password | ||||
|                                     }; | ||||
|                                     var done = function(err) { | ||||
|                                         if (err) { | ||||
|                                             console.log("Failed to update auth"); | ||||
| @@ -749,14 +756,7 @@ RED.projects = (function() { | ||||
|                                                 } | ||||
|                                             }, | ||||
|                                         } | ||||
|                                     },{ | ||||
|                                         remote: { | ||||
|                                             origin: { | ||||
|                                                 username: username, | ||||
|                                                 password: password | ||||
|                                             } | ||||
|                                         } | ||||
|                                     }); | ||||
|                                     },authBody); | ||||
|                                 } | ||||
|                             } | ||||
|                         ] | ||||
| @@ -858,7 +858,17 @@ RED.projects = (function() { | ||||
|             }, | ||||
|             filter: function(data) { | ||||
|                 var isCreateEntry = (typeof data !=="string"); | ||||
|                 return (isCreateEntry && (branchFilterTerm !== "" && branches.indexOf(branchPrefix+branchFilterTerm) === -1) ) ||  (!isCreateEntry && data.indexOf(branchPrefix+branchFilterTerm) !== -1); | ||||
|                 return ( | ||||
|                             isCreateEntry && | ||||
|                             ( | ||||
|                                 branchFilterTerm !== "" && | ||||
|                                 branches.indexOf(branchPrefix+branchFilterTerm) === -1 | ||||
|                             ) | ||||
|                      ) || | ||||
|                      ( | ||||
|                          !isCreateEntry && | ||||
|                          data.indexOf(branchFilterTerm) !== -1 | ||||
|                      ); | ||||
|             } | ||||
|         }); | ||||
|         return { | ||||
|   | ||||
| @@ -226,7 +226,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                 stagedChangesList.editableList('empty'); | ||||
|                 unmergedChangesList.editableList('empty'); | ||||
|  | ||||
|                 $.getJSON("/projects/"+activeProject.name+"/status",function(result) { | ||||
|                 $.getJSON("projects/"+activeProject.name+"/status",function(result) { | ||||
|                     refreshFiles(result); | ||||
|                 }); | ||||
|             } | ||||
| @@ -471,7 +471,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                     localCommitListShade.show(); | ||||
|                     $(this).addClass('selected'); | ||||
|                     var activeProject = RED.projects.getActiveProject(); | ||||
|                     localBranchList.refresh("/projects/"+activeProject.name+"/branches"); | ||||
|                     localBranchList.refresh("projects/"+activeProject.name+"/branches"); | ||||
|                     localBranchBox.show(); | ||||
|                     setTimeout(function() { | ||||
|                         localBranchBox.css("height","215px"); | ||||
| @@ -523,7 +523,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                     row.click(function(e) { | ||||
|                         var activeProject = RED.projects.getActiveProject(); | ||||
|                         if (activeProject) { | ||||
|                             $.getJSON("/projects/"+activeProject.name+"/commits/"+entry.sha,function(result) { | ||||
|                             $.getJSON("projects/"+activeProject.name+"/commits/"+entry.sha,function(result) { | ||||
|                                 result.project = activeProject; | ||||
|                                 result.parents = entry.parents; | ||||
|                                 result.oldRev = entry.sha+"~1"; | ||||
| @@ -572,7 +572,7 @@ RED.sidebar.versionControl = (function() { | ||||
|  | ||||
|         var localBranchList = utils.createBranchList({ | ||||
|             current: function() { | ||||
|                 return  RED.projects.getActiveProject().branches.local | ||||
|                 return  RED.projects.getActiveProject().git.branches.local | ||||
|             }, | ||||
|             placeholder: "Find or create a branch", | ||||
|             container: localBranchBox, | ||||
| @@ -653,7 +653,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                 } else { | ||||
|                     $(this).addClass('selected'); | ||||
|                     var activeProject = RED.projects.getActiveProject(); | ||||
|                     remoteBranchList.refresh("/projects/"+activeProject.name+"/branches/remote"); | ||||
|                     remoteBranchList.refresh("projects/"+activeProject.name+"/branches/remote"); | ||||
|                     remoteBranchSubRow.show(); | ||||
|                     setTimeout(function() { | ||||
|                         remoteBranchSubRow.height(180); | ||||
| @@ -676,7 +676,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                 var activeProject = RED.projects.getActiveProject(); | ||||
|                 var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain"); | ||||
|                 utils.sendRequest({ | ||||
|                     url: "/projects/"+activeProject.name+"/branches/remote", | ||||
|                     url: "projects/"+activeProject.name+"/branches/remote", | ||||
|                     type: "GET", | ||||
|                     responses: { | ||||
|                         0: function(error) { | ||||
| @@ -706,13 +706,13 @@ RED.sidebar.versionControl = (function() { | ||||
|         var remoteBranchSubRow = $('<div style="height: 0;overflow:hidden; transition: height 0.2s ease-in-out;"></div>').hide().appendTo(remoteBranchRow); | ||||
|         var remoteBranchList = utils.createBranchList({ | ||||
|             current: function() { | ||||
|                 return  RED.projects.getActiveProject().branches.remote | ||||
|                 return  RED.projects.getActiveProject().git.branches.remote | ||||
|             }, | ||||
|             placeholder: "Find or create a remote branch", | ||||
|             currentLabel: "upstream", | ||||
|             remote: function() { | ||||
|                 var project = RED.projects.getActiveProject(); | ||||
|                 var remotes = Object.keys(project.remotes); | ||||
|                 var remotes = Object.keys(project.git.remotes); | ||||
|                 return remotes[0]; | ||||
|             }, | ||||
|             container: remoteBranchSubRow, | ||||
| @@ -721,12 +721,12 @@ RED.sidebar.versionControl = (function() { | ||||
|                 $("#sidebar-version-control-repo-toolbar-set-upstream").prop('disabled',false); | ||||
|                 $("#sidebar-version-control-remote-branch").text(body.name+(body.create?" *":"")); | ||||
|                 var activeProject = RED.projects.getActiveProject(); | ||||
|                 if (activeProject.branches.remote === body.name) { | ||||
|                     delete activeProject.branches.remoteAlt; | ||||
|                 if (activeProject.git.branches.remote === body.name) { | ||||
|                     delete activeProject.git.branches.remoteAlt; | ||||
|                 } else { | ||||
|                     activeProject.branches.remoteAlt = body.name; | ||||
|                     activeProject.git.branches.remoteAlt = body.name; | ||||
|                 } | ||||
|                 $("#sidebar-version-control-repo-toolbar-set-upstream-row").toggle(!!activeProject.branches.remoteAlt); | ||||
|                 $("#sidebar-version-control-repo-toolbar-set-upstream-row").toggle(!!activeProject.git.branches.remoteAlt); | ||||
|                 closeRemoteBranchBox(function() { | ||||
|                     if (!body.create) { | ||||
|                         var start = Date.now(); | ||||
| @@ -738,7 +738,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                             },Math.max(400-(Date.now() - start),0)); | ||||
|                         }) | ||||
|                     } else { | ||||
|                         if (!activeProject.branches.remote) { | ||||
|                         if (!activeProject.git.branches.remote) { | ||||
|                             $('#sidebar-version-control-repo-toolbar-message').text("The created branch will be set as the tracked upstream branch."); | ||||
|                             $("#sidebar-version-control-repo-toolbar-set-upstream").prop('checked',true); | ||||
|                             $("#sidebar-version-control-repo-toolbar-set-upstream").prop('disabled',true); | ||||
| @@ -762,8 +762,8 @@ RED.sidebar.versionControl = (function() { | ||||
|                 var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain"); | ||||
|                 var activeProject = RED.projects.getActiveProject(); | ||||
|                 var url = "projects/"+activeProject.name+"/push"; | ||||
|                 if (activeProject.branches.remoteAlt) { | ||||
|                     url+="/"+activeProject.branches.remoteAlt; | ||||
|                 if (activeProject.git.branches.remoteAlt) { | ||||
|                     url+="/"+activeProject.git.branches.remoteAlt; | ||||
|                 } | ||||
|                 if ($("#sidebar-version-control-repo-toolbar-set-upstream").prop('checked')) { | ||||
|                     url+="?u=true" | ||||
| @@ -803,8 +803,8 @@ RED.sidebar.versionControl = (function() { | ||||
|                 var spinner = utils.addSpinnerOverlay(remoteBox).addClass("projects-dialog-spinner-contain"); | ||||
|                 var activeProject = RED.projects.getActiveProject(); | ||||
|                 var url = "projects/"+activeProject.name+"/pull"; | ||||
|                 if (activeProject.branches.remoteAlt) { | ||||
|                     url+="/"+activeProject.branches.remoteAlt; | ||||
|                 if (activeProject.git.branches.remoteAlt) { | ||||
|                     url+="/"+activeProject.git.branches.remoteAlt; | ||||
|                 } | ||||
|                 if ($("#sidebar-version-control-repo-toolbar-set-upstream").prop('checked')) { | ||||
|                     url+="?u=true" | ||||
| @@ -965,7 +965,7 @@ RED.sidebar.versionControl = (function() { | ||||
|         localCommitList.editableList('empty'); | ||||
|         var activeProject = RED.projects.getActiveProject(); | ||||
|         if (activeProject) { | ||||
|             getCommits("/projects/"+activeProject.name+"/commits",localCommitList,localCommitList.parent()); | ||||
|             getCommits("projects/"+activeProject.name+"/commits",localCommitList,localCommitList.parent()); | ||||
|         } | ||||
|     } | ||||
|     // function refreshRemoteCommits() { | ||||
| @@ -973,7 +973,7 @@ RED.sidebar.versionControl = (function() { | ||||
|     //     var spinner = utils.addSpinnerOverlay(remoteCommitList); | ||||
|     //     var activeProject = RED.projects.getActiveProject(); | ||||
|     //     if (activeProject) { | ||||
|     //         getCommits("/projects/"+activeProject.name+"/commits/origin",remoteCommitList,remoteCommitList.parent()); | ||||
|     //         getCommits("projects/"+activeProject.name+"/commits/origin",remoteCommitList,remoteCommitList.parent()); | ||||
|     //     } | ||||
|     // } | ||||
|  | ||||
| @@ -1127,7 +1127,7 @@ RED.sidebar.versionControl = (function() { | ||||
|  | ||||
|         var activeProject = RED.projects.getActiveProject(); | ||||
|         if (activeProject) { | ||||
|             $.getJSON("/projects/"+activeProject.name+"/status",function(result) { | ||||
|             $.getJSON("projects/"+activeProject.name+"/status",function(result) { | ||||
|                 refreshFiles(result); | ||||
|  | ||||
|                 $('#sidebar-version-control-local-branch').text(result.branches.local); | ||||
| @@ -1136,7 +1136,7 @@ RED.sidebar.versionControl = (function() { | ||||
|                 var commitsAhead = result.commits.ahead || 0; | ||||
|                 var commitsBehind = result.commits.behind || 0; | ||||
|  | ||||
|                 if (activeProject.hasOwnProperty('remotes')) { | ||||
|                 if (activeProject.git.hasOwnProperty('remotes')) { | ||||
|                     if (result.branches.hasOwnProperty("remoteError")) { | ||||
|                         $("#sidebar-version-control-repo-status-auth-issue").show(); | ||||
|                         $("#sidebar-version-control-repo-status-stats").hide(); | ||||
|   | ||||
| @@ -2766,7 +2766,7 @@ RED.view = (function() { | ||||
|             if (v === undefined) { | ||||
|                 return gridSize; | ||||
|             } else { | ||||
|                 gridSize = v; | ||||
|                 gridSize = Math.max(5,v); | ||||
|                 updateGrid(); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -79,6 +79,7 @@ | ||||
|     font-size: 14px; | ||||
|     padding: 6px 14px; | ||||
|     margin-right: 8px; | ||||
|     border-radius: 2px; | ||||
|     color: $editor-button-color; | ||||
|     background: $editor-button-background; | ||||
|  | ||||
|   | ||||
| @@ -180,7 +180,6 @@ | ||||
|             border-right-color: #aaa; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     i { | ||||
|         color: #ccc; | ||||
|         font-size: 2em; | ||||
| @@ -592,6 +591,9 @@ | ||||
|             border-right-color:#999; | ||||
|         } | ||||
|     } | ||||
|     &.unselectable { | ||||
|         color: #ccc; | ||||
|     } | ||||
|  | ||||
|     i { | ||||
|         color: #999; | ||||
| @@ -627,3 +629,47 @@ | ||||
|     } | ||||
| } | ||||
| .projects-dialog-file-list-entry-file-type-git { color: #999 } | ||||
|  | ||||
| .projects-dialog-remote-list { | ||||
|     .red-ui-editableList-container { | ||||
|         padding: 0; | ||||
|         li { | ||||
|             padding: 0; | ||||
|             border: none; | ||||
|             border-radius: 4px; | ||||
|             overflow: hidden; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| .projects-dialog-remote-list-entry-header { | ||||
|     padding: 8px 10px; | ||||
|     background: #f6f6f6; | ||||
|     margin-bottom: 8px; | ||||
| } | ||||
| .projects-dialog-remote-list-entry-delete { | ||||
|     float: right; | ||||
| } | ||||
|  | ||||
| /* | ||||
| .expandable-list-entry { | ||||
|     .exandable-list-entry-header { | ||||
|         padding: 15px 0; | ||||
|         cursor: pointer; | ||||
|         &:hover { | ||||
|             background: #f3f3f3; | ||||
|         } | ||||
|         i { | ||||
|             width: 16px; | ||||
|             text-align: center; | ||||
|         } | ||||
|         .fa-angle-right { | ||||
|             color: #333; | ||||
|             transition: all 0.2s ease-in-out; | ||||
|         } | ||||
|     } | ||||
|     &.expanded .fa-angle-right { | ||||
|         transform: rotate(90deg); | ||||
|     } | ||||
| } | ||||
| */ | ||||
|   | ||||
| @@ -54,6 +54,10 @@ | ||||
|     input[type='number'] { | ||||
|         width: 60px; | ||||
|     } | ||||
|     h4 { | ||||
|         margin-top: 20px; | ||||
|         margin-bottom: 10px; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #user-settings-tab-view { | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| var express = require("express"); | ||||
| var runtime; | ||||
| var settings; | ||||
| var needsPermission = require("../../auth").needsPermission; | ||||
|  | ||||
| module.exports = { | ||||
|     init: function(_runtime) { | ||||
| @@ -29,9 +30,10 @@ module.exports = { | ||||
|         // Projects | ||||
|  | ||||
|         // List all projects | ||||
|         app.get("/", function(req,res) { | ||||
|             runtime.storage.projects.listProjects().then(function(list) { | ||||
|                 var active = runtime.storage.projects.getActiveProject(); | ||||
|         app.get("/", needsPermission("projects.read"), function(req,res) { | ||||
|             console.log(req.user); | ||||
|             runtime.storage.projects.listProjects(req.user, req.user).then(function(list) { | ||||
|                 var active = runtime.storage.projects.getActiveProject(req.user); | ||||
|                 var response = { | ||||
|                     active: active.name, | ||||
|                     projects: list | ||||
| @@ -48,8 +50,8 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Create project | ||||
|         app.post("/", function(req,res) { | ||||
|             runtime.storage.projects.createProject(req.body).then(function(data) { | ||||
|         app.post("/", needsPermission("projects.write"), function(req,res) { | ||||
|             runtime.storage.projects.createProject(req.user, req.body).then(function(data) { | ||||
|                 res.json(data); | ||||
|             }).catch(function(err) { | ||||
|                 console.log(err.stack); | ||||
| @@ -62,12 +64,12 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Update a project | ||||
|         app.put("/:id", function(req,res) { | ||||
|         app.put("/:id", needsPermission("projects.write"), function(req,res) { | ||||
|             //TODO: validate the payload properly | ||||
|             if (req.body.active) { | ||||
|                 var currentProject = runtime.storage.projects.getActiveProject(); | ||||
|                 var currentProject = runtime.storage.projects.getActiveProject(req.user); | ||||
|                 if (req.params.id !== currentProject.name) { | ||||
|                     runtime.storage.projects.setActiveProject(req.params.id).then(function() { | ||||
|                     runtime.storage.projects.setActiveProject(req.user, req.params.id).then(function() { | ||||
|                         res.redirect(303,req.baseUrl + '/'); | ||||
|                     }).catch(function(err) { | ||||
|                         if (err.code) { | ||||
| @@ -84,8 +86,8 @@ module.exports = { | ||||
|                        req.body.hasOwnProperty('dependencies')|| | ||||
|                        req.body.hasOwnProperty('summary') || | ||||
|                        req.body.hasOwnProperty('files') || | ||||
|                        req.body.hasOwnProperty('remote')) { | ||||
|                 runtime.storage.projects.updateProject(req.params.id, req.body).then(function() { | ||||
|                         req.body.hasOwnProperty('git')) { | ||||
|                 runtime.storage.projects.updateProject(req.user, req.params.id, req.body).then(function() { | ||||
|                     res.redirect(303,req.baseUrl + '/'+ req.params.id); | ||||
|                 }).catch(function(err) { | ||||
|                     if (err.code) { | ||||
| @@ -100,8 +102,8 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get project metadata | ||||
|         app.get("/:id", function(req,res) { | ||||
|             runtime.storage.projects.getProject(req.params.id).then(function(data) { | ||||
|         app.get("/:id", needsPermission("projects.read"), function(req,res) { | ||||
|             runtime.storage.projects.getProject(req.user, req.params.id).then(function(data) { | ||||
|                 if (data) { | ||||
|                     res.json(data); | ||||
|                 } else { | ||||
| @@ -114,13 +116,13 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Delete project - tbd | ||||
|         app.delete("/:id", function(req,res) { | ||||
|         app.delete("/:id", needsPermission("projects.write"), function(req,res) { | ||||
|         }); | ||||
|  | ||||
|  | ||||
|         // Get project status - files, commit counts, branch info | ||||
|         app.get("/:id/status", function(req,res) { | ||||
|             runtime.storage.projects.getStatus(req.params.id).then(function(data) { | ||||
|         app.get("/:id/status", needsPermission("projects.read"), function(req,res) { | ||||
|             runtime.storage.projects.getStatus(req.user, req.params.id).then(function(data) { | ||||
|                 if (data) { | ||||
|                     res.json(data); | ||||
|                 } else { | ||||
| @@ -134,8 +136,8 @@ module.exports = { | ||||
|  | ||||
|  | ||||
|         // Project file listing | ||||
|         app.get("/:id/files", function(req,res) { | ||||
|             runtime.storage.projects.getFiles(req.params.id).then(function(data) { | ||||
|         app.get("/:id/files", needsPermission("projects.read"), function(req,res) { | ||||
|             runtime.storage.projects.getFiles(req.user, req.params.id).then(function(data) { | ||||
|                 console.log("TODO: REMOVE /:id/files as /:id/status is better!") | ||||
|                 res.json(data); | ||||
|             }) | ||||
| @@ -147,12 +149,12 @@ module.exports = { | ||||
|  | ||||
|  | ||||
|         // Get file content in a given tree (index/stage) | ||||
|         app.get("/:id/files/:treeish/*", function(req,res) { | ||||
|         app.get("/:id/files/:treeish/*", needsPermission("projects.read"), function(req,res) { | ||||
|             var projectId = req.params.id; | ||||
|             var treeish = req.params.treeish; | ||||
|             var filePath = req.params[0]; | ||||
|  | ||||
|             runtime.storage.projects.getFile(projectId,filePath,treeish).then(function(data) { | ||||
|             runtime.storage.projects.getFile(req.user, projectId,filePath,treeish).then(function(data) { | ||||
|                 res.json({content:data}); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -162,11 +164,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Stage a file | ||||
|         app.post("/:id/stage/*", function(req,res) { | ||||
|         app.post("/:id/stage/*", needsPermission("projects.write"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|             var file = req.params[0]; | ||||
|  | ||||
|             runtime.storage.projects.stageFile(projectName,file).then(function(data) { | ||||
|             runtime.storage.projects.stageFile(req.user, projectName,file).then(function(data) { | ||||
|                 res.redirect(303,req.baseUrl+"/"+projectName+"/status"); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -176,11 +178,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Stage multiple files | ||||
|         app.post("/:id/stage", function(req,res) { | ||||
|         app.post("/:id/stage", needsPermission("projects.write"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|             var files = req.body.files; | ||||
|  | ||||
|             runtime.storage.projects.stageFile(projectName,files).then(function(data) { | ||||
|             runtime.storage.projects.stageFile(req.user, projectName,files).then(function(data) { | ||||
|                 res.redirect(303,req.baseUrl+"/"+projectName+"/status"); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -190,10 +192,10 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Commit changes | ||||
|         app.post("/:id/commit", function(req,res) { | ||||
|         app.post("/:id/commit", needsPermission("projects.write"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|  | ||||
|             runtime.storage.projects.commit(projectName,req.body).then(function(data) { | ||||
|             runtime.storage.projects.commit(req.user, projectName,req.body).then(function(data) { | ||||
|                 res.redirect(303,req.baseUrl+"/"+projectName+"/status"); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -203,11 +205,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Unstage a file | ||||
|         app.delete("/:id/stage/*", function(req,res) { | ||||
|         app.delete("/:id/stage/*", needsPermission("projects.write"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|             var file = req.params[0]; | ||||
|  | ||||
|             runtime.storage.projects.unstageFile(projectName,file).then(function(data) { | ||||
|             runtime.storage.projects.unstageFile(req.user, projectName,file).then(function(data) { | ||||
|                 res.redirect(303,req.baseUrl+"/"+projectName+"/status"); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -217,9 +219,9 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Unstage multiple files | ||||
|         app.delete("/:id/stage", function(req, res) { | ||||
|         app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             runtime.storage.projects.unstageFile(projectName).then(function(data) { | ||||
|             runtime.storage.projects.unstageFile(req.user, projectName).then(function(data) { | ||||
|                 res.redirect(303,req.baseUrl+"/"+projectName+"/status"); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -229,11 +231,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get a file diff | ||||
|         app.get("/:id/diff/:type/*", function(req,res) { | ||||
|         app.get("/:id/diff/:type/*", needsPermission("projects.read"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|             var type = req.params.type; | ||||
|             var file = req.params[0]; | ||||
|             runtime.storage.projects.getFileDiff(projectName,file,type).then(function(data) { | ||||
|             runtime.storage.projects.getFileDiff(req.user, projectName,file,type).then(function(data) { | ||||
|                 res.json({ | ||||
|                     diff: data | ||||
|                 }) | ||||
| @@ -245,13 +247,13 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get a list of commits | ||||
|         app.get("/:id/commits", function(req, res) { | ||||
|         app.get("/:id/commits", needsPermission("projects.read"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             var options = { | ||||
|                 limit: req.query.limit||20, | ||||
|                 before: req.query.before | ||||
|             }; | ||||
|             runtime.storage.projects.getCommits(projectName,options).then(function(data) { | ||||
|             runtime.storage.projects.getCommits(req.user, projectName,options).then(function(data) { | ||||
|                 res.json(data); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -265,11 +267,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get an individual commit details | ||||
|         app.get("/:id/commits/:sha", function(req, res) { | ||||
|         app.get("/:id/commits/:sha", needsPermission("projects.read"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             var sha = req.params.sha; | ||||
|  | ||||
|             runtime.storage.projects.getCommit(projectName,sha).then(function(data) { | ||||
|             runtime.storage.projects.getCommit(req.user, projectName,sha).then(function(data) { | ||||
|                 res.json({commit:data}); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -279,11 +281,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Push local commits to remote | ||||
|         app.post("/:id/push/?*", function(req,res) { | ||||
|         app.post("/:id/push/?*", needsPermission("projects.write"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|             var remoteBranchName = req.params[0] | ||||
|             var setRemote = req.query.u; | ||||
|             runtime.storage.projects.push(projectName,remoteBranchName,setRemote).then(function(data) { | ||||
|             runtime.storage.projects.push(req.user, projectName,remoteBranchName,setRemote).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -297,11 +299,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Pull remote commits | ||||
|         app.post("/:id/pull/?*", function(req,res) { | ||||
|         app.post("/:id/pull/?*", needsPermission("projects.write"), function(req,res) { | ||||
|             var projectName = req.params.id; | ||||
|             var remoteBranchName = req.params[0]; | ||||
|             var setRemote = req.query.u; | ||||
|             runtime.storage.projects.pull(projectName,remoteBranchName,setRemote).then(function(data) { | ||||
|             runtime.storage.projects.pull(req.user, projectName,remoteBranchName,setRemote).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -315,9 +317,9 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Abort an ongoing merge | ||||
|         app.delete("/:id/merge", function(req, res) { | ||||
|         app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             runtime.storage.projects.abortMerge(projectName).then(function(data) { | ||||
|             runtime.storage.projects.abortMerge(req.user, projectName).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -331,11 +333,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Resolve a merge | ||||
|         app.post("/:id/resolve/*", function(req, res) { | ||||
|         app.post("/:id/resolve/*", needsPermission("projects.write"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             var file = req.params[0]; | ||||
|             var resolution = req.body.resolutions; | ||||
|             runtime.storage.projects.resolveMerge(projectName,file,resolution).then(function(data) { | ||||
|             runtime.storage.projects.resolveMerge(req.user, projectName,file,resolution).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -349,9 +351,9 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get a list of local branches | ||||
|         app.get("/:id/branches", function(req, res) { | ||||
|         app.get("/:id/branches", needsPermission("projects.read"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             runtime.storage.projects.getBranches(projectName,false).then(function(data) { | ||||
|             runtime.storage.projects.getBranches(req.user, projectName,false).then(function(data) { | ||||
|                 res.json(data); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -365,12 +367,13 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get a list of remote branches | ||||
|         app.get("/:id/branches/remote", function(req, res) { | ||||
|         app.get("/:id/branches/remote", needsPermission("projects.read"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             runtime.storage.projects.getBranches(projectName,true).then(function(data) { | ||||
|             runtime.storage.projects.getBranches(req.user, projectName,true).then(function(data) { | ||||
|                 res.json(data); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
|                 console.log(err.stack); | ||||
|                 if (err.code) { | ||||
|                     res.status(400).json({error:err.code, message: err.message}); | ||||
|                 } else { | ||||
| @@ -380,10 +383,10 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Get branch status - commit counts/ahead/behind | ||||
|         app.get("/:id/branches/remote/*/status", function(req, res) { | ||||
|         app.get("/:id/branches/remote/*/status", needsPermission("projects.read"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             var branch = req.params[0]; | ||||
|             runtime.storage.projects.getBranchStatus(projectName,branch).then(function(data) { | ||||
|             runtime.storage.projects.getBranchStatus(req.user, projectName,branch).then(function(data) { | ||||
|                 res.json(data); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
| @@ -397,11 +400,11 @@ module.exports = { | ||||
|         }); | ||||
|  | ||||
|         // Set the active local branch | ||||
|         app.post("/:id/branches", function(req, res) { | ||||
|         app.post("/:id/branches", needsPermission("projects.write"), function(req, res) { | ||||
|             var projectName = req.params.id; | ||||
|             var branchName = req.body.name; | ||||
|             var isCreate = req.body.create; | ||||
|             runtime.storage.projects.setBranch(projectName,branchName,isCreate).then(function(data) { | ||||
|             runtime.storage.projects.setBranch(req.user, projectName,branchName,isCreate).then(function(data) { | ||||
|                 res.json(data); | ||||
|             }) | ||||
|             .catch(function(err) { | ||||
|   | ||||
| @@ -46,13 +46,6 @@ function init(_server,_runtime) { | ||||
|         adminApp.use(bodyParser.json({limit:maxApiRequestSize})); | ||||
|         adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true})); | ||||
|  | ||||
|         // Editor | ||||
|         if (!settings.disableEditor) { | ||||
|             editor = require("./editor"); | ||||
|             var editorApp = editor.init(server, runtime); | ||||
|             adminApp.use(editorApp); | ||||
|         } | ||||
|  | ||||
|         adminApp.get("/auth/login",auth.login,apiUtil.errorHandler); | ||||
|         if (settings.adminAuth) { | ||||
|             if (settings.adminAuth.type === "strategy") { | ||||
| @@ -68,6 +61,13 @@ function init(_server,_runtime) { | ||||
|             } | ||||
|             adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler); | ||||
|         } | ||||
|          | ||||
|         // Editor | ||||
|         if (!settings.disableEditor) { | ||||
|             editor = require("./editor"); | ||||
|             var editorApp = editor.init(server, runtime); | ||||
|             adminApp.use(editorApp); | ||||
|         } | ||||
|  | ||||
|         if (settings.httpAdminCors) { | ||||
|             var corsHandler = cors(settings.httpAdminCors); | ||||
|   | ||||
| @@ -51,9 +51,9 @@ Project.prototype.load = function () { | ||||
|     } | ||||
|  | ||||
|     this.credentialSecret = projectSettings.credentialSecret; | ||||
|     this.git = projectSettings.git || { user:{} }; | ||||
|  | ||||
|     this.remote = projectSettings.remote; | ||||
|  | ||||
| console.log("LOADED",this.git); | ||||
|     // this.paths.flowFile = fspath.join(this.path,"flow.json"); | ||||
|     // this.paths.credentialsFile = fspath.join(this.path,"flow_cred.json"); | ||||
|  | ||||
| @@ -103,12 +103,7 @@ Project.prototype.load = function () { | ||||
|         //     project.paths.credentialsFile = fspath.join(project.path,"flow_cred.json"); | ||||
|         // } | ||||
|  | ||||
|         promises.push(gitTools.getRemotes(project.path).then(function(remotes) { | ||||
|             project.remotes = remotes; | ||||
|         })); | ||||
|         promises.push(gitTools.getBranchInfo(project.path).then(function(branches) { | ||||
|             project.branches = branches; | ||||
|         })); | ||||
|         promises.push(project.loadRemotes()); | ||||
|  | ||||
|         return when.settle(promises).then(function() { | ||||
|             return project; | ||||
| @@ -116,7 +111,51 @@ Project.prototype.load = function () { | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| Project.prototype.update = function (data) { | ||||
| Project.prototype.loadRemotes = function() { | ||||
|     var project = this; | ||||
|     return gitTools.getRemotes(project.path).then(function(remotes) { | ||||
|         project.remotes = remotes; | ||||
|     }).then(function() { | ||||
|         return project.loadBranches(); | ||||
|     }).then(function() { | ||||
|  | ||||
|         var allRemotes = Object.keys(project.remotes); | ||||
|         var match = ""; | ||||
|         allRemotes.forEach(function(remote) { | ||||
|             if (project.branches.remote.indexOf(remote) === 0 && match.length < remote.length) { | ||||
|                 match = remote; | ||||
|             } | ||||
|         }); | ||||
|         project.currentRemote = project.parseRemoteBranch(project.branches.remote).remote; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| Project.prototype.parseRemoteBranch = function (remoteBranch) { | ||||
|     if (!remoteBranch) { | ||||
|         return {} | ||||
|     } | ||||
|     var project = this; | ||||
|     var allRemotes = Object.keys(project.remotes); | ||||
|     var match = ""; | ||||
|     allRemotes.forEach(function(remote) { | ||||
|         if (remoteBranch.indexOf(remote) === 0 && match.length < remote.length) { | ||||
|             match = remote; | ||||
|         } | ||||
|     }); | ||||
|     return { | ||||
|         remote: match, | ||||
|         branch: remoteBranch.substring(match.length+1) | ||||
|     } | ||||
|  | ||||
| }; | ||||
|  | ||||
| Project.prototype.loadBranches = function() { | ||||
|     var project = this; | ||||
|     return gitTools.getBranchInfo(project.path).then(function(branches) { | ||||
|         project.branches = branches; | ||||
|     }); | ||||
| } | ||||
| Project.prototype.update = function (user, data) { | ||||
|  | ||||
|     var promises = []; | ||||
|     var project = this; | ||||
| @@ -172,13 +211,63 @@ Project.prototype.update = function (data) { | ||||
|         savePackage = true; | ||||
|         this.package.description = data.summary; | ||||
|     } | ||||
|     if (data.hasOwnProperty('remote')) { | ||||
|         for (var remote in data.remote) { | ||||
|             if (data.remote.hasOwnProperty(remote)) { | ||||
|                 authCache.set(project.name,remote,data.remote[remote]); | ||||
|     // if (data.hasOwnProperty('remote')) { | ||||
|     //     // TODO: this MUST move under 'git' | ||||
|     //     for (var remote in data.remote) { | ||||
|     //         if (data.remote.hasOwnProperty(remote)) { | ||||
|     //             authCache.set(project.name,remote,data.remote[remote]); | ||||
|     //         } | ||||
|     //     } | ||||
|     // } | ||||
|  | ||||
|     if (data.hasOwnProperty('git')) { | ||||
|         if (data.git.hasOwnProperty('user')) { | ||||
|             var username; | ||||
|             if (!user) { | ||||
|                 username = "_"; | ||||
|             } else { | ||||
|                 username = user.username; | ||||
|             } | ||||
|             globalProjectSettings.projects[this.name].git = globalProjectSettings.projects[this.name].git || {}; | ||||
|             globalProjectSettings.projects[this.name].git.user = globalProjectSettings.projects[this.name].git.user || {}; | ||||
|             globalProjectSettings.projects[this.name].git.user[username] = { | ||||
|                 name: data.git.user.name, | ||||
|                 email: data.git.user.email | ||||
|             } | ||||
|             this.git.user[username] = { | ||||
|                 name: data.git.user.name, | ||||
|                 email: data.git.user.email | ||||
|             } | ||||
|             saveSettings = true; | ||||
|         } | ||||
|         if (data.git.hasOwnProperty('remotes')) { | ||||
|             var remoteNames = Object.keys(data.git.remotes); | ||||
|             var remotesChanged = false; | ||||
|             var modifyRemotesPromise = when.resolve(); | ||||
|             remoteNames.forEach(function(name) { | ||||
|                 if (data.git.remotes[name].removed) { | ||||
|                     remotesChanged = true; | ||||
|                     modifyRemotesPromise = modifyRemotesPromise.then(function() { gitTools.removeRemote(project.path,name) }); | ||||
|                 } else { | ||||
|                     if (data.git.remotes[name].url) { | ||||
|                         remotesChanged = true; | ||||
|                         modifyRemotesPromise = modifyRemotesPromise.then(function() { gitTools.addRemote(project.path,name,data.git.remotes[name])}); | ||||
|                     } | ||||
|                     if (data.git.remotes[name].username && data.git.remotes[name].password) { | ||||
|                         var url = data.git.remotes[name].url || project.remotes[name].fetch; | ||||
|                         authCache.set(project.name,url,data.git.remotes[name]); | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|             if (remotesChanged) { | ||||
|                 modifyRemotesPromise = modifyRemotesPromise.then(function() { | ||||
|                     return project.loadRemotes(); | ||||
|                 }); | ||||
|                 promises.push(modifyRemotesPromise); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (data.hasOwnProperty('files')) { | ||||
|         this.package['node-red'] = this.package['node-red'] || { settings: {}}; | ||||
|         if (data.files.hasOwnProperty('flow') && this.package['node-red'].settings.flowFile !== data.files.flow) { | ||||
| @@ -223,8 +312,15 @@ Project.prototype.stageFile = function(file) { | ||||
| Project.prototype.unstageFile = function(file) { | ||||
|     return gitTools.unstageFile(this.path,file); | ||||
| } | ||||
| Project.prototype.commit = function(options) { | ||||
|     return gitTools.commit(this.path,options.message); | ||||
| Project.prototype.commit = function(user, options) { | ||||
|     var username; | ||||
|     if (!user) { | ||||
|         username = "_"; | ||||
|     } else { | ||||
|         username = user.username; | ||||
|     } | ||||
|     var gitUser = this.git.user[username]; | ||||
|     return gitTools.commit(this.path,options.message,gitUser); | ||||
| } | ||||
| Project.prototype.getFileDiff = function(file,type) { | ||||
|     return gitTools.getFileDiff(this.path,file,type); | ||||
| @@ -247,8 +343,17 @@ Project.prototype.status = function() { | ||||
|     var self = this; | ||||
|  | ||||
|     var fetchPromise; | ||||
|     if (this.remote) { | ||||
|         fetchPromise = gitTools.fetch(this.path,authCache.get(this.name,'origin')); | ||||
|     if (this.remotes) { | ||||
|         fetchPromise = gitTools.getRemoteBranch(self.path).then(function(remoteBranch) { | ||||
|             var allRemotes = Object.keys(self.remotes); | ||||
|             var match = ""; | ||||
|             allRemotes.forEach(function(remote) { | ||||
|                 if (remoteBranch.indexOf(remote) === 0 && match.length < remote.length) { | ||||
|                     match = remote; | ||||
|                 } | ||||
|             }) | ||||
|             return self.fetch(match); | ||||
|         }); | ||||
|     } else { | ||||
|         fetchPromise = when.resolve(); | ||||
|     } | ||||
| @@ -267,6 +372,7 @@ Project.prototype.status = function() { | ||||
|             self.branches.remote = result.branches.remote; | ||||
|             if (fetchError) { | ||||
|                 result.branches.remoteError = { | ||||
|                     remote: fetchError.remote, | ||||
|                     code: fetchError.code | ||||
|                 } | ||||
|             } | ||||
| @@ -283,17 +389,19 @@ Project.prototype.status = function() { | ||||
| }; | ||||
|  | ||||
| Project.prototype.push = function (remoteBranchName,setRemote) { | ||||
|     return gitTools.push(this.path, remoteBranchName, setRemote, authCache.get(this.name,'origin')); | ||||
|     var remote = this.parseRemoteBranch(remoteBranchName); | ||||
|     return gitTools.push(this.path, remote.remote || this.currentRemote,remote.branch, setRemote, authCache.get(this.name,this.remotes[this.currentRemote].fetch)); | ||||
| }; | ||||
|  | ||||
| Project.prototype.pull = function (remoteBranchName,setRemote) { | ||||
|     var self = this; | ||||
|     if (setRemote) { | ||||
|         return gitTools.setUpstream(this.path, remoteBranchName).then(function() { | ||||
|             return gitTools.pull(self.path, null, authCache.get(self.name,'origin')); | ||||
|             return gitTools.pull(self.path, null, null, authCache.get(self.name,this.remotes[this.currentRemote].fetch)); | ||||
|         }) | ||||
|     } else { | ||||
|         return gitTools.pull(this.path, remoteBranchName, authCache.get(this.name,'origin')); | ||||
|         var remote = this.parseRemoteBranch(remoteBranchName); | ||||
|         return gitTools.pull(this.path, remote.remote, remote.branch, authCache.get(this.name,this.remotes[this.currentRemote].fetch)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @@ -342,18 +450,41 @@ Project.prototype.abortMerge = function () { | ||||
|     return gitTools.abortMerge(this.path); | ||||
| }; | ||||
|  | ||||
| Project.prototype.getBranches = function (remote) { | ||||
| Project.prototype.getBranches = function (isRemote) { | ||||
|     var self = this; | ||||
|     var fetchPromise; | ||||
|     if (remote) { | ||||
|         fetchPromise = gitTools.fetch(this.path,authCache.get(this.name,'origin')) | ||||
|     if (isRemote) { | ||||
|         fetchPromise = self.fetch(); | ||||
|     } else { | ||||
|         fetchPromise = when.resolve(); | ||||
|     } | ||||
|     return fetchPromise.then(function() { | ||||
|         return gitTools.getBranches(self.path,remote); | ||||
|         return gitTools.getBranches(self.path,isRemote); | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| Project.prototype.fetch = function(remoteName) { | ||||
|     var project = this; | ||||
|     if (remoteName) { | ||||
|         return gitTools.fetch(project.path,remoteName,authCache.get(project.name,project.remotes[remoteName].fetch)).catch(function(err) { | ||||
|             err.remote = remoteName; | ||||
|             throw err; | ||||
|         }) | ||||
|     } else { | ||||
|         var remotes = Object.keys(this.remotes); | ||||
|         var promise = when.resolve(); | ||||
|         remotes.forEach(function(remote) { | ||||
|             promise = promise.then(function() { | ||||
|                 return gitTools.fetch(project.path,remote,authCache.get(project.name,project.remotes[remote].fetch)) | ||||
|             }).catch(function(err) { | ||||
|                 err.remote = remote; | ||||
|                 throw err; | ||||
|             }) | ||||
|         }); | ||||
|         return promise; | ||||
|     } | ||||
| } | ||||
|  | ||||
| Project.prototype.setBranch = function (branchName, isCreate) { | ||||
|     var self = this; | ||||
|     return gitTools.checkoutBranch(this.path, branchName, isCreate).then(function() { | ||||
| @@ -402,8 +533,10 @@ Project.prototype.toJSON = function () { | ||||
|             flow: this.paths.flowFile, | ||||
|             credentials: this.paths.credentialsFile | ||||
|         }, | ||||
|         remotes: this.remotes, | ||||
|         branches: this.branches | ||||
|         git: { | ||||
|             remotes: this.remotes, | ||||
|             branches: this.branches | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @@ -438,7 +571,7 @@ function createProjectDirectory(project) { | ||||
|     return fs.ensureDir(projectPath); | ||||
| } | ||||
|  | ||||
| function createDefaultProject(project) { | ||||
| function createDefaultProject(user, project) { | ||||
|     var projectPath = fspath.join(projectsDir,project.name); | ||||
|     // Create a basic skeleton of a project | ||||
|     return gitTools.initRepo(projectPath).then(function() { | ||||
| @@ -502,7 +635,7 @@ function checkProjectFiles(project) { | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function createProject(metadata) { | ||||
| function createProject(user, metadata) { | ||||
|     var project = metadata.name; | ||||
|     return when.promise(function(resolve,reject) { | ||||
|         var projectPath = fspath.join(projectsDir,project); | ||||
| @@ -518,23 +651,20 @@ function createProject(metadata) { | ||||
|                 if (metadata.hasOwnProperty('credentialSecret')) { | ||||
|                     projects.projects[project].credentialSecret = metadata.credentialSecret; | ||||
|                 } | ||||
|                 if (metadata.remote) { | ||||
|                     projects.projects[project].remote = metadata.remote; | ||||
|                 } | ||||
|                 return settings.set('projects',projects); | ||||
|             }).then(function() { | ||||
|                 if (metadata.remote) { | ||||
|                 if (metadata.git && metadata.git.remotes && metadata.git.remotes.origin) { | ||||
|                     var originRemote = metadata.git.remotes.origin; | ||||
|                     var auth; | ||||
|                     if (metadata.remote.hasOwnProperty("username") && metadata.remote.hasOwnProperty("password")) { | ||||
|                         authCache.set(project,'origin',{ // TODO: hardcoded remote name | ||||
|                                 username: metadata.remote.username, | ||||
|                                 password: metadata.remote.password | ||||
|                     if (originRemote.hasOwnProperty("username") && originRemote.hasOwnProperty("password")) { | ||||
|                         authCache.set(project,originRemote.url,{ // TODO: hardcoded remote name | ||||
|                                 username: originRemote.username, | ||||
|                                 password: originRemote.password | ||||
|                             } | ||||
|                         ); | ||||
|                         auth = authCache.get(project,'origin'); | ||||
|                         auth = authCache.get(project,originRemote.url); | ||||
|                     } | ||||
|  | ||||
|                     return gitTools.clone(metadata.remote,auth,projectPath).then(function(result) { | ||||
|                     return gitTools.clone(originRemote,auth,projectPath).then(function(result) { | ||||
|                         // Check this is a valid project | ||||
|                         // If it is empty | ||||
|                         //  - if 'populate' flag is set, call populateProject | ||||
| @@ -554,7 +684,7 @@ function createProject(metadata) { | ||||
|                         }); | ||||
|                     }) | ||||
|                 } else { | ||||
|                     createDefaultProject(metadata).then(function() { resolve(getProject(project))}).catch(reject); | ||||
|                     createDefaultProject(user, metadata).then(function() { resolve(getProject(project))}).catch(reject); | ||||
|                 } | ||||
|             }).catch(reject); | ||||
|         }) | ||||
|   | ||||
| @@ -25,15 +25,13 @@ module.exports = { | ||||
|         delete authCache[project]; | ||||
|     }, | ||||
|     set: function(project,remote,auth) { | ||||
|         if (authCache.hasOwnProperty(project)) { | ||||
|             authCache[project][remote] = auth; | ||||
|         } else { | ||||
|             authCache[project] = { | ||||
|                 remote: auth | ||||
|             } | ||||
|         } | ||||
|          console.log("AuthCache.set",remote,auth); | ||||
|         authCache[project] = authCache[project]||{}; | ||||
|         authCache[project][remote] = auth; | ||||
|         // console.log(JSON.stringify(authCache,'',4)); | ||||
|     }, | ||||
|     get: function(project,remote) { | ||||
|         console.log("AuthCache.get",remote,authCache[project]&&authCache[project][remote]); | ||||
|         if (authCache.hasOwnProperty(project)) { | ||||
|             return authCache[project][remote]; | ||||
|         } | ||||
|   | ||||
| @@ -37,7 +37,6 @@ function getListenPath() { | ||||
| var ResponseServer = function(auth) { | ||||
|     return new Promise(function(resolve, reject) { | ||||
|         server = net.createServer(function(connection) { | ||||
|             // Stop accepting new connections | ||||
|             connection.setEncoding('utf8'); | ||||
|             var parts = []; | ||||
|             connection.on('data', function(data) { | ||||
| @@ -46,6 +45,7 @@ var ResponseServer = function(auth) { | ||||
|                     parts.push(data.substring(0, m)); | ||||
|                     data = data.substring(m); | ||||
|                     var line = parts.join(""); | ||||
|                     console.log("LINE",line); | ||||
|                     parts = []; | ||||
|                     if (line==='Username') { | ||||
|                         connection.end(auth.username); | ||||
|   | ||||
| @@ -311,6 +311,15 @@ function getBranchStatus(cwd,remoteBranch) { | ||||
|     }) | ||||
| } | ||||
|  | ||||
| function addRemote(cwd,name,options) { | ||||
|     var args = ["remote","add",name,options.url] | ||||
|     return runGitCommand(args,cwd); | ||||
| } | ||||
| function removeRemote(cwd,name) { | ||||
|     var args = ["remote","remove",name]; | ||||
|     return runGitCommand(args,cwd); | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     init: function(_settings,_runtime) { | ||||
|         log = _runtime.log | ||||
| @@ -322,12 +331,11 @@ module.exports = { | ||||
|         var args = ["branch","--set-upstream-to",remoteBranch]; | ||||
|         return runGitCommand(args,cwd); | ||||
|     }, | ||||
|     pull: function(cwd,remoteBranch,auth) { | ||||
|     pull: function(cwd,remote,branch,auth) { | ||||
|         var args = ["pull"]; | ||||
|         var m = /^(.*?)\/(.*)$/.exec(remoteBranch); | ||||
|         if (m) { | ||||
|             args.push(m[1]); | ||||
|             args.push(m[2]) | ||||
|         if (remote && branch) { | ||||
|             args.push(remote); | ||||
|             args.push(branch); | ||||
|         } | ||||
|         var promise; | ||||
|         if (auth) { | ||||
| @@ -348,17 +356,16 @@ module.exports = { | ||||
|             throw err; | ||||
|         }); | ||||
|     }, | ||||
|     push: function(cwd,remoteBranch,setUpstream, auth) { | ||||
|     push: function(cwd,remote,branch,setUpstream, auth) { | ||||
|         var args = ["push"]; | ||||
|         var m = /^(.*?)\/(.*)$/.exec(remoteBranch); | ||||
|         if (m) { | ||||
|         if (branch) { | ||||
|             if (setUpstream) { | ||||
|                 args.push("-u"); | ||||
|             } | ||||
|             args.push(m[1]); | ||||
|             args.push("HEAD:"+m[2]); | ||||
|             args.push(remote); | ||||
|             args.push("HEAD:"+branch); | ||||
|         } else { | ||||
|             args.push("origin"); | ||||
|             args.push(remote); | ||||
|         } | ||||
|         args.push("--porcelain"); | ||||
|         var promise; | ||||
| @@ -419,9 +426,16 @@ module.exports = { | ||||
|         } | ||||
|         return runGitCommand(args,cwd); | ||||
|     }, | ||||
|     commit: function(cwd, message) { | ||||
|     commit: function(cwd, message, gitUser) { | ||||
|         var args = ["commit","-m",message]; | ||||
|         return runGitCommand(args,cwd); | ||||
|         var env; | ||||
|         if (gitUser && gitUser['name'] && gitUser['email']) { | ||||
|             args.unshift('user.name="'+gitUser['name']+'"'); | ||||
|             args.unshift('-c'); | ||||
|             args.unshift('user.email="'+gitUser['email']+'"'); | ||||
|             args.unshift('-c'); | ||||
|         } | ||||
|         return runGitCommand(args,cwd,env); | ||||
|     }, | ||||
|     getFileDiff(cwd,file,type) { | ||||
|         var args = ["diff"]; | ||||
| @@ -433,8 +447,8 @@ module.exports = { | ||||
|         args.push(file); | ||||
|         return runGitCommand(args,cwd); | ||||
|     }, | ||||
|     fetch: function(cwd,auth) { | ||||
|         var args = ["fetch"]; | ||||
|     fetch: function(cwd,remote,auth) { | ||||
|         var args = ["fetch",remote]; | ||||
|         if (auth) { | ||||
|             return runGitCommandWithAuth(args,cwd,auth); | ||||
|         } else { | ||||
| @@ -474,6 +488,9 @@ module.exports = { | ||||
|         return runGitCommand(['merge','--abort'],cwd); | ||||
|     }, | ||||
|     getRemotes: getRemotes, | ||||
|     getRemoteBranch: function(cwd) { | ||||
|         return runGitCommand(['rev-parse','--abbrev-ref','--symbolic-full-name','@{u}'],cwd) | ||||
|     }, | ||||
|     getBranches: getBranches, | ||||
|     getBranchInfo: getBranchInfo, | ||||
|     checkoutBranch: function(cwd, branchName, isCreate) { | ||||
| @@ -484,5 +501,7 @@ module.exports = { | ||||
|         args.push(branchName); | ||||
|         return runGitCommand(args,cwd); | ||||
|     }, | ||||
|     getBranchStatus: getBranchStatus | ||||
|     getBranchStatus: getBranchStatus, | ||||
|     addRemote: addRemote, | ||||
|     removeRemote: removeRemote | ||||
| } | ||||
|   | ||||
| @@ -96,6 +96,11 @@ function init(_settings, _runtime) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| function getUserGitSettings(user) { | ||||
|     var userSettings = settings.getUserSettings(user)||{}; | ||||
|     return userSettings.git; | ||||
| } | ||||
|  | ||||
| function getBackupFilename(filename) { | ||||
|     var ffName = fspath.basename(filename); | ||||
|     var ffDir = fspath.dirname(filename); | ||||
| @@ -113,10 +118,27 @@ function loadProject(name) { | ||||
|     }) | ||||
| } | ||||
|  | ||||
| function getProject(name) { | ||||
| function listProjects(user) { | ||||
|     return Projects.list(); | ||||
| } | ||||
|  | ||||
| function getProject(user, name) { | ||||
|     checkActiveProject(name); | ||||
|     //return when.resolve(activeProject.info); | ||||
|     return Projects.get(name); | ||||
|     var username; | ||||
|     if (!user) { | ||||
|         username = "_"; | ||||
|     } else { | ||||
|         username = user.username; | ||||
|     } | ||||
|     return Projects.get(name).then(function(project) { | ||||
|         var result = project.toJSON(); | ||||
|         var projectSettings = settings.get("projects").projects; | ||||
|         if (projectSettings[name].git && projectSettings[name].git.user[username]) { | ||||
|             result.git.user = projectSettings[name].git.user[username]; | ||||
|         } | ||||
|         return result; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function checkActiveProject(project) { | ||||
| @@ -125,78 +147,78 @@ function checkActiveProject(project) { | ||||
|         throw new Error("Cannot operate on inactive project wanted:"+project+" current:"+(activeProject&&activeProject.name)); | ||||
|     } | ||||
| } | ||||
| function getFiles(project) { | ||||
| function getFiles(user, project) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.getFiles(); | ||||
| } | ||||
| function stageFile(project,file) { | ||||
| function stageFile(user, project,file) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.stageFile(file); | ||||
| } | ||||
| function unstageFile(project,file) { | ||||
| function unstageFile(user, project,file) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.unstageFile(file); | ||||
| } | ||||
| function commit(project,options) { | ||||
| function commit(user, project,options) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.commit(options); | ||||
|     return activeProject.commit(user, options); | ||||
| } | ||||
| function getFileDiff(project,file,type) { | ||||
| function getFileDiff(user, project,file,type) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.getFileDiff(file,type); | ||||
| } | ||||
| function getCommits(project,options) { | ||||
| function getCommits(user, project,options) { | ||||
|     checkActiveProject(project); | ||||
|         return activeProject.getCommits(options); | ||||
| } | ||||
| function getCommit(project,sha) { | ||||
| function getCommit(user, project,sha) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.getCommit(sha); | ||||
| } | ||||
|  | ||||
| function getFile(project,filePath,sha) { | ||||
| function getFile(user, project,filePath,sha) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.getFile(filePath,sha); | ||||
| } | ||||
| function push(project,remoteBranchName,setRemote) { | ||||
| function push(user, project,remoteBranchName,setRemote) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.push(remoteBranchName,setRemote); | ||||
| } | ||||
| function pull(project,remoteBranchName,setRemote) { | ||||
| function pull(user, project,remoteBranchName,setRemote) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.pull(remoteBranchName,setRemote).then(function() { | ||||
|         return reloadActiveProject("pull"); | ||||
|     }); | ||||
| } | ||||
| function getStatus(project) { | ||||
| function getStatus(user, project) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.status(); | ||||
| } | ||||
| function resolveMerge(project,file,resolution) { | ||||
| function resolveMerge(user, project,file,resolution) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.resolveMerge(file,resolution); | ||||
| } | ||||
| function abortMerge(project) { | ||||
| function abortMerge(user, project) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.abortMerge().then(function() { | ||||
|         return reloadActiveProject("abort-merge") | ||||
|     }); | ||||
| } | ||||
| function getBranches(project,remote) { | ||||
| function getBranches(user, project,isRemote) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.getBranches(remote); | ||||
|     return activeProject.getBranches(isRemote); | ||||
| } | ||||
| function setBranch(project,branchName,isCreate) { | ||||
| function setBranch(user, project,branchName,isCreate) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.setBranch(branchName,isCreate).then(function() { | ||||
|         return reloadActiveProject("change-branch"); | ||||
|     }); | ||||
| } | ||||
| function getBranchStatus(project,branchName) { | ||||
| function getBranchStatus(user, project,branchName) { | ||||
|     checkActiveProject(project); | ||||
|     return activeProject.getBranchStatus(branchName); | ||||
| } | ||||
| function getActiveProject() { | ||||
| function getActiveProject(user) { | ||||
|     return activeProject; | ||||
| } | ||||
|  | ||||
| @@ -212,14 +234,15 @@ function reloadActiveProject(action) { | ||||
|         }); | ||||
|     }); | ||||
| } | ||||
| function createProject(metadata) { | ||||
|     return Projects.create(metadata).then(function(p) { | ||||
|         return setActiveProject(p.name); | ||||
| function createProject(user, metadata) { | ||||
|     // var userSettings = getUserGitSettings(user); | ||||
|     return Projects.create(null,metadata).then(function(p) { | ||||
|         return setActiveProject(user, p.name); | ||||
|     }).then(function() { | ||||
|         return getProject(metadata.name); | ||||
|         return getProject(user, metadata.name); | ||||
|     }) | ||||
| } | ||||
| function setActiveProject(projectName) { | ||||
| function setActiveProject(user, projectName) { | ||||
|     return loadProject(projectName).then(function(project) { | ||||
|         var globalProjectSettings = settings.get("projects"); | ||||
|         globalProjectSettings.activeProject = project.name; | ||||
| @@ -234,7 +257,7 @@ function setActiveProject(projectName) { | ||||
|         }) | ||||
|     }); | ||||
| } | ||||
| function updateProject(project,data) { | ||||
| function updateProject(user, project, data) { | ||||
|     if (!activeProject || activeProject.name !== project) { | ||||
|         // TODO standardise | ||||
|         throw new Error("Cannot update inactive project"); | ||||
| @@ -243,7 +266,7 @@ function updateProject(project,data) { | ||||
|     var isReset = data.resetCredentialSecret; | ||||
|     var wasInvalid = activeProject.credentialSecretInvalid; | ||||
|  | ||||
|     return activeProject.update(data).then(function(result) { | ||||
|     return activeProject.update(user,data).then(function(result) { | ||||
|  | ||||
|         if (result.flowFilesChanged) { | ||||
|             flowsFullPath = activeProject.getFlowFile(); | ||||
| @@ -371,7 +394,7 @@ function saveCredentials(credentials) { | ||||
|  | ||||
| module.exports = { | ||||
|     init: init, | ||||
|     listProjects: Projects.list, | ||||
|     listProjects: listProjects, | ||||
|     getActiveProject: getActiveProject, | ||||
|     setActiveProject: setActiveProject, | ||||
|     getProject: getProject, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user