Browse Source

Linux Installer updates

master
guest 2 years ago
parent
commit
748fd720e2
4 changed files with 620 additions and 346 deletions
  1. 31
    3
      cliverse.js
  2. 250
    343
      index.js
  3. 158
    0
      lin_verse.js
  4. 181
    0
      win_verse.js

+ 31
- 3
cliverse.js View File

return p; return p;
} }


var prompt = function(choices, label, defaultchoice){
var prompt = function(choices, label, defaultchoice, selectedchoice){
// prompt accepts either an array or an object as choices. // prompt accepts either an array or an object as choices.
var choices = choices || []; var choices = choices || [];
defaultchoice = defaultchoice || choices[0] || choices[Object.keys(choices)[0]]
defaultchoice = defaultchoice || choices[0] || selectedchoice || choices[Object.keys(choices)[0]]
var ci = 0;
return this.prompter.ask( return this.prompter.ask(
`${label} \n` + Object.keys(choices).map(choice => { var choice_label = isNaN(+choice) ? choice : ((+choice) + 1); return ` ${choice_label}) ${choices[choice]} `}).join('\n') + `\n default ( <= ${ defaultchoice || choices[0]} ) : `
`${label} \n` + Object.keys(choices).map(
choice => {
++ci; var choice_label = isNaN(+choice) ? `${ci}) (${choice})` : ci + ')';
return ` ${choice_label} ${choices[choice]} `
}).join('\n')
+ `\n default ( <= ${ defaultchoice || choices[0]} ) : `
+ `\n selected ( <= ${ selectedchoice || defaultchoice || choices[0]} ) : `
).then(choice => { ).then(choice => {
// propName = promptable.interpret(propValue) // propName = promptable.interpret(propValue)
if(!choice) return selectedchoice;
if(!choice) return defaultchoice || choices[0]; if(!choice) return defaultchoice || choices[0];
if(choice && isNaN(+choice)) return choice; if(choice && isNaN(+choice)) return choice;
return choices[(+choice) - 1]; return choices[(+choice) - 1];
return prompt_interface return prompt_interface
} }
, prompt , prompt
, createTask(task, str){

var tasks = {
getTaskCheckExists : (str)=>{
return (command, options) => {
options = options || {}
return () => {
var p = nodeShellExec.apply(null, [str, [command]])
if (options.ignorefailures) {
return p.then(() => { return true }).catch(e => { // Ignore. Not a major error.
return false;
})
}
else return p.then(() => { return true });
}
}
}
}
return tasks[task](str)
}
} }


module.exports = cli module.exports = cli

+ 250
- 343
index.js View File

global.env = process.env global.env = process.env
global.env.NODE_ENV = global.env.NODE_ENV || 'development' global.env.NODE_ENV = global.env.NODE_ENV || 'development'


const fs = require('fs')
var path = require('path'); var path = require('path');
var utils = require('bbhverse'); var utils = require('bbhverse');
var any = utils.any; var any = utils.any;
var statuslog = utils.Traq var statuslog = utils.Traq
var Traq = utils.Traq var Traq = utils.Traq
Tasq.addlistener(statuslog.statuslog) Tasq.addlistener(statuslog.statuslog)
fs.writeFileSync('run.log', ', ' + JSON.stringify( { m : 'Hello'} ), { 'flag': 'a+' })
Tasq.addlistener((e)=>{ fs.writeFileSync('run.log', ', ' + JSON.stringify( e ), { 'flag': 'a+' }) })
var cli = require('./cliverse') var cli = require('./cliverse')
function isWin(){ return /^win/.test(process.platform) }
if(isWin()) {
var win_verse = require('./win_verse')
var shell_verse = win_verse;
}
else {
var lin_verse = require('./lin_verse')
var shell_verse = lin_verse;
}



var nodeShellExec = cli.nodeShellExec; var nodeShellExec = cli.nodeShellExec;
var chalk = require('chalk') var chalk = require('chalk')
const homedir = require('os').homedir(); const homedir = require('os').homedir();
// }, options) // }, options)
// powershell $env:Path -split ';' // powershell $env:Path -split ';'
if (__isElevated) {
return nodeShellExec('Powershell.exe', [
var etask = ()=>{
return nodeShellExec('Powershell.exe', [
`$path = [Environment]::GetEnvironmentVariable('PATH', 'Machine') `$path = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
$newpath = $path + ';${addpath}' $newpath = $path + ';${addpath}'
[Environment]::SetEnvironmentVariable("PATH", $newpath, 'Machine')` [Environment]::SetEnvironmentVariable("PATH", $newpath, 'Machine')`
fs.writeFileSync('run.done', 'error') fs.writeFileSync('run.done', 'error')
}) })
} }
else return op['runas']()
etask.statuslog = statuslog
etask.selectedinstance = selectedinstance
etask.processedArgs = processedArgs
return shell_verse.runElevated(etask)
// var newpath = addpath.split(';'); // var newpath = addpath.split(';');
}); });
} }
const existsFolderSync = existsSync; const existsFolderSync = existsSync;
const fs = require('fs')


const cliargs = utils.cliargs; const cliargs = utils.cliargs;
const processedArgs = cliargs(process.argv.slice(2)); const processedArgs = cliargs(process.argv.slice(2));
return nodeShellExec( `"${gitbash}"`, ['-c', getCmdString(args)], args[2]).catch( onEachError || function(e){ console.error(e) }) } return nodeShellExec( `"${gitbash}"`, ['-c', getCmdString(args)], args[2]).catch( onEachError || function(e){ console.error(e) }) }
} }


var getTaskCheckExists = (command, options) => {
options = options || {}
return () => {
var p = nodeShellExec.apply(null, ['where', [command]])
if (options.ignorefailures) {
return p.then(() => { return true }).catch(e => { // Ignore. Not a major error.
return false;
})
}
else return p.then(() => { return true });
}
}

var getTaskWithElevation = function(tasdef){
return ()=>{
if (__isElevated) {
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 {
// PB : TODO -- Rename op['runas'] to 'elevate'

var __runasresult = null;

return op['runas']().then((r) => { return __runasresult = r; })
.catch((e) => {
console.error(e)
})
.finally(() => {
if(__runasresult && !__runasresult.skipped) fs.unlinkSync('run.done')
if (!processedArgs.runas) { return tasdef.regularpulltasks(); }
})
}
}
}
var getTaskCheckExists = shell_verse.getTaskCheckExists
// var getTaskWithElevation = function(tasdef){ return shell_verse.getElevatedTask( tasdef.elevatedpulltasks ) }


var getTaskWithoutElevation = function(tasdef){
return ()=>{
if(!processedArgs.runas) { return tasdef.regularpulltasks(); }
else Promise.resolve(true)
}
}
// var getTaskWithoutElevation = function(tasdef){
// return ()=>{
// if(!processedArgs.runas) { return tasdef.regularpulltasks(); }
// else Promise.resolve(true)
// }
// }


var gitops = { var gitops = {


console.log(e) console.log(e)
} }



if (exists) { if (exists) {
var branchprint = branch ? ' branch :' + branch : ''; var branchprint = branch ? ' branch :' + branch : '';
console.log('pulling ' + instanceroot + '/' + repo + branchprint ) console.log('pulling ' + instanceroot + '/' + repo + branchprint )
return nodeShellExec.apply(null, getPullCmd(repo, branch)).then(() => {
if (__isElevated) {
fs.writeFileSync('run.log', ', ' + JSON.stringify({ repo, success: true }), { 'flag': 'a+' })
}
else statuslog.statuslog(null, repo)
return true;
})
.catch((e) => {
e.repo = repo;
if(errHandler) throw errHandler(e)
if (__isElevated) {
fs.writeFileSync('run.log', ', ' + JSON.stringify(e), { 'flag': 'a+' })
}
else statuslog.statuslog(e);
// console.error(e)
throw e;
})
var task = ()=>{
return nodeShellExec.apply(null, getPullCmd(repo, branch)).then(() => {
return true;
})
}

task.info = { repo }
task.errHandler = errHandler
task.statuslog = statuslog
return shell_verse.runTask( task )
} }
else { else {
console.log('cloning ' + repo) console.log('cloning ' + repo)
// PB : TODO -- detect if a clonable repo exists in currentGitAuthUser // PB : TODO -- detect if a clonable repo exists in currentGitAuthUser
return nodeShellExec('git', ['clone', '-c', 'core.symlinks=true', selectedinstance.reposerver + `/${repoowner || defaultRepoOwner}/` + repo + '.git'],
{
inherit: true, shell: true,
env: process.env
, cwd : instanceroot
, runas: processedArgs.runas
}).then(() => {

return nodeShellExec('git', ['config', '--replace-all', 'core.symlinks', true],
{
inherit: true, shell: true,
var task = ()=>{
return nodeShellExec('git', ['clone', '-c', 'core.symlinks=true', selectedinstance.reposerver + `/${repoowner || defaultRepoOwner}/` + repo + '.git'],
{
inherit: true, shell: true,
env: process.env env: process.env
, cwd: instanceroot + '/' + repo
, runas: processedArgs.runas
, title: `'git', ${['config', '--replace-all', 'core.symlinks', selectedinstance.username].join(' ')}`
})
.then(() => {
if (__isElevated) {
fs.writeFileSync('run.log', ', ' + JSON.stringify({ repo, success: true }), { 'flag': 'a+' })
}
else statuslog.statuslog(null, repo)
})
.catch((e) => {
e.repo = repo;
if (__isElevated) {
fs.writeFileSync('run.log', ', ' + JSON.stringify(e), { 'flag': 'a+' })
}
else statuslog.statuslog(e);
})
})
.catch(e => {
e.repo = repo;
if(errHandler) throw errHandler(e)
if (__isElevated) {
fs.writeFileSync('run.log', ', ' + JSON.stringify(e), { 'flag': 'a+' })
}
else statuslog.statuslog(e);
throw e
})
}
}
, cwd : instanceroot
, runas: processedArgs.runas
}).then(() => {


// PB : TODO -- If we are run from an elevated shell it never moves forward and simply exits.
// -- Currently workaround is to always run from a non-elevated shell.
var __isElevated = null; // We assume non-Elevated until someone evaluates and sets this variable.
var acquireElevationState = () => {
if (__isElevated === null) {
return nodeShellExec("fsutil", ["dirty", "query", "C:"], {
inherit: true
// , shell: true
, stdio: 'ignore'
, env: process.env
, title: `check privileged execution mode using "fsutil dirty query C:"`
}).then((exitcode) => {
console.log('Elevated')
__isElevated = true;
return true;
}).catch(() => {
__isElevated = false;
console.log('Not Elevated');
return false;
});
var task = ()=>{
return nodeShellExec('git', ['config', '--replace-all', 'core.symlinks', true],
{
inherit: true, shell: true,
env: process.env
, cwd: instanceroot + '/' + repo
, runas: processedArgs.runas
, title: `'git', ${['config', '--replace-all', 'core.symlinks', selectedinstance.username].join(' ')}`
})
}
task.info = { repo }
task.errHandler = errHandler
task.statuslog = statuslog
return shell_verse.runTask( task )
})
}
task.info = { repo }
task.errHandler = errHandler
task.statuslog = statuslog
return shell_verse.runTask( task )
} }
else return Promise.resolve(__isElevated);
} }



var currentGitAuthUser; // nodeShellExec('git', ['config', 'user.email']) ... PB : TODO-- get the current GITEA username var currentGitAuthUser; // nodeShellExec('git', ['config', 'user.email']) ... PB : TODO-- get the current GITEA username
var defaultRepoOwner = 'chess'; var defaultRepoOwner = 'chess';
var elevatedRunasRepos = null var elevatedRunasRepos = null
} }


// SAM : TODO Use nodeshellexec where to detect git installation dir // SAM : TODO Use nodeshellexec where to detect git installation dir
var gitbash = "C:\\Program Files\\Git\\bin\\sh.exe"
var gitbash = shell_verse.getbash()
// var gitbash = "G:\\Installed\\Git\\bin\\sh.exe" // var gitbash = "G:\\Installed\\Git\\bin\\sh.exe"
// Relevant git repos // Relevant git repos
var exludeMergeRepos = []; var exludeMergeRepos = [];
var useGitPull = processedArgs.useGitPull || false; var useGitPull = processedArgs.useGitPull || false;
var configPromise = null var configPromise = null



var op = { var op = {
'h': () => { console.log(elxr.help()); return '-h' } 'h': () => { console.log(elxr.help()); return '-h' }
, 'clean' : () => { , 'clean' : () => {
}) })
}) })
} }
, 'runas': () => {

if(processedArgs.skipelevated) return Promise.resolve({ skipped : true });

console.log('Testing Elevation')

if (__isElevated) {
try {
op[processedArgs.label || processedArgs._[0] || 'undefined'](processedArgs)
}
catch (e) {
console.error('Error Invalid command : ' + e)
fs.writeFileSync('run.done', 'error')
}
finally {
}
}
else {
console.log('Requesting Elevated Privileges');
// Wait for the runas to complete before we read it.
try {
fs.unlinkSync('run.done')
fs.unlinkSync('run.log')
}
catch (e) { } //Ignore

// Find node path to send to hta.
return nodeShellExec('where', ['node']).then(r => {
var namedArgs = [];
console.log('result : ' + JSON.stringify(r))
Object.keys(processedArgs).forEach((v) => { v != '_' ? namedArgs.push('--' + v + '=' + processedArgs[v]) : null; })
// PB : TODO -- Convert all the cli args back to string.
var args = [`${selectedinstance.root}/.elxr/run-${runtimestamp}/windowselevate.hta`].concat(processedArgs._)
namedArgs.length > 0 ? args = args.concat(namedArgs.join(' ')) : null;
args.push('--runas=self');
// args.push('--nodepath=' + r.messages[r.messages.length - 1])
// if (!processedArgs.node_env) args.push('--node_env=' + ENV.NODE_ENV)
// if (processedArgs.debug) args.push('--debug=true') // Enable to debug elevated..
// console.dir(processedArgs._)
// console.dir(namedArgs.join(' '))
console.dir(args)
// throw 'test'

return nodeShellExec('MSHTA', [`"${args.join('" "')}"`]
, {
inherit: true
, shell: true
, env: ENV
, runas: 'self'
, title: `runas`
}
).then(() => {
// runas returned.
try {
// PB : TODO -- Log is comma prefixed. Needs to be proper JSON.
var runaslog = JSON.parse('[ { "success" : true, "result" : "started"}' + fs.readFileSync('run.log', { flags: 'a+' }) + ']');
runaslog.forEach((logEntry) => {
statuslog.statuslog(logEntry.success ? null : logEntry, logEntry)
logEntry.success ? (console.log(['success :' + logEntry.result]), console.log((logEntry.messages || []).join(' '))) : (console.error(['error :' + logEntry.result]), console.error((logEntry.messages || []).join(' ')))
})
}
catch (e) {
// We must have a runas log
statuslog.statuslog(e)
console.error('Run log error probably was not created by runas : ' + e)
}
})
.catch(err => console.error('Elevation failed : ' + err));
})

}
}
, 'push': () => { , 'push': () => {
if (!processedArgs._[1]) { console.error('push all not supported. Specify repo name'); return } if (!processedArgs._[1]) { console.error('push all not supported. Specify repo name'); return }
// init remote bare from local // init remote bare from local
console.log('Running exlr pull : ' + path.dirname(__dirname)) console.log('Running exlr pull : ' + path.dirname(__dirname))


if (!processedArgs.runas) gitRepos.map((def) => performPull(def.repo, def.branch || 'master')) if (!processedArgs.runas) gitRepos.map((def) => performPull(def.repo, def.branch || 'master'))
if (__isElevated) {
var etask = ()=>{
return any(elevatedRunasRepos.map((def) => performPull(def.repo, def.branch || 'master'))).then(() => { return any(elevatedRunasRepos.map((def) => performPull(def.repo, def.branch || 'master'))).then(() => {
fs.writeFileSync('run.done', 'success') fs.writeFileSync('run.done', 'success')
}).catch(() => { }).catch(() => {
fs.writeFileSync('run.done', 'error') fs.writeFileSync('run.done', 'error')
}) })
} }
else return op['runas']()
etask.statuslog = statuslog
etask.selectedinstance = selectedinstance
etask.processedArgs = processedArgs
return shell_verse.runElevated(etask)
} }


, 'repo-relocate' : function(args){ , 'repo-relocate' : function(args){
// Usage : // Usage :
// elxr pull -- Defaults to run config // elxr pull -- Defaults to run config


return elxr.getpulltask(selectedinstance)()
return elxr.getpulltask(selectedinstance)
} }
, 'isInstalled': () => { , 'isInstalled': () => {
return nodeShellExec('where', [processedArgs._[1]], { inherit: true }).then(() => { return nodeShellExec('where', [processedArgs._[1]], { inherit: true }).then(() => {
var tasks = [] var tasks = []
// tasks.push(op['pull']); // tasks.push(op['pull']);
tasks.push(getShellTask.apply(null, ['rm', [instanceroot + '/run.js'], { ignorefailures: true }])) tasks.push(getShellTask.apply(null, ['rm', [instanceroot + '/run.js'], { ignorefailures: true }]))
tasks.push(op['use'])
if (!__isElevated) {
tasks.push(op['npmi'])
}
tasks.push(op['use']) // Will pull repos...
op['npmi'].statuslog = statuslog
tasks.push(shell_verse.getNonElevatedTask(op['npmi'])) // We do not run npm i with elevated privilege for security reasons.


// var tasksdefs = [ // var tasksdefs = [
// ['elxr', ['pull']] // ['elxr', ['pull']]
kill(serverPid) kill(serverPid)
} }
, 'model' : () => { , 'model' : () => {
if (__isElevated) {
var etask = ()=>{
var tasks = [ var tasks = [
() => { () => {
var p = nodeShellExec('mklink', [ `${processedArgs._[2]}.json` var p = nodeShellExec('mklink', [ `${processedArgs._[2]}.json`
fs.writeFileSync('run.done', 'error') fs.writeFileSync('run.done', 'error')
}) })
} }
else return op['runas']()
etask.statuslog = statuslog
etask.selectedinstance = selectedinstance
etask.processedArgs = processedArgs
return shell_verse.runElevated(etask)
} }




var promise = new Promise((resolve, reject)=>{ var promise = new Promise((resolve, reject)=>{
existslink('config', function(err, data){ existslink('config', function(err, data){
if(data) { if(data) {
var p = nodeShellExec('rmdir', ['config'], { inherit: true, shell: true, env: process.env })
var p = shell_verse.removeJuncionOrLink('config')
.then(()=>{resolve(true)}) .then(()=>{resolve(true)})
.catch((err) => { console.log('Ignoring benign error : ' + err); return resolve(true); }) .catch((err) => { console.log('Ignoring benign error : ' + err); return resolve(true); })
} }
var promise = new Promise((resolve, reject)=>{ var promise = new Promise((resolve, reject)=>{
existslink('data', function(err, data){ existslink('data', function(err, data){
if(data) { if(data) {
var p = nodeShellExec('rmdir', ['data'], { inherit: true, shell: true, env: process.env })
var p = shell_verse.removeJuncionOrLink('data')
.then(()=>{resolve(true)}) .then(()=>{resolve(true)})
.catch((err) => { console.log('Ignoring benign error : ' + err); return resolve(true); }) .catch((err) => { console.log('Ignoring benign error : ' + err); return resolve(true); })
} }
]; ];
runconfig.NODE_ENV = process.env.NODE_ENV = process.env.NODE_ENV || runconfig.NODE_ENV || 'development'; runconfig.NODE_ENV = process.env.NODE_ENV = process.env.NODE_ENV || runconfig.NODE_ENV || 'development';
if (processedArgs._[1] && runconfig.use !== processedArgs._[1]) runconfig.use = processedArgs._[1]; if (processedArgs._[1] && runconfig.use !== processedArgs._[1]) runconfig.use = processedArgs._[1];
if (!runconfig.use && selectedinstance.instanceName) runconfig.use = selectedinstance.instanceName;
if (!runconfig.use) { throw 'unspecifed use not allowed. Please specify chess instance name.' } if (!runconfig.use) { throw 'unspecifed use not allowed. Please specify chess instance name.' }
// console.log(process.env.cwd) // console.log(process.env.cwd)
fs.writeFileSync(instanceroot + '/run.js', 'module.exports = ' + JSON.stringify(runconfig)) fs.writeFileSync(instanceroot + '/run.js', 'module.exports = ' + JSON.stringify(runconfig))
// } // }


return any(tasks).then(() => { return any(tasks).then(() => {
var pr = Promise.resolve(true)
if (!__isElevated) {
pr = op['runas']()
return pr.then(()=>{


//target is the env is we specify in elxr use command. Default is dev
//Switch to target branch
return any(gitRepos.map((repodef) => { return performCheckout({ repo : repodef.repo, branch}).catch(e=>{ console.log(e); }) } ))
// pull or clone target branch
.then(() => {
if(!mergesource || branch === mergesource) return Promise.resolve(true)
return any(gitRepos.map((repo) => performPullAll(repo)))
})
// switch to source branch
.then( () => {
if(!mergesource || branch === mergesource ) return Promise.resolve(true) // Dont do anything if there is no source to merge from.
return any(gitRepos.map((repodef) => performCheckout({ repo : repodef.repo, branch: mergesource})))
})
//Pull on merge source branch
.then( () => {
if(!mergesource || branch === mergesource ) return Promise.resolve(true)
return any(gitRepos.map((repo) => performPullAll(repo)))
})
var task = ()=>{

//target is the env is we specify in elxr use command. Default is dev
//Switch to target branch //Switch to target branch
.then( () => {
return any(gitRepos.map((repodef) => { return performCheckout({ repo : repodef.repo, branch}).catch(e=>{ console.log(e); }) } ))
// pull or clone target branch
.then(() => {
if(!mergesource || branch === mergesource) return Promise.resolve(true)
return any(gitRepos.map((repo) => performPullAll(repo)))
})
// switch to source branch
.then( () => {
if(!mergesource || branch === mergesource ) return Promise.resolve(true) // Dont do anything if there is no source to merge from.
return any(gitRepos.map((repodef) => performCheckout({ repo : repodef.repo, branch: mergesource})))
})
//Pull on merge source branch
.then( () => {
if(!mergesource || branch === mergesource ) return Promise.resolve(true) if(!mergesource || branch === mergesource ) return Promise.resolve(true)
return any(gitRepos.map((repodef) => performCheckout({ repo : repodef.repo, branch})))
return any(gitRepos.map((repo) => performPullAll(repo)))
}) })
.then( //Merge source branch to target branch
() => {
if(!mergesource || branch === mergesource) return Promise.resolve(true)
return any(gitRepos.map((repo) => performMerge( repo ))).catch(err => { console.error('error in performMerge ' + err) })
})
//Switch to target branch
.then( () => {
if(!mergesource || branch === mergesource ) return Promise.resolve(true)
return any(gitRepos.map((repodef) => performCheckout({ repo : repodef.repo, branch})))
}) })
.then( //Merge source branch to target branch
() => {
if(!mergesource || branch === mergesource) return Promise.resolve(true)
return any(gitRepos.map((repo) => performMerge( repo ))).catch(err => { console.error('error in performMerge ' + err) })
})
} }
else {
tasks = [
task.statuslog = statuslog
var netask = shell_verse.getNonElevatedTask(task)
var eltask = ()=> {
var opts = {
inherit: true, shell: true
, cwd : instanceroot
, env: process.env
}
var tasks = [
() => { () => {
// Use junctions to avoid npm package issues // Use junctions to avoid npm package issues
var p = nodeShellExec('mklink', ['/J', 'config', runconfig.use + '-config' + '-' + process.env.NODE_ENV], {
inherit: true, shell: true
, cwd : instanceroot
, env: process.env
}).catch((e) => { console.error(e) })
var target = runconfig.use + '-' + 'config' + '-' + process.env.NODE_ENV
var p = shell_verse.createJuntionOrLink('config', target, opts)
return p; return p;
} }
]; ];
if (processedArgs._[1]) {
tasks = tasks.concat(
[
// if (processedArgs._[1]) {
tasks = tasks.concat( [
() => { () => {
var dataToLink = runconfig.use + '-data' + '-' + process.env.NODE_ENV var dataToLink = runconfig.use + '-data' + '-' + process.env.NODE_ENV
if(!existsSync(dataToLink)) dataToLink = runconfig.use + '-data'; if(!existsSync(dataToLink)) dataToLink = runconfig.use + '-data';
var p = nodeShellExec('mklink', ['/J', 'data', dataToLink], {
inherit: true, shell: true
, cwd : instanceroot
, env: process.env
}).catch((e) => { console.error(e) })
var p = shell_verse.createJuntionOrLink('data', dataToLink, opts)
return p; return p;
} }
] ]
) )
}
// }
return any(tasks).then(()=>{ return any(tasks).then(()=>{
// checkout target branch // checkout target branch
}) })
}) })
} }
eltask.statuslog = statuslog
eltask.selectedinstance = selectedinstance
eltask.processedArgs = processedArgs
var etask = shell_verse.getElevatedTask(eltask)


}).catch(() => {
fs.writeFileSync('run.done', 'error')
return etask().then( ()=>{ return netask() })

}).catch((e) => {
fs.writeFileSync('run.done', 'error : ' + e)
}) })


// Antibiotic stewardship program. // Antibiotic stewardship program.
, 'switch user' : (tousername)=>{ return GIT['switch user'](tousername) } , 'switch user' : (tousername)=>{ return GIT['switch user'](tousername) }
} }


// elxr cli operations
// independent elxr cli operations
var noprerequisites = { var noprerequisites = {
add : true, 'set-url' : true, 'repo-relocate' : true add : true, 'set-url' : true, 'repo-relocate' : true
, remote : true, 'c' : true, 'h' : true , remote : true, 'c' : true, 'h' : true
return p; return p;
} }
]; ];
if (__isElevated) {
var etask = ()=>{
return any(tasks).then(() => { return any(tasks).then(() => {
fs.writeFileSync('run.done', 'success') fs.writeFileSync('run.done', 'success')
}).catch(() => { }).catch(() => {
fs.writeFileSync('run.done', 'error') fs.writeFileSync('run.done', 'error')
}) })
} }
else return op['runas']()
etask.statuslog = statuslog
etask.selectedinstance = selectedinstance
etask.processedArgs = processedArgs
return shell_verse.runElevated(etask)
} }
, noprerequisites : true , noprerequisites : true
, privileged : true , privileged : true
if(def.repo) { if(def.repo) {
// Single repo case. // Single repo case.
if(def.repo.requiresElevation) { if(def.repo.requiresElevation) {
elevatedpulltasks = function() {
var t1 = function() {
return performPull(def.repo).then(() => { return performPull(def.repo).then(() => {
return true; return true;
}).catch((e) => { }).catch((e) => {
console.error(e) console.error(e)
})
}).finally(Traq.finally)
} }
return
t1.statuslog = statuslog
t1.selectedinstance = selectedinstance
t1.processedArgs = processedArgs
elevatedpulltasks = shell_verse.getElevatedTask( t1 )
} }
else { else {
var regularpulltasks = function(){
var pendingpulls = [];
pendingpulls.push(performPull(def.repo))
return Promise.all(pendingpulls).finally(Traq.finally)
var t2 = function(){
return performPull(def.repo).then(() => {
return true;
}).catch((e) => {
console.error(e)
}).finally(Traq.finally)
} }
t2.statuslog = statuslog
var regularpulltasks = shell_verse.getNonElevatedTask( t2 )
} }
if(elevatedpulltasks) return getTaskWithElevation( { elevatedpulltasks, regularpulltasks} )
else return getTaskWithoutElevation({ regularpulltasks})
if(elevatedpulltasks) return elevatedpulltasks //getTaskWithElevation( { elevatedpulltasks, regularpulltasks} )
else return regularpulltasks // getTaskWithoutElevation({ regularpulltasks})
} }
// console.log(`-------------------Processing pull for : ${def.repo} ${def.branch}`) // console.log(`-------------------Processing pull for : ${def.repo} ${def.branch}`)
console.error(e) console.error(e)
}) })
} }
elevatedpulltasks.statuslog = statuslog
} }
if(def.repos) { if(def.repos) {
var regularpulltasks = function(){ var regularpulltasks = function(){
def.repos.forEach((def) => { pendingpulls.push(performPull(def.repo)) }) def.repos.forEach((def) => { pendingpulls.push(performPull(def.repo)) })
return Promise.all(pendingpulls).finally(Traq.finally) return Promise.all(pendingpulls).finally(Traq.finally)
} }
regularpulltasks.statuslog = statuslog
} }
if(elevatedpulltasks) return getTaskWithElevation( { elevatedpulltasks, regularpulltasks} )
else return getTaskWithoutElevation({ regularpulltasks})
// if(elevatedpulltasks) return getTaskWithElevation( { elevatedpulltasks, regularpulltasks} )
// else return getTaskWithoutElevation({ regularpulltasks})
return any([ elevatedpulltasks, regularpulltasks ])
} }
} }


.catch( (e)=>{ .catch( (e)=>{
// if(e){ // if(e){
if(Promise.resolve(e) === e) return e; if(Promise.resolve(e) === e) return e;
console.error(e)
throw e; // Not a hard error but we need this for bcontinueonfailure
// console.error(e)
throw e; // Not a hard error but we need this for bcontinueonfailure as we still want to stop on firstsuccess.
// } // }
}) })
} }
.catch( (e)=>{ .catch( (e)=>{
// if(e){ // if(e){
if(Promise.resolve(e) === e) return e; if(Promise.resolve(e) === e) return e;
console.error(e)
// console.error(e)
throw e; // Not a hard error but we need this for bcontinueonfailure throw e; // Not a hard error but we need this for bcontinueonfailure
// } // }
}) })
server : `${options.reposerver}`, user : '${options.username}', path : ``, get url(){ return `${this.server}/${this.user}/${this.path}`} // fetch server : `${options.reposerver}`, user : '${options.username}', path : ``, get url(){ return `${this.server}/${this.user}/${this.path}`} // fetch
} }
, 'origin-public' : { , 'origin-public' : {
// export GIT_SSL_NO_VERIFY=true
server : `https://git.bbh.org.in`, user : 'chess', path : ``, get url(){ return `${this.server}/${this.user}/${this.path}`} // fetch server : `https://git.bbh.org.in`, user : 'chess', path : ``, get url(){ return `${this.server}/${this.user}/${this.path}`} // fetch
, push : { , push : {
server : `${options.reposerver}`, user : `${options.username}`, path : ``, get url(){ return `${this.server}/${this.user}/${this.path}`} server : `${options.reposerver}`, user : `${options.username}`, path : ``, get url(){ return `${this.server}/${this.user}/${this.path}`}
: ` : `
, choices : [] , choices : []
, defaultchoice : 'c' , defaultchoice : 'c'
, selectedchoice : target.runchoice
, interpret : function(choice){ , interpret : function(choice){
var interpret_map = { var interpret_map = {
d : function(){ d : function(){
target.reposerver = 'https://git.bbh.org.in' target.reposerver = 'https://git.bbh.org.in'
} }
, n : function() { processedArgs._[0] = 'i' } , n : function() { processedArgs._[0] = 'i' }
, i : function() { processedArgs._[0] = 'i' }
, i : function() {
processedArgs._[0] = 'i'
// processedArgs._[1] = target.instanceName || processedArgs._[1] || 'chess';
}
, c : async function() { , c : async function() {
// this here will always be the target.
Object.defineProperty(this, 'cmd', getPromptableAsyncPropDescriptor('cmd', { Object.defineProperty(this, 'cmd', getPromptableAsyncPropDescriptor('cmd', {
label : `Enter cmd : label : `Enter cmd :
p) pull p) pull
, h : function() { console.log(elxr.help()); process.exit() } // PB : TODO -- Why do we need log. , h : function() { console.log(elxr.help()); process.exit() } // PB : TODO -- Why do we need log.
, q : function() { process.exit() } , q : function() { process.exit() }
} }
var __interpreter = interpret_map['c']

if(Promise.resolve(choice) === choice){
return choice.then( resolvedchoice => {
return (interpret_map[choice] || interpret_map['c']).call(target)
})
}
else return Promise.resolve( (interpret_map[choice] || interpret_map['c']).call(target) )

// var __interpreter = interpret_map[choice] || interpret_map['c']
// if(!choice) return interpret_map['c']() // This should not happen prompter should always give us a default choice. // if(!choice) return interpret_map['c']() // This should not happen prompter should always give us a default choice.
if(interpret_map[choice]) __interpreter = interpret_map[choice];
// if(interpret_map[choice]) __interpreter = interpret_map[choice];
return __interpreter.call(target)
// return __interpreter.call(target)
} }
} }
, instanceName : { label : `Enter Instance Name ( <= ${target.instanceName || 'chess'} ) : ` , instanceName : { label : `Enter Instance Name ( <= ${target.instanceName || 'chess'} ) : `
, choices : choices['instanceName'], defaultchoice : 'chess'}
, choices : choices['instanceName'], defaultchoice : 'chess'
, selectedchoice : target.instanceName
}
, instanceType : { label : `Enter Instance Type ( <= ${target.instanceType || 'development'} ) : ` , instanceType : { label : `Enter Instance Type ( <= ${target.instanceType || 'development'} ) : `
, choices : choices['instanceType'], defaultchoice : 'development'}
, choices : choices['instanceType'], defaultchoice : 'development'
, selectedchoice : target.instanceType
}
, reposerver : { label : `Enter Repo Url ( <= ${target.reposerver || 'https://git.bbh.org.in'} ) : ` , reposerver : { label : `Enter Repo Url ( <= ${target.reposerver || 'https://git.bbh.org.in'} ) : `
, choices : choices['reposerver'], defaultchoice : 'https://git.bbh.org.in'}
, choices : choices['reposerver'], defaultchoice : 'https://git.bbh.org.in'
, selectedchoice : target.reposerver
}
, get username() { return { label : `Enter User Id for ${target.reposerver} ( <= ${target.username || 'chess'} ) : ` , get username() { return { label : `Enter User Id for ${target.reposerver} ( <= ${target.username || 'chess'} ) : `
, choices : choices['username'], defaultchoice : 'chess'} }
, choices : choices['username'], defaultchoice : 'chess', selectedchoice : target.username } }
, get password() { return { label : `Enter Password for ${target.username} @ ${target.reposerver} ( <= ${target.password || ''} ) : ` , get password() { return { label : `Enter Password for ${target.username} @ ${target.reposerver} ( <= ${target.password || ''} ) : `
, choices : choices['password'], defaultchoice : '***'} }
, choices : choices['password'], defaultchoice : '***', selectedchoice : target.password } }
, get email() { return { label : `Enter Email for ${target.username} @ ${target.reposerver} ( <= ${target.email || ''} ) : ` , get email() { return { label : `Enter Email for ${target.username} @ ${target.reposerver} ( <= ${target.email || ''} ) : `
, choices : choices['email'], defaultchoice : 'guest@bbh.org.in'} }
, choices : choices['email'], defaultchoice : 'guest@bbh.org.in', selectedchoice : target.email } }


} }


, ,
{ {
shellcmd: 'node', shellcmd: 'node',
name : 'ndoe',
name : 'node',
url: 'https://nodejs.org/dist/v14.16.0/node-v14.16.0-x64.msi' url: 'https://nodejs.org/dist/v14.16.0/node-v14.16.0-x64.msi'
, installer: 'node-v14.16.0-x64.msi' , installer: 'node-v14.16.0-x64.msi'
, installcmd: ['MSIEXEC.exe', ['/i' , installcmd: ['MSIEXEC.exe', ['/i'
var getPromptableAsyncPropDescriptor = function(propName, promptable){ var getPromptableAsyncPropDescriptor = function(propName, promptable){
return { return {
get (){ get (){
return cli.prompt( promptable.choices, promptable.label, promptable.defaultchoice ).then(propValue => {
return cli.prompt( promptable.choices, promptable.label, promptable.defaultchoice, promptable.selectedchoice ).then(propValue => {
var asyncprop = Promise.resolve(propValue) var asyncprop = Promise.resolve(propValue)
if(promptable.interpret){ if(promptable.interpret){
} }
// Override sequence. // Override sequence.
// __default, chessinstances[current_run], instanceName-config-development, cliargs, interactve_promts // __default, chessinstances[current_run], instanceName-config-development, cliargs, interactve_promts
// PB : TODO -- Undefined keys are overriding and deleting values. We should not allow that.
// This is ordinary utils.assign behavior. The key should not exist as undefined in the override.
if(selected_overrides.node_env === undefined) delete selected_overrides.node_env
selectedinstance = utils.assign( selectedinstance = utils.assign(
chessinstances[instanceName][node_env] chessinstances[instanceName][node_env]
, clioverrides , clioverrides
, selected_overrides
, selected_overrides
// , __interactive_prompts -- Cant just override. Also need selectedinstance to be ready... // , __interactive_prompts -- Cant just override. Also need selectedinstance to be ready...
); );


// chessinstances[instanceName] = chessinstances[instanceName] || {} // chessinstances[instanceName] = chessinstances[instanceName] || {}
// chessinstances[instanceName][node_env] = chessinstances[instanceName][node_env] || {} // chessinstances[instanceName][node_env] = chessinstances[instanceName][node_env] || {}
// if(!selectedinstance.repos || selectedinstance.instanceName) { // if(!selectedinstance.repos || selectedinstance.instanceName) {
// // Brand New. // // Brand New.
// selectedinstance = Object.assign( __default, selectedinstance ) // selectedinstance = Object.assign( __default, selectedinstance )
return prerequisites.git.verifyAndInstall().then(()=>{ return prerequisites.git.verifyAndInstall().then(()=>{
var e = { message : 'verifyAndInstall', success : true} var e = { message : 'verifyAndInstall', success : true}
var inittasks = [] var inittasks = []
var commantask = () => { preworkerconfig(); return elxrworker(true) }
if(!detection_state.localInstanceDetected) { if(!detection_state.localInstanceDetected) {
var specifictask = ()=>{ return createInstance(selectedinstance) }
var commantask = () => { preworkerconfig(); return elxrworker(true) }
if(!__isElevated) {
}
else {
specifictask = ()=>{ Promise.resolve(true) }
}
inittasks.push(specifictask().then( commantask ))
var t1 = ()=>{ return createInstance(selectedinstance) };
t1.statuslog = statuslog
var specifictask = shell_verse.getNonElevatedTask(t1)
} }
else { else {
var specifictask = ()=>{ return acquireConfig(selectedinstance) }
var commantask = () => { preworkerconfig(); return elxrworker(true) }
if(!__isElevated) {
}
else {
specifictask = ()=>{ return Promise.resolve(true) }
}
inittasks.push( specifictask().catch((err) => {
e = err;
console.error('Chosen cofiguraton failed or not found. Fix config and rerun or chose another.')
console.error(err)
}).then( commantask )
// .finally(()=>{
// fs.writeFileSync('run.log', ', ' + JSON.stringify({ error: e.message }), { 'flag': 'a+' })
// if(!e.success) fs.writeFileSync('run.done', 'error');
// // return process.exit()
// }))
)
var t2 = ()=>{ return acquireConfig(selectedinstance) };
t2.statuslog = statuslog
var specifictask = shell_verse.getNonElevatedTask(t2)
} }
inittasks.push( specifictask().catch((err) => {
e = err;
console.error('Chosen cofiguraton failed or not found. Fix config and rerun or chose another.')
console.error(err)
}).then( commantask )
// .finally(()=>{
// fs.writeFileSync('run.log', ', ' + JSON.stringify({ error: e.message }), { 'flag': 'a+' })
// if(!e.success) fs.writeFileSync('run.done', 'error');
// // return process.exit()
// }))
)
return any(inittasks) return any(inittasks)
}) })
var cmdinstance = cmds[clioverrides.cmd] var cmdinstance = cmds[clioverrides.cmd]
var cmdprompts = cmdinstance.getPossiblePrompts() var cmdprompts = cmdinstance.getPossiblePrompts()
selectedinstance.node_env ? selectedinstance.node_env : selectedinstance.node_env = clioverrides.node_env
// PB : TODO -- Most recent should be at the tip ! at index 0 so utils.reverseassign is required !!! // PB : TODO -- Most recent should be at the tip ! at index 0 so utils.reverseassign is required !!!
selectedinstance = utils.assign( ...detectedinstanceoptions.slice(-2), promptkeys ) selectedinstance = utils.assign( ...detectedinstanceoptions.slice(-2), promptkeys )
// promptkeys = utils.assign(promptkeys, clioverrides) // promptkeys = utils.assign(promptkeys, clioverrides)
return elxrworker() return elxrworker()
} }


if(!__isElevated) {
var neTask = ()=>{
ensureDirectoryExistence(`${selectedinstance.root}/.elxr/${__ALIAS__STAMP__}`) ensureDirectoryExistence(`${selectedinstance.root}/.elxr/${__ALIAS__STAMP__}`)
// collect garbage // collect garbage
return dirs( (dir)=>{ return dirs( (dir)=>{
} }
else return true else return true
}) })
.then(()=>{
if (!skipprerequisites && !__isElevated || processedArgs.forceprereqs && !__isElevated ) mainTasks.push(verifyAndInstallPrerequisites);
mainTasks.push(maintask)
return any(mainTasks);
})
}
else {
if (!skipprerequisites && !__isElevated || processedArgs.forceprereqs && !__isElevated ) mainTasks.push(verifyAndInstallPrerequisites);
}
neTask.statuslog = statuslog
shell_verse.getNonElevatedTask( neTask )()
var commonTask = ()=>{
verifyAndInstallPrerequisites.statuslog = statuslog
if((!skipprerequisites || processedArgs.forceprereqs)) mainTasks.push(verifyAndInstallPrerequisites);
mainTasks.push(maintask) mainTasks.push(maintask)
return any(mainTasks); return any(mainTasks);
} }
return commonTask()
}) })
} }


detectInstanceRoot.then(()=>{
var cmdobj = cmds[clioverrides.cmd]
return Promise.all((cmdobj.requires || []).map( (r) => utils.promisify(null, r) ) ).then(()=>{
if(cmdobj.independentcmd) {
if(cmdobj.requiresElevation) {
return acquireElevationState().then(() => {
cmdobj.cmdFn() })
// PB : TODO -- In windows if we are run from an elevated shell we never move forward and simply exits !?.
// -- Currently workaround in windows is to always run from a non-elevated shell.
shell_verse.acquireElevationState().then((elevationstate) => {
return detectInstanceRoot.then(()=>{
var cmdobj = cmds[clioverrides.cmd]
return Promise.all((cmdobj.requires || []).map( (r) => utils.promisify(null, r) ) ).then(()=>{
if(cmdobj.independentcmd) {
if(cmdobj.requiresElevation) {
return cmdobj.cmdFn()
}
else return cmdobj.cmdFn()
} }
else return cmdobj.cmdFn()
}
else return acquireElevationState().then(() => {
return startElxr()
else return startElxr()
})
.catch(e => {
if(typeof e === 'symbol') console.log('error : ' + 'symbol')
else console.log('error : ' + e)
}) })
})
.catch(e => {
console.log('error ')
}) })
}) })



+ 158
- 0
lin_verse.js View File

const fs = require('fs')

var cli = require('./cliverse')
var nodeShellExec = cli.nodeShellExec;

// PB : TODO -- linux prerequistes.
// npm i -g nodemon
// sudo apt install python2
// sudo apt install build-essential
// sudo apt install -y make

// phantomjs": "^2.1.7
// "sass": "^1.32.7",
// "node-sass": "^5.0.0",
// "ember-cli-sass": "^10.0.1",
// "gulp-sass": "^4.1.0",

// ember-searchable-select
// ember-cli-sass
// ember-cp-validatations
// ember-cli-yuidoc
// yuidoc-ember-theme

// chess-server-lib/server
// java

// client
// export NODE_OPTIONS=--openssl-legacy-provider

// elixir-client npmi
// elixir-client/chess-client-lib npmi
// crossfilter2

var __isElevated = null;
var shell_verse = {
// getCommonTask is agnostic of whether we are running in an elevated shell or not. It runs in either case.
getCommonTask( taskToRun ){ return ()=>{ return shell_verse.runTask(taskToRun) }}
, runTask : ( taskToRun ) => {
if (__isElevated) return shell_verse.elevatedRunner()
else return shell_verse.runNonElevated( taskToRun )
}

, elevatedRunner( taskToRun ){
try {
var __runasresult = null;
return taskToRun().then((r)=>{
// PB : TODO -- Every elevation should have its own messaging file. Async writes from multiple processes are a problem here...
fs.writeFileSync('run.log', ', ' + JSON.stringify( { info : taskToRun.info, success: true }), { 'flag': 'a+' })
fs.writeFileSync('run.done', 'success') // PB : TODO -- This should be done conditionally if we are running inproc.
return __runasresult = r;
})
.catch((e) => {
fs.writeFileSync('run.log', ', ' + JSON.stringify(e), { 'flag': 'a+' })
fs.writeFileSync('run.done', 'failure')
console.error(e)
})
.finally(() => {
if(__runasresult && !__runasresult.skipped) fs.unlinkSync('run.done')
})
}
catch (e) {
console.error('Error Invalid command : ' + e)
fs.writeFileSync('run.done', 'error')
}
finally {
}
}
, getElevatedTask : function( taskToRun ){ return ()=>{ return shell_verse.runElevated(taskToRun) }}
, runElevated : ( taskToRun ) => {
// Let shell_verse decide whether to Elevate Out of Proc or In Proc
// taskToRun by default is the launched command and args. Specially in windows out of proc.
// taskToRun = taskToRun || (()=>{ return op[processedArgs.label || processedArgs._[0] || 'undefined'](processedArgs) })

if(taskToRun.processedArgs.skipelevated) return Promise.resolve({ skipped : true });


if (__isElevated) {
return shell_verse.elevatedRunner(taskToRun)
}
else {
console.log('Requesting Elevated Privileges');
// requesteElevation is acutally request elevation and run. Both In Proc and Out of Proc.
// Linux doesnt require elevation for most commands...
return shell_verse.requestElevation(shell_verse.elevatedRunner, taskToRun)
}
}

, getNonElevatedTask : function( taskToRun ){ return ()=>{ return shell_verse.runNonElevated(taskToRun) } }
, runNonElevated : ( taskToRun ) => {
// Let shell_verse decide whether to Elevate Out of Proc or In Proc
if(__isElevated) {
return Promise.resolve( new Error('Cannot Run Task in Elevated Mode.') )
}
else {
// taskToRun by default is the launched command and args.
// taskToRun = taskToRun || (()=>{ return op[processedArgs.label || processedArgs._[0] || 'undefined'](processedArgs) })

return taskToRun().then(r=>{
taskToRun.statuslog.statuslog(null, taskToRun.info /*repo*/ )
return r;
}).catch((e) => {
e.info = taskToRun.info;
if(taskToRun.errHandler) throw taskToRun.errHandler(e)
taskToRun.statuslog.statuslog(e);
// console.error(e)
throw e;
}).finally(()=>{})
}
}
, isElevated : ()=>{
return acquireElevationState().then( ()=>{
shell_verse.isElevated = () => {
return Promise.resolve(__isElevated)
}
return shell_verse.isElevated()
})
}
// , isElevationOutOfProc : ()=>{ return true }

, acquireElevationState : () => {
return Promise.resolve(false).then(( elevationstate ) => {
__isElevated ? console.log('Elevated') : console.log('Not Elevated')
__isElevated = elevationstate;
}).catch(() => {
__isElevated = false;
console.log('Not Elevated');
}).finally(()=>{
shell_verse.acquireElevationState = ()=> Promise.resolve(__isElevated);
shell_verse.isElevated = () => { return Promise.resolve(__isElevated)}
return __isElevated;
})
}

, getTaskCheckExists : cli.createTask('getTaskCheckExists', 'which')

, getbash : ()=>{ return "sh" }

, createJuntionOrLink : (dirOrFile, target, opts)=>{
return nodeShellExec('ln', ['-s', target, dirOrFile], opts).catch((e) => { console.error(e) })
}

, removeJuncionOrLink : ( junctionOrLink )=>{
return nodeShellExec('rm', [junctionOrLink], { inherit: true, shell: true, env: process.env })
}

, requestElevation(elevatedRunner, taskToRun) {
// PB : TODO -- Most linking cmds in linux may not need elevation like in windows.
// However returning true here is pseudo and will break cases where real elevation is required in linux. We need to refactor to reimplement
// this with sudo and change all calles to use ony where required.
return elevatedRunner(taskToRun);
}
}

module.exports = shell_verse

+ 181
- 0
win_verse.js View File

const fs = require('fs')

var cli = require('./cliverse')
var nodeShellExec = cli.nodeShellExec;

var __isElevated = null;
var shell_verse = {
// getCommonTask is agnostic of whether we are running in an elevated shell or not. It runs in either case.
getCommonTask( taskToRun ){ return ()=>{ return shell_verse.runTask(taskToRun) }}
, runTask : ( taskToRun ) => {
if (__isElevated) return shell_verse.elevatedRunner()
else return shell_verse.runNonElevated( taskToRun )
}

, elevatedRunner( taskToRun ){
try {
var __runasresult = null;
return taskToRun().then((r)=>{
// PB : TODO -- Every elevation should have its own messaging file. Async writes from multiple processes are a problem here...
fs.writeFileSync('run.log', ', ' + JSON.stringify( { info : taskToRun.info, success: true }), { 'flag': 'a+' })
fs.writeFileSync('run.done', 'success') // PB : TODO -- This should be done conditionally if we are running inproc.
return __runasresult = r;
})
.catch((e) => {
fs.writeFileSync('run.log', ', ' + JSON.stringify(e), { 'flag': 'a+' })
fs.writeFileSync('run.done', 'failure')
console.error(e)
})
.finally(() => {
if(__runasresult && !__runasresult.skipped) fs.unlinkSync('run.done')
})
}
catch (e) {
console.error('Error Invalid command : ' + e)
fs.writeFileSync('run.done', 'error')
}
finally {
}
}
, getElevatedTask : function( taskToRun ){ return ()=>{ return shell_verse.runElevated(taskToRun) }}
, runElevated : ( taskToRun ) => {
// Let shell_verse decide whether to Elevate Out of Proc or In Proc
// taskToRun by default is the launched command and args. Specially in windows out of proc.
// taskToRun = taskToRun || (()=>{ return op[processedArgs.label || processedArgs._[0] || 'undefined'](processedArgs) })

if(taskToRun.processedArgs.skipelevated) return Promise.resolve({ skipped : true });


if (__isElevated) {
return shell_verse.elevatedRunner(taskToRun)
}
else {
console.log('Requesting Elevated Privileges');
// requesteElevation is acutally request elevation and run. Both In Proc and Out of Proc.
// Linux doesnt require elevation for most commands...
return shell_verse.requestElevation(shell_verse.elevatedRunner, taskToRun)
}
}

, getNonElevatedTask : function( taskToRun ){ return ()=>{ return shell_verse.runNonElevated(taskToRun) } }
, runNonElevated : ( taskToRun ) => {
// Let shell_verse decide whether to Elevate Out of Proc or In Proc
if(__isElevated) {
return Promise.resolve( new Error('Cannot Run Task in Elevated Mode.') )
}
else {
// taskToRun by default is the launched command and args.
// taskToRun = taskToRun || (()=>{ return op[processedArgs.label || processedArgs._[0] || 'undefined'](processedArgs) })

return taskToRun().then(r=>{
taskToRun.statuslog.statuslog(null, taskToRun.info /*repo*/ )
return r;
}).catch((e) => {
e.info = taskToRun.info;
taskToRun.statuslog.statuslog(e);
if(taskToRun.errHandler) throw taskToRun.errHandler(e)
// console.error(e)
throw e;
}).finally(()=>{})
}
}

, isElevated : ()=>{
return acquireElevationState().then( ()=>{
shell_verse.isElevated = () => {
return Promise.resolve(__isElevated)
}
return shell_verse.isElevated()
})
}

// , isElevationOutOfProc : ()=>{ return true }
, acquireElevationState : () => {
return nodeShellExec("fsutil", ["dirty", "query", "C:"], {
inherit: true
// , shell: true
, stdio: 'ignore'
, env: process.env
, title: `check privileged execution mode using "fsutil dirty query C:"`
}).then((exitcode) => {
console.log('Elevated')
__isElevated = true;
}).catch(() => {
__isElevated = false;
console.log('Not Elevated');
}).finally(()=>{
shell_verse.acquireElevationState = ()=> Promise.resolve(__isElevated);
shell_verse.isElevated = () => { return Promise.resolve(__isElevated)}
return __isElevated;
})
}
, getTaskCheckExists : cli.createTask('getTaskCheckExists', 'where')

, getbash : ()=>{ return "C:\\Program Files\\Git\\bin\\sh.exe" }

, createJuntionOrLink : (dirOrFile, target, opts) =>{
return nodeShellExec('mklink', ['/J', dirOrFile, target], opts).catch((e) => { console.error(e) })
}
, removeJuncionOrLink : ( junctionOrLink )=>{
return nodeShellExec('rmdir', [junctionOrLink], { inherit: true, shell: true, env: process.env })
}

, requestElevation(elevatedRunner, taskToRun) {
var processedArgs = taskToRun.processedArgs, selectedinstance = taskToRun.selectedinstance , statuslog = taskToRun.statuslog
// Wait for the runas to complete before we read it.
try {
fs.unlinkSync('run.done')
fs.unlinkSync('run.log')
}
catch (e) { } //Ignore

// Find node path to send to hta.
return nodeShellExec('where', ['node']).then(r => {
var namedArgs = [];
console.log('result : ' + JSON.stringify(r))
Object.keys(processedArgs).forEach((v) => { v != '_' ? namedArgs.push('--' + v + '=' + processedArgs[v]) : null; })
// PB : TODO -- Convert all the cli args back to string.
var args = [`${selectedinstance.root}/.elxr/run-${runtimestamp}/windowselevate.hta`].concat(processedArgs._)
namedArgs.length > 0 ? args = args.concat(namedArgs.join(' ')) : null;
args.push('--runas=self');
// args.push('--nodepath=' + r.messages[r.messages.length - 1])
// if (!processedArgs.node_env) args.push('--node_env=' + ENV.NODE_ENV)
// if (processedArgs.debug) args.push('--debug=true') // Enable to debug elevated..
// console.dir(processedArgs._)
// console.dir(namedArgs.join(' '))
console.dir(args)
// throw 'test'

return nodeShellExec('MSHTA', [`"${args.join('" "')}"`]
, {
inherit: true
, shell: true
, env: ENV
, runas: 'self'
, title: `runas`
}
).then(() => {
// runas returned.
try {
// PB : TODO -- Log is comma prefixed. Needs to be proper JSON.
var runaslog = JSON.parse('[ { "success" : true, "result" : "started"}' + fs.readFileSync('run.log', { flags: 'a+' }) + ']');
runaslog.forEach((logEntry) => {
statuslog.statuslog(logEntry.success ? null : logEntry, logEntry)
logEntry.success ? (console.log(['success :' + logEntry.result]), console.log((logEntry.messages || []).join(' '))) : (console.error(['error :' + logEntry.result]), console.error((logEntry.messages || []).join(' ')))
})
}
catch (e) {
// We must have a runas log
statuslog.statuslog(e)
console.error('Run log error probably was not created by runas : ' + e)
}
})
.catch(err => console.error('Elevation failed : ' + err));
})
}
}

module.exports = shell_verse

Loading…
Cancel
Save