| @@ -0,0 +1,390 @@ | |||
| var BUILD_VERSION = '[VI]Version: {version} - built on {date}[/VI]'; | |||
| var runtimestamp = (new Date()).getTime(); | |||
| function getVersion() { return BUILD_VERSION; } | |||
| WScript.echo(getVersion()) | |||
| var fso = new ActiveXObject('Scripting.FileSystemObject'); | |||
| var shell = new ActiveXObject('shell.application'); | |||
| function forEach(eachFn){ | |||
| for(var i=0; i<this.length; i++) eachFn(this[i]) | |||
| } | |||
| var console = { log : function(m) {WScript.Echo(m)}, error : function(m) {WScript.Echo(m)} } | |||
| var Promise = function(fn){ | |||
| // Detect error | |||
| var state = Promise.PENDING; | |||
| var chain = []; | |||
| chain.forEach = forEach; | |||
| function reject(e){ | |||
| if(state !== Promise.PENDING) { console.error ('Error : Promise Rejection can only be called once')} | |||
| var __i = 0; | |||
| var __e = e; | |||
| do { | |||
| for(var i = __i; i < chain.length; i++, __i = i) if(chain[i].isCatch) break; | |||
| try { | |||
| for(var i = __i; i < chain.length; i++, __i = i) if(chain[i].isCatch) { chain[i](__e); break; } | |||
| __e = null; | |||
| } | |||
| catch(e){ __e = e} | |||
| } while(__e) | |||
| do { | |||
| try { for(var i = __i; i < chain.length; i++, __i = i) if(!chain[i].isCatch) { p.result = chain[i](p.result); } } | |||
| catch(e){ | |||
| do { | |||
| try { | |||
| for(var i = __i; i < chain.length; i++, __i = i) if(chain[i].isCatch) { chain[i](__e); break; } | |||
| __e = null; | |||
| } | |||
| catch(e){ __e = e} | |||
| } while(__e) | |||
| } | |||
| } while ( __i < chain.length ) | |||
| state = Promise.REJECTED; | |||
| } | |||
| function resolve(result){ | |||
| if(state !== Promise.PENDING) { console.error ('Error : Promise Rejection can only be called once')} | |||
| // console.log('main promise resolve... ' + chain.length ) | |||
| p.result = result; | |||
| var __i = 0; | |||
| do { | |||
| try { for(var i = __i; i < chain.length; i++, __i = i) if(!chain[i].isCatch) { p.result = chain[i](p.result); } } | |||
| catch(e){ | |||
| var __e = e; | |||
| do { | |||
| try { | |||
| for(var i = __i; i < chain.length; i++, __i = i) if(chain[i].isCatch) { chain[i](__e); break; } | |||
| __e = null; | |||
| } | |||
| catch(e){ __e = e} | |||
| } while(__e) | |||
| } | |||
| } while ( __i < chain.length ) | |||
| state = Promise.FULFILLED; | |||
| }; | |||
| var p = { | |||
| then : function(thenfn){ | |||
| thenfn.isThen = true | |||
| chain.push(thenfn) | |||
| return p; | |||
| } | |||
| , pcatch : function(catchfn) { | |||
| catchfn.isCatch = true | |||
| chain.push(catchfn) | |||
| return p; | |||
| } | |||
| , start : function(){ | |||
| try { fn(resolve, reject) } | |||
| catch(e){ reject(e) } | |||
| } | |||
| } | |||
| return p | |||
| } | |||
| Promise.all = function(arr){ | |||
| arr.forEach = forEach; | |||
| var results = []; | |||
| return new Promise(function(resolve, reject){ | |||
| arr.forEach(function(p){ results.push(waitForResult(p))} ) | |||
| resolve(results) | |||
| }); | |||
| } | |||
| any = function(arr){ | |||
| arr.forEach = forEach; | |||
| var results = []; | |||
| return new Promise(function(resolve, reject){ | |||
| arr.forEach(function(p){ results.push(waitForResult(p))} ) | |||
| resolve(results) | |||
| }); | |||
| } | |||
| Promise.PENDING = 1 | |||
| Promise.FULFILLED = 2 | |||
| Promise.REJECTED = 3 | |||
| function waitForResult(p){ | |||
| while(p.state === Promise.PENDING) WScript.Sleep(500) | |||
| return true | |||
| } | |||
| var stampedFilePfx = function(date) { | |||
| return date.getFullYear() + | |||
| ('0' + (date.getMonth() + 1)).slice(-2) + | |||
| ('0' + date.getDate()).slice(-2) + | |||
| ('0' + date.getHours()).slice(-2) + | |||
| ('0' + date.getMinutes()).slice(-2) + | |||
| ('0' + date.getSeconds()).slice(-2); | |||
| } | |||
| function nodeShellExec(cmd, cargs){ | |||
| var p = new Promise(function(resolve, reject){ | |||
| var runFile = selectedinstance.root + '\\' + stampedFilePfx(new Date()) + cmd + cargs + "out.txt"; | |||
| // console.log(runFile) | |||
| shell.ShellExecute('cmd', '/c ' + cmd + ' ' + cargs + " > " + runFile , "", "", 1); | |||
| // var WshFinished = 1 | |||
| // var WshFailed = 2 | |||
| // var strOutput = 'Did not work' | |||
| // switch(shell.Status){ | |||
| // case WshFinished : | |||
| // strOutput = oShell.StdOut.ReadAll; | |||
| // break; | |||
| // case WshFailed : | |||
| // strOutput = oShell.StdErr.ReadAll; | |||
| // break; | |||
| // } | |||
| // WScript.Echo(strOutput) | |||
| while(!fso.FileExists(runFile)) { | |||
| WScript.Sleep(500) | |||
| } | |||
| var objFileToRead = fso.OpenTextFile(runFile,1) | |||
| var strFileText = objFileToRead.ReadAll() | |||
| objFileToRead.Close() | |||
| fso.DeleteFile(runFile) | |||
| resolve(strFileText) | |||
| }) | |||
| return p; | |||
| } | |||
| // Detect or specify install directory. | |||
| var selectedinstance = { | |||
| root : fso.GetAbsolutePathName(".") | |||
| } | |||
| var downloadsdir = selectedinstance.root + '/Downloads'; | |||
| var fs = { | |||
| writeFileSync : function(filepath, text) { | |||
| WScript.echo(filepath) | |||
| var fh = fso.CreateTextFile(filepath, true); | |||
| fh.WriteLine(text); | |||
| fh.Close(); | |||
| }, | |||
| existsSync : function(path){ | |||
| // fso.FileExists(path) | |||
| return fso.FolderExists(path) | |||
| } | |||
| , mkdirSync : function(path) { | |||
| fso.CreateFolder(path) | |||
| } | |||
| } | |||
| var path = { | |||
| dirname : function(filepath) { | |||
| var normalized = filepath.replace(/\//g,'\\'); | |||
| var li = normalized.lastIndexOf("\\") | |||
| if( li > -1) { | |||
| return normalized.substring(0, li) | |||
| } | |||
| } | |||
| } | |||
| function ensureDirectoryExistence(filePath) { | |||
| var dirname = path.dirname(filePath); | |||
| if (fs.existsSync(dirname)) { | |||
| return filePath; | |||
| } | |||
| ensureDirectoryExistence(dirname); | |||
| fs.mkdirSync(dirname); | |||
| return filePath; | |||
| } | |||
| var getTaskCheckExists = function(command, options) { | |||
| options = options || {} | |||
| return function() { | |||
| var p = nodeShellExec.apply(null, ['where', [command]]) | |||
| if (options.ignorefailures) { | |||
| return p.then(function(v) { | |||
| // WScript.Echo('firstThen ' + v); | |||
| return v }).pcatch( function(e) { // Ignore. Not a major error. | |||
| return false; | |||
| }) | |||
| } | |||
| else return p.then(function() { | |||
| // WScript.Echo('firstThen ddd'); | |||
| return v }); | |||
| } | |||
| } | |||
| function verifyAndInstallPrerequisites() { | |||
| fs.writeFileSync(ensureDirectoryExistence(downloadsdir + '/readme.txt'), getVersion() + ' Your local downloads for this instance'); | |||
| var downloadbatch = | |||
| "::************************************************************************** \ | |||
| :Download_ <url> <File> \ | |||
| Powershell.exe ^ \ | |||
| $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'; ^ \ | |||
| [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols; ^ \ | |||
| (New-Object System.Net.WebClient).DownloadFile('%1','%2') \ | |||
| exit /b \ | |||
| ::**************************************************************************"; | |||
| fs.writeFileSync('download.bat', downloadbatch); | |||
| var downloadtasks = []; | |||
| var installtasks = []; | |||
| prerequisites.forEach(function(preq) { | |||
| var p = null; | |||
| downloadtasks.push( | |||
| p = preq.exists().then(function(exists) { | |||
| if (exists) console.log( preq.shellcmd + ' exists'); | |||
| else { | |||
| console.log(preq.shellcmd + ' is not installed'); | |||
| return preq.preinstallsteps().then(function(){ | |||
| installtasks.push(task.install); | |||
| }) | |||
| } | |||
| } | |||
| )); | |||
| p.start() | |||
| }); | |||
| return Promise.all(downloadtasks).then(function(){ return any(installtasks) }) | |||
| } | |||
| var prerequisites = [ | |||
| { | |||
| shellcmd: 'git', | |||
| url: 'https://github.com/git-for-windows/git/releases/download/v2.31.0.windows.1/Git-2.31.0-64-bit.exe' | |||
| , installer: 'Git-2.31.0-64-bit.exe' | |||
| , installcmd: ['cmd', ['/c', 'start', | |||
| '/WAIT', downloadsdir + '/' + 'Git-2.31.0-64-bit.exe' | |||
| , '/VERYSILENT' | |||
| // , '/MERGETASKS=!runcode' // This is required only for vscode... | |||
| ]] | |||
| , preinstallsteps: function() { | |||
| var prompt = cli.prompter; | |||
| var steps = [ | |||
| function(){ | |||
| if (!existsSync(downloadsdir + '/' + this.installer)) { | |||
| return nodeShellExec(selectedinstance.root + '/.elxr/run-${runtimestamp}/download.bat', [this.url, downloadsdir + '/' + this.installer]) | |||
| } | |||
| else return Promise.resolve(true) | |||
| } | |||
| ] | |||
| var prompts = [ | |||
| function() {prompt.ask('git user name : ( <= ' + gitUser + ' )').then( function(user){ gitUser = user; })} | |||
| , function() { prompt.ask('git email : ( <= ' + gitEmail + ' )').then(function(email) { gitEmail = email; })} | |||
| ] | |||
| return any([any(steps), any(prompts)]) | |||
| } | |||
| , installsteps: function () { | |||
| return any([this.installcmd].map(callsheltask)) | |||
| } | |||
| , postinstallsteps: function(){ | |||
| var prompt = cli.prompter; | |||
| var gitUser = 'guest'; | |||
| var gitEmail = 'guest@bbh.org.in'; | |||
| var prompts = []; | |||
| prompts.push( | |||
| function(){ | |||
| var choices = { 0 : 'guest', 1 : 'chessdemo' } | |||
| return cli.prompt(choices, 'git user name').then(function(gituser) { gitUser = gituser}) | |||
| } | |||
| ) | |||
| prompts.push( | |||
| function(){ | |||
| var choices = { 0 : 'guest@bbh.org.in', 1 : 'chessdemo@bbh.org.in' } | |||
| return cli.prompt(choices, 'git user email').then(function(gitemail) { gitEmail = gitemail}) | |||
| } | |||
| ) | |||
| return any(prompts).then(function(){ | |||
| var steps = [ | |||
| ['git', ['config', '--global', '--add', 'user.name', gitUser]] | |||
| , ['git', ['config', '--global', '--add', 'user.email', gitEmail]] | |||
| ] | |||
| return any(steps.map(callsheltask)).then(function(){ | |||
| }) | |||
| }); | |||
| } | |||
| , install: function () { | |||
| return any([ /*this.preinstallsteps,*/ this.installsteps.bind(this), this.postinstallsteps.bind(this)]) | |||
| } | |||
| , verifyAndInstall : function(){ | |||
| var self = this; | |||
| return self.exists().then( function(exits) { | |||
| if(exists) return self.getUser(null, self.postinstallsteps.bind(self)) | |||
| else return self.install(); | |||
| }) | |||
| } | |||
| , exists : function(next){ | |||
| var self = this; | |||
| return getTaskCheckExists(this.shellcmd, { ignorefailures: true })().then(function(exists) { | |||
| if(exists && exists.indexOf(self.shellcmd) > -1 ) { | |||
| // console.log(exists + ' git exists') | |||
| return true; | |||
| } | |||
| else return false | |||
| }) | |||
| } | |||
| , getUser : function(repo, onNoResult){ | |||
| onNoResult = onNoResult || function(){return false} | |||
| var globalOrLocal = '--global'; | |||
| if(!repo) globalOrLocal = '--global'; | |||
| else globalOrLocal = '--local' | |||
| return any([['git', ['config', globalOrLocal, '--get-all', 'user.name']]].map(callsheltask)).then(function(result){ | |||
| // not yet configured. | |||
| if(!result.success) return onNoResult() | |||
| else { | |||
| var users = result.messages[0].trim().split('\n'); | |||
| if(users.length === 0 || | |||
| users.length === 1 && users[0] === 'guest') { | |||
| return onNoResult() | |||
| } | |||
| else return users[0]; // PB : TODO == We should probably prompt with all the users available for selection ! | |||
| } | |||
| }) | |||
| .pcatch(function(e){ | |||
| console.log(e) | |||
| return onNoResult() | |||
| }) | |||
| } | |||
| } | |||
| , | |||
| { | |||
| shellcmd: 'node', | |||
| url: 'https://nodejs.org/dist/v14.16.0/node-v14.16.0-x64.msi' | |||
| , installer: 'node-v14.16.0-x64.msi' | |||
| , installcmd: ['MSIEXEC.exe', ['/i' | |||
| , downloadsdir + '/' + 'node-v14.16.0-x64.msi' | |||
| , 'ACCEPT=YES', '/passive']] | |||
| , install : function() { return any([this.installcmd].map(callsheltask)) } | |||
| , exists : function(next){ | |||
| var self = this; | |||
| return getTaskCheckExists(this.shellcmd, { ignorefailures: true })().then(function(exists) { | |||
| if(exists && exists.indexOf(self.shellcmd) > -1 ) { | |||
| // console.log(self.shellcmd + ' ' + exists + ' node exists') | |||
| return true | |||
| } | |||
| else { | |||
| // console.log(self.shellcmd + ' ' + exists + ' node doesnt exist') | |||
| return false | |||
| } | |||
| }) | |||
| } | |||
| , preinstallsteps : function(){ | |||
| return true; | |||
| } | |||
| } | |||
| ] | |||
| prerequisites.forEach = forEach; | |||
| verifyAndInstallPrerequisites() | |||