|
|
|
|
|
|
|
|
var getTaskWithElevation = function(tasdef){ |
|
|
var getTaskWithElevation = function(tasdef){ |
|
|
return ()=>{ |
|
|
return ()=>{ |
|
|
if (__isElevated) { |
|
|
if (__isElevated) { |
|
|
return tasdef.elevatedpulltasks(); |
|
|
|
|
|
|
|
|
return tasdef.elevatedpulltasks().then(()=>{ |
|
|
|
|
|
// PB : TODO -- Every elevation should have its own messaging file. Async writes from multiple processes are a problem here... |
|
|
|
|
|
fs.writeFileSync('run.done', 'success') |
|
|
|
|
|
}).catch(e=>{ |
|
|
|
|
|
fs.writeFileSync('run.done', 'failure') |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
// PB : TODO -- Rename op['runas'] to 'elevate' |
|
|
// PB : TODO -- Rename op['runas'] to 'elevate' |
|
|
|
|
|
|
|
|
console.error(e) |
|
|
console.error(e) |
|
|
}) |
|
|
}) |
|
|
.finally(() => { |
|
|
.finally(() => { |
|
|
|
|
|
fs.unlinkSync('run.done') |
|
|
if (!processedArgs.runas) { return tasdef.regularpulltasks(); } |
|
|
if (!processedArgs.runas) { return tasdef.regularpulltasks(); } |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// git remote equivalents... |
|
|
// git remote equivalents... |
|
|
// git branch --set-upstream-to=elixir-unc/master master |
|
|
// git branch --set-upstream-to=elixir-unc/master master |
|
|
// git push --set-upstream elixir-unc branch.. |
|
|
// git push --set-upstream elixir-unc branch.. |
|
|
, 'set-url': (remotename, url) => { |
|
|
|
|
|
|
|
|
, 'remote set-url': (args) => { |
|
|
// git remote set-url elixir-unc //10.10.5.60/gitrepo/chess/bbhverse |
|
|
// git remote set-url elixir-unc //10.10.5.60/gitrepo/chess/bbhverse |
|
|
|
|
|
var __args = { |
|
|
|
|
|
remotename : args.remotename || processedArgs._[2] |
|
|
|
|
|
, url : args.url || processedArgs._[3] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// pushable doesn't mean the remote doesn't support being pushed to. |
|
|
|
|
|
// Over here it just means we are disabling pushing to that remote by setting the push portion of the url the a junk remote called no-pushing. |
|
|
|
|
|
// PB : TODO -- change this to enablepushing. |
|
|
|
|
|
// By default pushing should be disabled. Also developers permissions on the remote is a secondary check for pushing. |
|
|
var pushable = processedArgs.pushable || false; |
|
|
var pushable = processedArgs.pushable || false; |
|
|
remotename = remotename || processedArgs._[1] |
|
|
|
|
|
url = url || processedArgs._[2] |
|
|
|
|
|
|
|
|
remotename = __args.remotename |
|
|
|
|
|
url = __args.url |
|
|
var serial_perform_git_seturl = (repo) => { |
|
|
var serial_perform_git_seturl = (repo) => { |
|
|
var options = { cwd: instanceroot + '/' + repo } |
|
|
var options = { cwd: instanceroot + '/' + repo } |
|
|
// console.log(repo) |
|
|
// console.log(repo) |
|
|
|
|
|
|
|
|
] |
|
|
] |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
console.error('not supported for non-pushable') |
|
|
|
|
|
|
|
|
return [ |
|
|
|
|
|
['git', ['remote', 'set-url', remotename, url + '/' + repo], { cwd: instanceroot + '/' + repo }] |
|
|
|
|
|
, ['git', ['remote', `set-url`, '--push', remotename, 'no-pushing'], { cwd: instanceroot + '/' + repo }] |
|
|
|
|
|
] |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var x = (args) => { |
|
|
var x = (args) => { |
|
|
return () => { |
|
|
|
|
|
|
|
|
var tasq = () => { |
|
|
// console.log(args) |
|
|
// console.log(args) |
|
|
return nodeShellExec.apply(null, args) |
|
|
|
|
|
|
|
|
return nodeShellExec.apply(null, args).catch(e => { |
|
|
|
|
|
// We continue on failure. |
|
|
|
|
|
console.error(tasq.toString()) |
|
|
|
|
|
}) |
|
|
} |
|
|
} |
|
|
// return Promise.resolve(true) |
|
|
|
|
|
|
|
|
tasq.toString = function(){ |
|
|
|
|
|
return JSON.stringify(args) |
|
|
|
|
|
} |
|
|
|
|
|
return tasq; |
|
|
} |
|
|
} |
|
|
var perform_git_seturl = (dir) => { |
|
|
var perform_git_seturl = (dir) => { |
|
|
op['is-git-repo'](dir).then((logEntry) => { |
|
|
op['is-git-repo'](dir).then((logEntry) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dirs(perform_git_add) |
|
|
dirs(perform_git_add) |
|
|
} |
|
|
} |
|
|
, 'remove': (remotename) => { |
|
|
|
|
|
remotename = remotename || processedArgs._[1] |
|
|
|
|
|
|
|
|
, 'remote remove': (args) => { |
|
|
|
|
|
|
|
|
|
|
|
var __args = { |
|
|
|
|
|
remotename : args.remotename|| processedArgs._[2] |
|
|
|
|
|
} |
|
|
|
|
|
var remotename = __args.remotename |
|
|
var serial_perform_git_remove = (repo) => { |
|
|
var serial_perform_git_remove = (repo) => { |
|
|
var options = { cwd: instanceroot + '/' + repo } |
|
|
var options = { cwd: instanceroot + '/' + repo } |
|
|
// console.log(repo) |
|
|
// console.log(repo) |
|
|
|
|
|
|
|
|
any(serial_perform_git_remove(dir.name).map(x)) |
|
|
any(serial_perform_git_remove(dir.name).map(x)) |
|
|
}) |
|
|
}) |
|
|
.catch((e) => { |
|
|
.catch((e) => { |
|
|
console.log('skipped : ' + dir.name + ', reason : No remote named origin') |
|
|
|
|
|
|
|
|
console.log('skipped : ' + dir.name + `, reason : No remote named ${remotename}`) |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
// else console.log('Skipped : Not a Git Repo : ' + dir.name) |
|
|
// else console.log('Skipped : Not a Git Repo : ' + dir.name) |
|
|
|
|
|
|
|
|
var util = require('util'); |
|
|
var util = require('util'); |
|
|
var cliname = 'elxr'; |
|
|
var cliname = 'elxr'; |
|
|
var ver = '1.1'; |
|
|
var ver = '1.1'; |
|
|
var help = `# list of commands... please refer dveloper documentation for ${cliname} |
|
|
|
|
|
|
|
|
var readme = ` |
|
|
|
|
|
Command syntax examples |
|
|
|
|
|
|
|
|
|
|
|
elxr |
|
|
|
|
|
Displays help. Same as elxr h |
|
|
|
|
|
|
|
|
|
|
|
elxr i |
|
|
|
|
|
Runs interactive propmts to help choose installation options. |
|
|
|
|
|
|
|
|
|
|
|
NODE_ENV={{yourenvironment}} elxr {{cmd}} {{instancename}} {{otheroptions}} |
|
|
|
|
|
General command syntax. |
|
|
|
|
|
Eg: NODE_ENV=development elxr pull elixir |
|
|
|
|
|
|
|
|
|
|
|
Note : Although {{instancename}} is generally a positional parameter supplied immediately after the cmd for most cmd's. |
|
|
|
|
|
The specific cmd defines what the value is interpreted as. |
|
|
|
|
|
There are several cmds that do not require an {{instancename}} parameter. |
|
|
|
|
|
Eg: elxr remote remove origin |
|
|
|
|
|
Git operations or passthrough external commands on all repository folders in you working directory. |
|
|
|
|
|
|
|
|
|
|
|
Main objectives. |
|
|
|
|
|
elxr cli is a wrapper around other shell commands and api based operations. |
|
|
|
|
|
One of the main objetives it achives is ease of use of repeating an individual cmd multiple times on all targets. |
|
|
|
|
|
Eg: A git operation like pull can be repeated consistently on a set of git repositories. |
|
|
|
|
|
|
|
|
|
|
|
`; |
|
|
|
|
|
var help = ` |
|
|
|
|
|
${readme} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# list of commands... please refer dveloper documentation for ${cliname} |
|
|
${ |
|
|
${ |
|
|
// util.inspect( |
|
|
// util.inspect( |
|
|
[Object.keys(op)] |
|
|
[Object.keys(op)] |
|
|
|
|
|
|
|
|
if(def.elevatedRepos){ |
|
|
if(def.elevatedRepos){ |
|
|
elevatedpulltasks = function() { |
|
|
elevatedpulltasks = function() { |
|
|
return any(def.elevatedRepos.map((def) => performPull(def.repo))).then(() => { |
|
|
return any(def.elevatedRepos.map((def) => performPull(def.repo))).then(() => { |
|
|
// fs.writeFileSync('run.done', 'success') |
|
|
|
|
|
return true; |
|
|
return true; |
|
|
}).catch((e) => { |
|
|
}).catch((e) => { |
|
|
console.error(e) |
|
|
console.error(e) |
|
|
fs.writeFileSync('run.done', 'error') |
|
|
|
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function preworkerconfig(){ |
|
|
|
|
|
// Everything runs after this check is completed. Elevation occurs out of process when needed. |
|
|
|
|
|
gitRepos = repomanifest.repos |
|
|
|
|
|
// gitRepos = ['chess-server-lib']; |
|
|
|
|
|
|
|
|
|
|
|
// Repositiories that have symlinks that require elevated priviletes in windows to create symlinks |
|
|
|
|
|
elevatedRunasRepos = repomanifest.elevated |
|
|
|
|
|
// Repos that should excluded from merge for releases... |
|
|
|
|
|
exludeMergeRepos = repomanifest.exludeMergeRepos |
|
|
|
|
|
|
|
|
|
|
|
// mysqldump --add-drop-table --no-data -u root -p db_name | grep 'DROP TABLE' ) > drop_all_tables.sql |
|
|
|
|
|
// mysql -u root -p db_name < drop_all_tables.sql |
|
|
|
|
|
|
|
|
|
|
|
var mysql = '../xampp/mysql/bin/mysql' |
|
|
|
|
|
var mysqldump = '../xampp/mysql/bin/mysqldump' |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The main elxr cli process |
|
|
// The main elxr cli process |
|
|
function elxrworker() { |
|
|
function elxrworker() { |
|
|
// Everything runs after this check is completed. Elevation occurs out of process when needed. |
|
|
|
|
|
gitRepos = repomanifest.repos |
|
|
|
|
|
// gitRepos = ['chess-server-lib']; |
|
|
|
|
|
|
|
|
|
|
|
// Repositiories that have symlinks that require elevated priviletes in windows to create symlinks |
|
|
|
|
|
elevatedRunasRepos = repomanifest.elevated |
|
|
|
|
|
// Repos that should excluded from merge for releases... |
|
|
|
|
|
exludeMergeRepos = repomanifest.exludeMergeRepos |
|
|
|
|
|
|
|
|
var subcommandlabels = { |
|
|
|
|
|
remote : `remote ${processedArgs._[1]}` |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
var env = Object.assign({}, process.env); // Shallow clone it. |
|
|
|
|
|
var __runcmd = function (label) { |
|
|
var __runcmd = function (label) { |
|
|
return op[label] ? op[label]() : null; |
|
|
|
|
|
|
|
|
var distinquishedlabel = subcommandlabels[label] || label |
|
|
|
|
|
return op[distinquishedlabel] ? op[distinquishedlabel](processedArgs) : null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// mysqldump --add-drop-table --no-data -u root -p db_name | grep 'DROP TABLE' ) > drop_all_tables.sql |
|
|
|
|
|
// mysql -u root -p db_name < drop_all_tables.sql |
|
|
|
|
|
|
|
|
|
|
|
var mysql = '../xampp/mysql/bin/mysql' |
|
|
|
|
|
var mysqldump = '../xampp/mysql/bin/mysqldump' |
|
|
|
|
|
|
|
|
|
|
|
// --runas |
|
|
// --runas |
|
|
if (processedArgs.runas) { |
|
|
if (processedArgs.runas) { |
|
|
|
|
|
|
|
|
return Promise.all(downloadtasks).then(() => { return any(installtasks) }) |
|
|
return Promise.all(downloadtasks).then(() => { return any(installtasks) }) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var getPromptableAsyncPropDescriptor = function(propName, choices, defaultchoise){ |
|
|
|
|
|
return { |
|
|
|
|
|
get (){ |
|
|
|
|
|
return cli.prompt( choices, propName, defaultchoise).then(propValue => { |
|
|
|
|
|
Object.defineProperty(this, propName, { |
|
|
|
|
|
value: propValue, |
|
|
|
|
|
writable: false, |
|
|
|
|
|
configurable : true |
|
|
|
|
|
}); |
|
|
|
|
|
return propValue |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
// , set (propValue){ |
|
|
|
|
|
// Object.defineProperty(this, propName, { |
|
|
|
|
|
// value: propValue, |
|
|
|
|
|
// writable: false, |
|
|
|
|
|
// configurable : true |
|
|
|
|
|
// }) |
|
|
|
|
|
// return propValue; |
|
|
|
|
|
// } |
|
|
|
|
|
, configurable : true |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// function updateselection(selected) { selectedinstance = utils.assign(selectedinstance, selected) } |
|
|
// function updateselection(selected) { selectedinstance = utils.assign(selectedinstance, selected) } |
|
|
var selectedinstance = null; |
|
|
var selectedinstance = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var noprerequisites = { |
|
|
var noprerequisites = { |
|
|
add : true, 'set-url' : true, 'repo-relocate' : true |
|
|
add : true, 'set-url' : true, 'repo-relocate' : true |
|
|
|
|
|
, remote : true |
|
|
} |
|
|
} |
|
|
var skipprereqs = {} |
|
|
var skipprereqs = {} |
|
|
var maintask = () => { |
|
|
var maintask = () => { |
|
|
|
|
|
|
|
|
e = err; |
|
|
e = err; |
|
|
console.error('Chosen cofiguraton failed or not found. Fix config and rerun or chose another.') |
|
|
console.error('Chosen cofiguraton failed or not found. Fix config and rerun or chose another.') |
|
|
console.error(err) |
|
|
console.error(err) |
|
|
}).then(() => { return elxrworker(true) }) |
|
|
|
|
|
|
|
|
}).then(() => { preworkerconfig(); return elxrworker(true) }) |
|
|
// .finally(()=>{ |
|
|
// .finally(()=>{ |
|
|
// fs.writeFileSync('run.log', ', ' + JSON.stringify({ error: e.message }), { 'flag': 'a+' }) |
|
|
// fs.writeFileSync('run.log', ', ' + JSON.stringify({ error: e.message }), { 'flag': 'a+' }) |
|
|
// if(!e.success) fs.writeFileSync('run.done', 'error'); |
|
|
// if(!e.success) fs.writeFileSync('run.done', 'error'); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
console.log('cmd has no preqs or has been configured to skip preqs') |
|
|
console.log('cmd has no preqs or has been configured to skip preqs') |
|
|
|
|
|
preworkerconfig() |
|
|
return elxrworker() |
|
|
return elxrworker() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(noprerequisites[processedArgs._[0]] |
|
|
if(noprerequisites[processedArgs._[0]] |
|
|
|| skipprereqs[processedArgs._[0]] |
|
|
|| skipprereqs[processedArgs._[0]] |
|
|
) { |
|
|
) { |
|
|
return op[processedArgs._[0]]() |
|
|
|
|
|
|
|
|
return elxrworker() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return detectInstance().then((detectedInstance)=>{ |
|
|
return detectInstance().then((detectedInstance)=>{ |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
catch (e) { |
|
|
catch (e) { |
|
|
console.error(e) |
|
|
console.error(e) |
|
|
// No local instances config found. We acquire user choices and proceed to reattempt. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Basic keys that must be prompted and confirmed if not supplied as cmd line args. |
|
|
|
|
|
// PB: TODO --- This should be cmd specific interpretation of location parameters !!! |
|
|
|
|
|
var promptkeys = { |
|
|
|
|
|
'instanceName' : processedArgs._[1] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var reconfirm = { |
|
|
|
|
|
'instanceName' : true |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// No local instances config found. We use a default initialized instance available in selectedinstance |
|
|
|
|
|
// Confirm those that were not supplied as user choices in runtime args and proceed to reattempt. |
|
|
initinstances(chessinstances, selectedinstance) |
|
|
initinstances(chessinstances, selectedinstance) |
|
|
|
|
|
|
|
|
|
|
|
var instanceNameChoices = new Set(Object.keys( chessinstances) ) |
|
|
|
|
|
instanceNameChoices.delete('current_run') |
|
|
|
|
|
instanceNameChoices.add(selectedinstance['instanceName']) |
|
|
|
|
|
instanceNameChoices.add(promptkeys['instanceName']) |
|
|
|
|
|
|
|
|
|
|
|
var choices = { |
|
|
|
|
|
'instanceName' : Array.from(instanceNameChoices) |
|
|
|
|
|
, 'reposerver' : selectedinstance['reposervers'] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
var prompts = []; |
|
|
var prompts = []; |
|
|
Object.keys(__interactve_promts).forEach(k => { |
|
|
|
|
|
if(!selectedinstance[k]) { |
|
|
|
|
|
|
|
|
var eachPrompt = function(k, i, a){ |
|
|
|
|
|
|
|
|
|
|
|
if(selectedinstance[k] !== promptkeys[k] || promptkeys[k] === undefined || reconfirm[k]) { |
|
|
prompts.push(async ()=>{ |
|
|
prompts.push(async ()=>{ |
|
|
Object.defineProperty(selectedinstance, k, Object.getOwnPropertyDescriptor(__interactve_promts, k)); |
|
|
|
|
|
|
|
|
// PB : NOTE -- Important in async cases when this needs to be in the same state as when it was invoked. |
|
|
|
|
|
// We take a snapshot... Shallow.. !! If required deep should be used based on use case. |
|
|
|
|
|
// If latest altered state is required we can reerence this directly. |
|
|
|
|
|
// var asyncthis = Object.assign(this); |
|
|
|
|
|
Object.defineProperty(selectedinstance, k, getPromptableAsyncPropDescriptor(k, choices[k], promptkeys[k] || selectedinstance[k] )); |
|
|
return await selectedinstance[k] |
|
|
return await selectedinstance[k] |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
}) |
|
|
|
|
|
|
|
|
delete promptkeys[k] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Object.keys(__interactve_promts).forEach(eachPrompt, __interactve_promts) |
|
|
|
|
|
Object.keys(promptkeys).forEach(eachPrompt, promptkeys) |
|
|
|
|
|
|
|
|
todo = any(prompts).then(()=>{ return selectedinstance }) |
|
|
todo = any(prompts).then(()=>{ return selectedinstance }) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Promise.all(tasks) |
|
|
return Promise.all(tasks) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Sample instances config. |
|
|
// Sample instances config. |
|
|
// var instances = { |
|
|
// var instances = { |
|
|
// "elixir": { |
|
|
// "elixir": { |