mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add simplified git workflow to auto-commit changes
This commit is contained in:
parent
e6ffa3d143
commit
69d60ffb24
@ -721,6 +721,12 @@
|
|||||||
"committerTip": "Leave blank to use system default",
|
"committerTip": "Leave blank to use system default",
|
||||||
"userName": "Username",
|
"userName": "Username",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
|
"workflow": "Workflow",
|
||||||
|
"workfowTip": "Choose your preferred git workflow",
|
||||||
|
"workflowManual": "Manual",
|
||||||
|
"workflowManualTip": "All changes must be manually committed under the 'history' sidebar",
|
||||||
|
"workflowAuto": "Automatic",
|
||||||
|
"workflowAutoTip": "Changes are committed automatically with every deploy",
|
||||||
"sshKeys": "SSH Keys",
|
"sshKeys": "SSH Keys",
|
||||||
"sshKeysTip": "Allows you to create secure connections to remote git repositories.",
|
"sshKeysTip": "Allows you to create secure connections to remote git repositories.",
|
||||||
"add": "add key",
|
"add": "add key",
|
||||||
|
@ -1573,8 +1573,6 @@ RED.projects.settings = (function() {
|
|||||||
updateForm();
|
updateForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function createSettingsPane(activeProject) {
|
function createSettingsPane(activeProject) {
|
||||||
var pane = $('<div id="red-ui-project-settings-tab-settings" class="red-ui-project-settings-tab-pane red-ui-help"></div>');
|
var pane = $('<div id="red-ui-project-settings-tab-settings" class="red-ui-project-settings-tab-pane red-ui-help"></div>');
|
||||||
createFilesSection(activeProject,pane);
|
createFilesSection(activeProject,pane);
|
||||||
|
@ -38,13 +38,34 @@ RED.projects.userSettings = (function() {
|
|||||||
$('<label for="user-settings-gitconfig-email"></label>').text(RED._("editor:sidebar.project.userSettings.email")).appendTo(row);
|
$('<label for="user-settings-gitconfig-email"></label>').text(RED._("editor:sidebar.project.userSettings.email")).appendTo(row);
|
||||||
gitEmailInput = $('<input type="text" id="user-settings-gitconfig-email">').appendTo(row);
|
gitEmailInput = $('<input type="text" id="user-settings-gitconfig-email">').appendTo(row);
|
||||||
gitEmailInput.val(currentGitSettings.user.email||"");
|
gitEmailInput.val(currentGitSettings.user.email||"");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function createWorkflowSection(pane) {
|
||||||
|
|
||||||
|
var currentGitSettings = RED.settings.get('git') || {};
|
||||||
|
currentGitSettings.workflow = currentGitSettings.workflow || {};
|
||||||
|
currentGitSettings.workflow.mode = currentGitSettings.workflow.mode || "manual";
|
||||||
|
|
||||||
|
var title = $('<h3></h3>').text(RED._("editor:sidebar.project.userSettings.workflow")).appendTo(pane);
|
||||||
|
|
||||||
|
var workflowContainer = $('<div class="red-ui-settings-section"></div>').appendTo(pane);
|
||||||
|
$('<div class="red-ui-settings-section-description"></div>').appendTo(workflowContainer).text(RED._("editor:sidebar.project.userSettings.workfowTip"));
|
||||||
|
|
||||||
|
var row = $('<div class="red-ui-settings-row"></div>').appendTo(workflowContainer);
|
||||||
|
$('<label><input type="radio" name="user-setting-gitworkflow" value="manual"> <div style="margin-left: 3px; display: inline-block"><div data-i18n="editor:sidebar.project.userSettings.workflowManual"></div><div style="color:#aaa;" data-i18n="editor:sidebar.project.userSettings.workflowManualTip"></div></div></label>').appendTo(row);
|
||||||
|
row = $('<div class="red-ui-settings-row"></div>').appendTo(workflowContainer);
|
||||||
|
$('<label><input type="radio" name="user-setting-gitworkflow" value="auto"> <div style="margin-left: 3px; display: inline-block"><div data-i18n="editor:sidebar.project.userSettings.workflowAuto"></div><div style="color:#aaa;" data-i18n="editor:sidebar.project.userSettings.workflowAutoTip"></div></div></label>').appendTo(row);
|
||||||
|
|
||||||
|
workflowContainer.find('[name="user-setting-gitworkflow"][type="radio"][value="'+currentGitSettings.workflow.mode+'"]').prop('checked',true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function createSSHKeySection(pane) {
|
function createSSHKeySection(pane) {
|
||||||
|
var title = $('<h3></h3>').text(RED._("editor:sidebar.project.userSettings.sshKeys")).appendTo(pane);
|
||||||
var container = $('<div class="red-ui-settings-section"></div>').appendTo(pane);
|
var container = $('<div class="red-ui-settings-section"></div>').appendTo(pane);
|
||||||
var popover;
|
var popover;
|
||||||
var title = $('<h3></h3>').text(RED._("editor:sidebar.project.userSettings.sshKeys")).appendTo(container);
|
|
||||||
var subtitle = $('<div class="red-ui-settings-section-description"></div>').appendTo(container).text(RED._("editor:sidebar.project.userSettings.sshKeysTip"));
|
var subtitle = $('<div class="red-ui-settings-section-description"></div>').appendTo(container).text(RED._("editor:sidebar.project.userSettings.sshKeysTip"));
|
||||||
|
|
||||||
var addKeyButton = $('<button id="user-settings-gitconfig-add-key" class="red-ui-button red-ui-button-small" style="float: right; margin-right: 10px;">'+RED._("editor:sidebar.project.userSettings.add")+'</button>')
|
var addKeyButton = $('<button id="user-settings-gitconfig-add-key" class="red-ui-button red-ui-button-small" style="float: right; margin-right: 10px;">'+RED._("editor:sidebar.project.userSettings.add")+'</button>')
|
||||||
@ -391,6 +412,7 @@ RED.projects.userSettings = (function() {
|
|||||||
function createSettingsPane(activeProject) {
|
function createSettingsPane(activeProject) {
|
||||||
var pane = $('<div id="red-ui-settings-tab-gitconfig" class="project-settings-tab-pane red-ui-help"></div>');
|
var pane = $('<div id="red-ui-settings-tab-gitconfig" class="project-settings-tab-pane red-ui-help"></div>');
|
||||||
createGitUserSection(pane);
|
createGitUserSection(pane);
|
||||||
|
createWorkflowSection(pane);
|
||||||
createSSHKeySection(pane);
|
createSSHKeySection(pane);
|
||||||
return pane;
|
return pane;
|
||||||
}
|
}
|
||||||
@ -407,6 +429,9 @@ RED.projects.userSettings = (function() {
|
|||||||
currentGitSettings.user = currentGitSettings.user || {};
|
currentGitSettings.user = currentGitSettings.user || {};
|
||||||
currentGitSettings.user.name = gitUsernameInput.val();
|
currentGitSettings.user.name = gitUsernameInput.val();
|
||||||
currentGitSettings.user.email = gitEmailInput.val();
|
currentGitSettings.user.email = gitEmailInput.val();
|
||||||
|
currentGitSettings.workflow = currentGitSettings.workflow || {};
|
||||||
|
currentGitSettings.workflow.mode = $('[name="user-setting-gitworkflow"][type="radio"]:checked').val()
|
||||||
|
|
||||||
RED.settings.set('git', currentGitSettings);
|
RED.settings.set('git', currentGitSettings);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -293,14 +293,20 @@ RED.sidebar.versionControl = (function() {
|
|||||||
if (activeProject) {
|
if (activeProject) {
|
||||||
// TODO: this is a full refresh of the files - should be able to
|
// TODO: this is a full refresh of the files - should be able to
|
||||||
// just do an incremental refresh
|
// just do an incremental refresh
|
||||||
allChanges = {};
|
|
||||||
unstagedChangesList.editableList('empty');
|
|
||||||
stagedChangesList.editableList('empty');
|
|
||||||
unmergedChangesList.editableList('empty');
|
|
||||||
|
|
||||||
$.getJSON("projects/"+activeProject.name+"/status",function(result) {
|
var workflowMode = ((RED.settings.get('git') || {}).workflow || {}).mode || "manual";
|
||||||
refreshFiles(result);
|
if (workflowMode === 'auto') {
|
||||||
});
|
refresh(true);
|
||||||
|
} else {
|
||||||
|
allChanges = {};
|
||||||
|
unstagedChangesList.editableList('empty');
|
||||||
|
stagedChangesList.editableList('empty');
|
||||||
|
unmergedChangesList.editableList('empty');
|
||||||
|
|
||||||
|
$.getJSON("projects/"+activeProject.name+"/status",function(result) {
|
||||||
|
refreshFiles(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
RED.events.on("login",function() {
|
RED.events.on("login",function() {
|
||||||
|
@ -79,7 +79,7 @@
|
|||||||
display: table;
|
display: table;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
.uneditable-input, input, textarea {
|
.uneditable-input, input[type="text"],input[type="password"], textarea {
|
||||||
width: calc(100% - 150px);
|
width: calc(100% - 150px);
|
||||||
}
|
}
|
||||||
textarea {
|
textarea {
|
||||||
|
@ -88,7 +88,7 @@ var api = module.exports = {
|
|||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apiPromise = runtime.nodes.setFlows(flows.flows,flows.credentials,deploymentType);
|
apiPromise = runtime.nodes.setFlows(flows.flows,flows.credentials,deploymentType,null,null,opts.user);
|
||||||
}
|
}
|
||||||
apiPromise.then(function(flowId) {
|
apiPromise.then(function(flowId) {
|
||||||
return resolve({rev:flowId});
|
return resolve({rev:flowId});
|
||||||
@ -98,7 +98,7 @@ var api = module.exports = {
|
|||||||
return reject(err);
|
return reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,7 +114,7 @@ var api = module.exports = {
|
|||||||
return mutex.runExclusive(function() {
|
return mutex.runExclusive(function() {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var flow = opts.flow;
|
var flow = opts.flow;
|
||||||
runtime.nodes.addFlow(flow).then(function (id) {
|
runtime.nodes.addFlow(flow,opts.user).then(function (id) {
|
||||||
runtime.log.audit({event: "flow.add", id: id}, opts.req);
|
runtime.log.audit({event: "flow.add", id: id}, opts.req);
|
||||||
return resolve(id);
|
return resolve(id);
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
@ -170,7 +170,7 @@ var api = module.exports = {
|
|||||||
var flow = opts.flow;
|
var flow = opts.flow;
|
||||||
var id = opts.id;
|
var id = opts.id;
|
||||||
try {
|
try {
|
||||||
runtime.nodes.updateFlow(id, flow).then(function () {
|
runtime.nodes.updateFlow(id, flow, opts.user).then(function () {
|
||||||
runtime.log.audit({event: "flow.update", id: id}, opts.req);
|
runtime.log.audit({event: "flow.update", id: id}, opts.req);
|
||||||
return resolve(id);
|
return resolve(id);
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
@ -216,7 +216,7 @@ var api = module.exports = {
|
|||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
var id = opts.id;
|
var id = opts.id;
|
||||||
try {
|
try {
|
||||||
runtime.nodes.removeFlow(id).then(function () {
|
runtime.nodes.removeFlow(id, opts.user).then(function () {
|
||||||
runtime.log.audit({event: "flow.remove", id: id}, opts.req);
|
runtime.log.audit({event: "flow.remove", id: id}, opts.req);
|
||||||
return resolve();
|
return resolve();
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
|
@ -115,7 +115,7 @@ function load(forceStart) {
|
|||||||
* type - full/nodes/flows/load (default full)
|
* type - full/nodes/flows/load (default full)
|
||||||
* muteLog - don't emit the standard log messages (used for individual flow api)
|
* muteLog - don't emit the standard log messages (used for individual flow api)
|
||||||
*/
|
*/
|
||||||
function setFlows(_config,_credentials,type,muteLog,forceStart) {
|
function setFlows(_config,_credentials,type,muteLog,forceStart,user) {
|
||||||
if (typeof _credentials === "string") {
|
if (typeof _credentials === "string") {
|
||||||
type = _credentials;
|
type = _credentials;
|
||||||
_credentials = null;
|
_credentials = null;
|
||||||
@ -186,7 +186,7 @@ function setFlows(_config,_credentials,type,muteLog,forceStart) {
|
|||||||
credentialsDirty:credsDirty,
|
credentialsDirty:credsDirty,
|
||||||
credentials: creds
|
credentials: creds
|
||||||
}
|
}
|
||||||
return storage.saveFlows(saveConfig);
|
return storage.saveFlows(saveConfig, user);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,7 +481,7 @@ function updateMissingTypes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addFlow(flow) {
|
function addFlow(flow, user) {
|
||||||
var i,node;
|
var i,node;
|
||||||
if (!flow.hasOwnProperty('nodes')) {
|
if (!flow.hasOwnProperty('nodes')) {
|
||||||
throw new Error('missing nodes property');
|
throw new Error('missing nodes property');
|
||||||
@ -531,7 +531,7 @@ function addFlow(flow) {
|
|||||||
var newConfig = clone(activeConfig.flows);
|
var newConfig = clone(activeConfig.flows);
|
||||||
newConfig = newConfig.concat(nodes);
|
newConfig = newConfig.concat(nodes);
|
||||||
|
|
||||||
return setFlows(newConfig,null,'flows',true).then(function() {
|
return setFlows(newConfig, null, 'flows', true, null, user).then(function() {
|
||||||
log.info(log._("nodes.flows.added-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"}));
|
log.info(log._("nodes.flows.added-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"}));
|
||||||
return flow.id;
|
return flow.id;
|
||||||
});
|
});
|
||||||
@ -607,7 +607,7 @@ function getFlow(id) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFlow(id,newFlow) {
|
function updateFlow(id,newFlow, user) {
|
||||||
var label = id;
|
var label = id;
|
||||||
if (id !== 'global') {
|
if (id !== 'global') {
|
||||||
if (!activeFlowConfig.flows[id]) {
|
if (!activeFlowConfig.flows[id]) {
|
||||||
@ -662,12 +662,12 @@ function updateFlow(id,newFlow) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newConfig = newConfig.concat(nodes);
|
newConfig = newConfig.concat(nodes);
|
||||||
return setFlows(newConfig,null,'flows',true).then(function() {
|
return setFlows(newConfig, null, 'flows', true, null, user).then(function() {
|
||||||
log.info(log._("nodes.flows.updated-flow",{label:(label?label+" ":"")+"["+id+"]"}));
|
log.info(log._("nodes.flows.updated-flow",{label:(label?label+" ":"")+"["+id+"]"}));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFlow(id) {
|
function removeFlow(id, user) {
|
||||||
if (id === 'global') {
|
if (id === 'global') {
|
||||||
// TODO: nls + error code
|
// TODO: nls + error code
|
||||||
throw new Error('not allowed to remove global');
|
throw new Error('not allowed to remove global');
|
||||||
@ -684,7 +684,7 @@ function removeFlow(id) {
|
|||||||
return node.z !== id && node.id !== id;
|
return node.z !== id && node.id !== id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return setFlows(newConfig,null,'flows',true).then(function() {
|
return setFlows(newConfig, null, 'flows', true, null, user).then(function() {
|
||||||
log.info(log._("nodes.flows.removed-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"}));
|
log.info(log._("nodes.flows.removed-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ var storageModuleInterface = {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
saveFlows: function(config) {
|
saveFlows: function(config, user) {
|
||||||
var flows = config.flows;
|
var flows = config.flows;
|
||||||
var credentials = config.credentials;
|
var credentials = config.credentials;
|
||||||
var credentialSavePromise;
|
var credentialSavePromise;
|
||||||
@ -94,7 +94,7 @@ var storageModuleInterface = {
|
|||||||
delete config.credentialsDirty;
|
delete config.credentialsDirty;
|
||||||
|
|
||||||
return credentialSavePromise.then(function() {
|
return credentialSavePromise.then(function() {
|
||||||
return storageModule.saveFlows(flows).then(function() {
|
return storageModule.saveFlows(flows, user).then(function() {
|
||||||
return crypto.createHash('md5').update(JSON.stringify(config.flows)).digest("hex");
|
return crypto.createHash('md5').update(JSON.stringify(config.flows)).digest("hex");
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -40,16 +40,22 @@ function getSSHKeyUsername(userObj) {
|
|||||||
}
|
}
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
function getGitUser(user) {
|
|
||||||
|
function getUserGitSettings(user) {
|
||||||
var username;
|
var username;
|
||||||
if (!user) {
|
if (!user) {
|
||||||
username = "_";
|
username = "_";
|
||||||
} else {
|
} else {
|
||||||
username = user.username;
|
username = user.username;
|
||||||
}
|
}
|
||||||
var userSettings = settings.getUserSettings(username);
|
var userSettings = settings.getUserSettings(username)||{};
|
||||||
if (userSettings && userSettings.git) {
|
return userSettings.git;
|
||||||
return userSettings.git.user;
|
}
|
||||||
|
|
||||||
|
function getGitUser(user) {
|
||||||
|
var gitSettings = getUserGitSettings(user);
|
||||||
|
if (gitSettings) {
|
||||||
|
return gitSettings.user;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -172,7 +178,7 @@ Project.prototype.initialise = function(user,data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return when.all(promises).then(function() {
|
return Promise.all(promises).then(function() {
|
||||||
return gitTools.stageFile(project.path,files);
|
return gitTools.stageFile(project.path,files);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
return gitTools.commit(project.path,"Create project files",getGitUser(user));
|
return gitTools.commit(project.path,"Create project files",getGitUser(user));
|
||||||
@ -390,11 +396,15 @@ Project.prototype.update = function (user, data) {
|
|||||||
if (saveSettings) {
|
if (saveSettings) {
|
||||||
promises.push(settings.set("projects",globalProjectSettings));
|
promises.push(settings.set("projects",globalProjectSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var modifiedFiles = [];
|
||||||
|
|
||||||
if (saveREADME) {
|
if (saveREADME) {
|
||||||
promises.push(util.writeFile(fspath.join(this.path,this.paths['README.md']), this.description));
|
promises.push(util.writeFile(fspath.join(this.path,this.paths['README.md']), this.description));
|
||||||
|
modifiedFiles.push('README.md');
|
||||||
}
|
}
|
||||||
if (savePackage) {
|
if (savePackage) {
|
||||||
promises.push(fs.readFile(fspath.join(project.path,project.paths['package.json']),"utf8").then(content => {
|
promises.push(fs.readFile(fspath.join(this.path,this.paths['package.json']),"utf8").then(content => {
|
||||||
var currentPackage = {};
|
var currentPackage = {};
|
||||||
try {
|
try {
|
||||||
currentPackage = util.parseJSON(content);
|
currentPackage = util.parseJSON(content);
|
||||||
@ -403,12 +413,22 @@ Project.prototype.update = function (user, data) {
|
|||||||
this.package = Object.assign(currentPackage,this.package);
|
this.package = Object.assign(currentPackage,this.package);
|
||||||
return util.writeFile(fspath.join(project.path,this.paths['package.json']), JSON.stringify(this.package,"",4));
|
return util.writeFile(fspath.join(project.path,this.paths['package.json']), JSON.stringify(this.package,"",4));
|
||||||
}));
|
}));
|
||||||
|
modifiedFiles.push('package.json');
|
||||||
}
|
}
|
||||||
return when.settle(promises).then(res => {
|
return when.settle(promises).then(function(res) {
|
||||||
|
var gitSettings = getUserGitSettings(user) || {};
|
||||||
|
var workflowMode = (gitSettings.workflow||{}).mode || "manual";
|
||||||
|
if (workflowMode === 'auto') {
|
||||||
|
return project.stageFile(modifiedFiles.map(f => project.paths[f])).then(() => {
|
||||||
|
return project.commit(user,{message:"Update "+modifiedFiles.join(", ")})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
if (reloadProject) {
|
if (reloadProject) {
|
||||||
return this.load()
|
return this.load()
|
||||||
}
|
}
|
||||||
}).then(() => { return {
|
}).then(function() {
|
||||||
|
return {
|
||||||
flowFilesChanged: flowFilesChanged,
|
flowFilesChanged: flowFilesChanged,
|
||||||
credentialSecretChanged: credentialSecretChanged
|
credentialSecretChanged: credentialSecretChanged
|
||||||
}})
|
}})
|
||||||
@ -910,7 +930,7 @@ function createDefaultProject(user, project) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return when.all(promises).then(function() {
|
return Promise.all(promises).then(function() {
|
||||||
return gitTools.stageFile(projectPath,files);
|
return gitTools.stageFile(projectPath,files);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
return gitTools.commit(projectPath,"Create project",getGitUser(user));
|
return gitTools.commit(projectPath,"Create project",getGitUser(user));
|
||||||
|
@ -190,7 +190,13 @@ function listProjects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getUserGitSettings(user) {
|
function getUserGitSettings(user) {
|
||||||
var userSettings = settings.getUserSettings(user)||{};
|
var username;
|
||||||
|
if (!user) {
|
||||||
|
username = "_";
|
||||||
|
} else {
|
||||||
|
username = user.username;
|
||||||
|
}
|
||||||
|
var userSettings = settings.getUserSettings(username)||{};
|
||||||
return userSettings.git;
|
return userSettings.git;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +368,6 @@ function reloadActiveProject(action) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function createProject(user, metadata) {
|
function createProject(user, metadata) {
|
||||||
// var userSettings = getUserGitSettings(user);
|
|
||||||
if (metadata.files && metadata.migrateFiles) {
|
if (metadata.files && metadata.migrateFiles) {
|
||||||
// We expect there to be no active project in this scenario
|
// We expect there to be no active project in this scenario
|
||||||
if (activeProject) {
|
if (activeProject) {
|
||||||
@ -549,7 +554,7 @@ function getFlows() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveFlows(flows) {
|
function saveFlows(flows, user) {
|
||||||
if (settings.readOnly) {
|
if (settings.readOnly) {
|
||||||
return when.resolve();
|
return when.resolve();
|
||||||
}
|
}
|
||||||
@ -569,7 +574,15 @@ function saveFlows(flows) {
|
|||||||
} else {
|
} else {
|
||||||
flowData = JSON.stringify(flows);
|
flowData = JSON.stringify(flows);
|
||||||
}
|
}
|
||||||
return util.writeFile(flowsFullPath, flowData, flowsFileBackup);
|
return util.writeFile(flowsFullPath, flowData, flowsFileBackup).then(() => {
|
||||||
|
var gitSettings = getUserGitSettings(user) || {};
|
||||||
|
var workflowMode = (gitSettings.workflow||{}).mode || "manual";
|
||||||
|
if (activeProject && workflowMode === 'auto') {
|
||||||
|
return activeProject.stageFile([flowsFullPath, credentialsFile]).then(() => {
|
||||||
|
return activeProject.commit(user,{message:"Update flow files"})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCredentials() {
|
function getCredentials() {
|
||||||
|
@ -45,7 +45,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should initialise the user directory',function(done) {
|
it('should initialise the user directory',function(done) {
|
||||||
localfilesystem.init({userDir:userDir}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
fs.existsSync(path.join(userDir,"lib")).should.be.true();
|
fs.existsSync(path.join(userDir,"lib")).should.be.true();
|
||||||
fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true();
|
fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true();
|
||||||
done();
|
done();
|
||||||
@ -60,7 +60,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
process.env.NODE_RED_HOME = path.join(userDir,"NRH");
|
process.env.NODE_RED_HOME = path.join(userDir,"NRH");
|
||||||
fs.mkdirSync(process.env.NODE_RED_HOME);
|
fs.mkdirSync(process.env.NODE_RED_HOME);
|
||||||
fs.writeFileSync(path.join(process.env.NODE_RED_HOME,".config.json"),"{}","utf8");
|
fs.writeFileSync(path.join(process.env.NODE_RED_HOME,".config.json"),"{}","utf8");
|
||||||
var settings = {};
|
var settings = {getUserSettings: () => {{}}};
|
||||||
localfilesystem.init(settings, mockRuntime).then(function() {
|
localfilesystem.init(settings, mockRuntime).then(function() {
|
||||||
try {
|
try {
|
||||||
fs.existsSync(path.join(process.env.NODE_RED_HOME,"lib")).should.be.true();
|
fs.existsSync(path.join(process.env.NODE_RED_HOME,"lib")).should.be.true();
|
||||||
@ -85,7 +85,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
fs.mkdirSync(process.env.HOMEPATH);
|
fs.mkdirSync(process.env.HOMEPATH);
|
||||||
fs.mkdirSync(path.join(process.env.HOMEPATH,".node-red"));
|
fs.mkdirSync(path.join(process.env.HOMEPATH,".node-red"));
|
||||||
fs.writeFileSync(path.join(process.env.HOMEPATH,".node-red",".config.json"),"{}","utf8");
|
fs.writeFileSync(path.join(process.env.HOMEPATH,".node-red",".config.json"),"{}","utf8");
|
||||||
var settings = {};
|
var settings = {getUserSettings: () => {{}}};
|
||||||
localfilesystem.init(settings, mockRuntime).then(function() {
|
localfilesystem.init(settings, mockRuntime).then(function() {
|
||||||
try {
|
try {
|
||||||
fs.existsSync(path.join(process.env.HOMEPATH,".node-red","lib")).should.be.true();
|
fs.existsSync(path.join(process.env.HOMEPATH,".node-red","lib")).should.be.true();
|
||||||
@ -112,7 +112,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
|
process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
|
||||||
|
|
||||||
fs.mkdirSync(process.env.HOME);
|
fs.mkdirSync(process.env.HOME);
|
||||||
var settings = {};
|
var settings = {getUserSettings: () => {{}}};
|
||||||
localfilesystem.init(settings, mockRuntime).then(function() {
|
localfilesystem.init(settings, mockRuntime).then(function() {
|
||||||
try {
|
try {
|
||||||
fs.existsSync(path.join(process.env.HOME,".node-red","lib")).should.be.true();
|
fs.existsSync(path.join(process.env.HOME,".node-red","lib")).should.be.true();
|
||||||
@ -142,7 +142,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
process.env.USERPROFILE = path.join(userDir,"USERPROFILE");
|
process.env.USERPROFILE = path.join(userDir,"USERPROFILE");
|
||||||
|
|
||||||
fs.mkdirSync(process.env.USERPROFILE);
|
fs.mkdirSync(process.env.USERPROFILE);
|
||||||
var settings = {};
|
var settings = {getUserSettings: () => {{}}};
|
||||||
localfilesystem.init(settings, mockRuntime).then(function() {
|
localfilesystem.init(settings, mockRuntime).then(function() {
|
||||||
try {
|
try {
|
||||||
fs.existsSync(path.join(process.env.USERPROFILE,".node-red","lib")).should.be.true();
|
fs.existsSync(path.join(process.env.USERPROFILE,".node-red","lib")).should.be.true();
|
||||||
@ -163,7 +163,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle missing flow file',function(done) {
|
it('should handle missing flow file',function(done) {
|
||||||
localfilesystem.init({userDir:userDir}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
fs.existsSync(flowFilePath).should.be.false();
|
fs.existsSync(flowFilePath).should.be.false();
|
||||||
@ -179,7 +179,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle empty flow file, no backup',function(done) {
|
it('should handle empty flow file, no backup',function(done) {
|
||||||
localfilesystem.init({userDir:userDir}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
||||||
@ -197,7 +197,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should handle empty flow file, restores backup',function(done) {
|
it('should handle empty flow file, restores backup',function(done) {
|
||||||
localfilesystem.init({userDir:userDir}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
||||||
@ -220,7 +220,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should save flows to the default file',function(done) {
|
it('should save flows to the default file',function(done) {
|
||||||
localfilesystem.init({userDir:userDir}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
var flowFile = 'flows_'+require('os').hostname()+'.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
||||||
@ -249,7 +249,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
var flowFile = 'test.json';
|
var flowFile = 'test.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
|
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
fs.existsSync(defaultFlowFilePath).should.be.false();
|
fs.existsSync(defaultFlowFilePath).should.be.false();
|
||||||
fs.existsSync(flowFilePath).should.be.false();
|
fs.existsSync(flowFilePath).should.be.false();
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
it('should format the flows file when flowFilePretty specified',function(done) {
|
it('should format the flows file when flowFilePretty specified',function(done) {
|
||||||
var flowFile = 'test.json';
|
var flowFile = 'test.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,flowFilePretty:true}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,flowFilePretty:true,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
localfilesystem.saveFlows(testFlow).then(function() {
|
localfilesystem.saveFlows(testFlow).then(function() {
|
||||||
var content = fs.readFileSync(flowFilePath,"utf8");
|
var content = fs.readFileSync(flowFilePath,"utf8");
|
||||||
content.split("\n").length.should.be.above(1);
|
content.split("\n").length.should.be.above(1);
|
||||||
@ -294,7 +294,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
it('should fsync the flows file',function(done) {
|
it('should fsync the flows file',function(done) {
|
||||||
var flowFile = 'test.json';
|
var flowFile = 'test.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
localfilesystem.init({editorTheme:{projects:{enabled:false}},userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({editorTheme:{projects:{enabled:false}},userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
sinon.spy(fs,"fsync");
|
sinon.spy(fs,"fsync");
|
||||||
localfilesystem.saveFlows(testFlow).then(function() {
|
localfilesystem.saveFlows(testFlow).then(function() {
|
||||||
fs.fsync.callCount.should.be.greaterThan(0);
|
fs.fsync.callCount.should.be.greaterThan(0);
|
||||||
@ -312,7 +312,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
it('should log fsync errors and continue',function(done) {
|
it('should log fsync errors and continue',function(done) {
|
||||||
var flowFile = 'test.json';
|
var flowFile = 'test.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
sinon.stub(fs,"fsync", function(fd, cb) {
|
sinon.stub(fs,"fsync", function(fd, cb) {
|
||||||
cb(new Error());
|
cb(new Error());
|
||||||
});
|
});
|
||||||
@ -338,7 +338,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
|
||||||
|
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
fs.existsSync(defaultFlowFilePath).should.be.false();
|
fs.existsSync(defaultFlowFilePath).should.be.false();
|
||||||
fs.existsSync(flowFilePath).should.be.false();
|
fs.existsSync(flowFilePath).should.be.false();
|
||||||
fs.existsSync(flowFileBackupPath).should.be.false();
|
fs.existsSync(flowFileBackupPath).should.be.false();
|
||||||
@ -378,7 +378,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
var flowFile = 'test.json';
|
var flowFile = 'test.json';
|
||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var credFile = path.join(userDir,"test_cred.json");
|
var credFile = path.join(userDir,"test_cred.json");
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
fs.existsSync(credFile).should.be.false();
|
fs.existsSync(credFile).should.be.false();
|
||||||
|
|
||||||
localfilesystem.getCredentials().then(function(creds) {
|
localfilesystem.getCredentials().then(function(creds) {
|
||||||
@ -397,7 +397,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var credFile = path.join(userDir,"test_cred.json");
|
var credFile = path.join(userDir,"test_cred.json");
|
||||||
|
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
|
|
||||||
fs.existsSync(credFile).should.be.false();
|
fs.existsSync(credFile).should.be.false();
|
||||||
|
|
||||||
@ -426,7 +426,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
var credFile = path.join(userDir,"test_cred.json");
|
var credFile = path.join(userDir,"test_cred.json");
|
||||||
var credFileBackup = path.join(userDir,".test_cred.json.backup");
|
var credFileBackup = path.join(userDir,".test_cred.json.backup");
|
||||||
|
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
|
|
||||||
fs.writeFileSync(credFile,"{}","utf8");
|
fs.writeFileSync(credFile,"{}","utf8");
|
||||||
|
|
||||||
@ -452,7 +452,7 @@ describe('storage/localfilesystem', function() {
|
|||||||
var flowFilePath = path.join(userDir,flowFile);
|
var flowFilePath = path.join(userDir,flowFile);
|
||||||
var credFile = path.join(userDir,"test_cred.json");
|
var credFile = path.join(userDir,"test_cred.json");
|
||||||
|
|
||||||
localfilesystem.init({userDir:userDir, flowFile:flowFilePath, flowFilePretty:true}, mockRuntime).then(function() {
|
localfilesystem.init({userDir:userDir, flowFile:flowFilePath, flowFilePretty:true,getUserSettings: () => {{}}}, mockRuntime).then(function() {
|
||||||
|
|
||||||
fs.existsSync(credFile).should.be.false();
|
fs.existsSync(credFile).should.be.false();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user