選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
3年前
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724
  1. var scripthostName = 'node'
  2. var __Promise = {};
  3. var promises = [];
  4. function startPromises(){
  5. promises.forEach(function(p){
  6. // console.log(p.chain)
  7. p ? p() : null;
  8. // promises.splice(0,1)
  9. })
  10. }
  11. function isWin(){ return /^win/.test(process.platform) }
  12. var stampedFilePfx = function(date) {
  13. return date.getFullYear() +
  14. ('0' + (date.getMonth() + 1)).slice(-2) +
  15. ('0' + date.getDate()).slice(-2) +
  16. ('0' + date.getHours()).slice(-2) +
  17. ('0' + date.getMinutes()).slice(-2) +
  18. ('0' + date.getSeconds()).slice(-2);
  19. }
  20. var runtimestamp = (new Date()).getTime();
  21. try {
  22. console.log("detected node")
  23. // var WScript = console || WScript // Dummy
  24. // console.Echo = console.log
  25. __Promise = Promise
  26. var __require = require
  27. var map = Array.map
  28. function startPromises(){
  29. promises.forEach(function(p){
  30. // console.log(p.chain)
  31. p ? Promise.resolve(p) === p ? p : p() : null;
  32. // promises.splice(0,1)
  33. })
  34. }
  35. // --------------------------------------------
  36. // Node Exists. Lets launch ourselves in Node itself
  37. WScript = function(){}
  38. WScript.Echo = function(m){
  39. console.log('Invalid Wscript')
  40. throw "Failed in Node Run."
  41. }
  42. var wait = function(ms, cb) {any
  43. return new __Promise(function(resolve){ setTimeout(resolve, ms) } ).then(function(){ cb() });
  44. }
  45. var fs = require('fs')
  46. var existsSync = require('fs').existsSync;
  47. var existsSyncFolder = existsSync
  48. var path = require('path');
  49. console.log('before cliverse')
  50. var cli = require('./cliverse')
  51. var nodeShellExec = cli.nodeShellExec;
  52. console.log('before bbhverse')
  53. var utils = require('bbhverse');
  54. var any = utils.any;
  55. var wait = setTimeout
  56. // --------------------------------------------
  57. // PB : TODO -- This should be parent dir if elxr is already installed.
  58. var selectedinstance = { root : path.resolve(".") }
  59. __main(selectedinstance)
  60. }
  61. catch(e) {
  62. WScript.Echo('detected wsh')
  63. scripthostName = 'wsh'
  64. WScript.Echo(WScript.FullName)
  65. // WScript.Echo('--' + WScript.Arguments(0) + '--')
  66. // WScript.Echo('------------ALL-----------')
  67. // var argEnumerator = new Enumerator(WScript.Arguments)
  68. // for(; !argEnumerator.atEnd(); argEnumerator.moveNext()){
  69. // WScript.Echo('-arg-' + argEnumerator.item() + '-arg-')
  70. // }
  71. // // Unnamed
  72. // WScript.Echo('------------UNNAMED-----------')
  73. // argEnumerator = new Enumerator(WScript.Arguments.Unnamed)
  74. // for(; !argEnumerator.atEnd(); argEnumerator.moveNext()){
  75. // WScript.Echo('-arg-' + argEnumerator.item() + '-arg-') // Value
  76. // }
  77. // // Named
  78. // WScript.Echo('------------NAMED-----------')
  79. // argEnumerator = new Enumerator(WScript.Arguments.Named)
  80. // for(; !argEnumerator.atEnd(); argEnumerator.moveNext()){
  81. // // WScript.Echo('-arg-' + argEnumerator.item(argEnumerator) + '-arg-') // Key
  82. // WScript.Echo('-key-' + argEnumerator.item() + '-key-') // Key
  83. // WScript.Echo('-val=' + WScript.Arguments.Named(argEnumerator.item()) + '=val-') // Value
  84. // }
  85. // cscript elxr/i.win.js /all:true
  86. var all = WScript.Arguments.Named('all');
  87. trim = function(str) { return str.replace(/^\s+|\s+$/g, ''); };
  88. var fs = new ActiveXObject('Scripting.FileSystemObject');
  89. var WshShell = WScript.CreateObject("WScript.Shell")
  90. var ENV = WshShell.Environment("Process")
  91. var sfn = WScript.ScriptFullName
  92. // WScript.Echo(sfn)
  93. var cd = fs.GetAbsolutePathName(".")
  94. var cfn = cd + '\\i.win.js'
  95. // WScript.Echo(cfn)
  96. var waslaunchedwithenv = trim(ENV.Item('LAUNCHEDWITHENV'));
  97. // for(e=new Enumerator(ENV); !e.atEnd(); e.moveNext()) WScript.echo(e.item(e));
  98. if(waslaunchedwithenv !== "YES"){
  99. var a = fs.CreateTextFile("launchwithenv.bat", true)
  100. a.WriteLine("@echo off")
  101. a.WriteLine("echo %PATH%")
  102. var gitpath = "C:\\Program Files\\Git\\cmd"
  103. var nodepath = "C:\\Program Files\\nodejs\\"
  104. var codepath = "C:\\Users\\Pradeep\\AppData\\Local\\Programs\\Microsoft VS Code\\bin"
  105. var python2path = "C:\\Python27" // Python installer doesnt write to PATH!!!
  106. a.WriteLine("set PATH=%PATH%;" + gitpath )
  107. a.WriteLine("set PATH=%PATH%;" + nodepath )
  108. a.WriteLine("set PATH=%PATH%;" + codepath )
  109. a.WriteLine("set PATH=%PATH%;" + python2path )
  110. // a.WriteLine("set LAUNCHEDWITHENV=YES" )
  111. var __ALIAS__STAMP__ = '9e7bebe0-1f57-11ec-8f88-778ffeea9d1b'
  112. var currentIsExlr = function() {
  113. if(fs.FileExists('./' + __ALIAS__STAMP__)) return true
  114. }
  115. var runningInExlr = currentIsExlr()
  116. if(cfn === sfn && runningInExlr) {
  117. a.WriteLine("cd ..");
  118. a.WriteLine("SET LAUNCHEDWITHENV=YES && cscript "+cfn+" /all:true") // PB : TODO -- Retain all script args...
  119. }
  120. else {
  121. var guesselxr = fs.FileExists(cd + './elxr/' + __ALIAS__STAMP__)
  122. if(guesselxr) {
  123. a.WriteLine("SET LAUNCHEDWITHENV=YES && cscript "+cd + './elxr/' + 'i.win.js' +" /all:true")
  124. }
  125. else a.WriteLine("SET LAUNCHEDWITHENV=YES && cscript "+sfn+" /all:true")
  126. }
  127. // a.WriteLine("powershell.exe ^")
  128. // a.WriteLine("[Environment]::GetEnvironmentVariable('Path')" )
  129. a.Close()
  130. WshShell.run("cmd /k launchwithenv.bat")
  131. WScript.Quit()
  132. // WshShell.run("powershell -noexit [Environment]::GetEnvironmentVariable(\"\"Path\"\"\) ")
  133. // WshShell.run("powershell -noexit [Environment]::SetEnvironmentVariable(\"\"Path\"\", $env:Path + \"\";C:\\tttt\"\", \"\"Machine\"\"\) ")
  134. }
  135. console = {
  136. log : function(m) { WScript.Echo(m)}
  137. , error : function(m) {WScript.Echo(m) }
  138. , dir : function(o) {
  139. for(var i in o){ console.log(i + ' : ' + o[i])}
  140. }
  141. }
  142. // if(!String.prototype.trim) String.prototype.trim = function(){
  143. // return this.replace(/^\s+|\s+$/g, '');
  144. // };
  145. // var ovrrides = {
  146. // resolve : function(v){
  147. // if(v && v.then) return v;
  148. // var p = new Promise(function(resolve, reject){ resolve(v) });
  149. // return p;
  150. // }
  151. // };
  152. // // --------------------------------------------
  153. // // Cscript
  154. var wsh = true;
  155. function isWin(){ return true; }
  156. // If UCase( Right( WScript.FullName, 12 ) ) = "\CSCRIPT.EXE" Then
  157. var clii = {
  158. question : function(q, answercb){
  159. WScript.Echo(q)
  160. // console.log('WScript.StdIn : ' + WScript.StdIn.ReadLine() + ' ==== ')
  161. var answer = WScript.StdIn.ReadLine()
  162. answercb(answer)
  163. }
  164. }
  165. var prompter = {
  166. ask : function(q){
  167. // Needs to be serialized. Parallel asks are not possible.
  168. // const clii = readline.createInterface({ input: process.stdin, output: process.stdout });
  169. return new Promise(function(resolve, reject){
  170. clii.question(q, function(answer){
  171. // clii.close();
  172. // console.log("resolve is being called");
  173. resolve(answer)
  174. })
  175. })
  176. }
  177. }
  178. var cli = {
  179. prompt : function(choices, label, defaultchoice){
  180. var options = [];
  181. // console.dir(choices)
  182. choices.forEach = forEach
  183. choices.forEach(function(choice, i, a){
  184. // console.log(choice)
  185. // console.log('------------------------')
  186. // console.log( ((+i) + 1) + ' ' + choice )
  187. options.push( ((+i) + 1) + ' ' + choice )
  188. // console.log('------------------------')
  189. })
  190. // console.log(options)
  191. return prompter.ask( label + '\n' + options.join('\n') + '\n default ( <= ' + (defaultchoice || choices[0]) + ' ) : '
  192. ).then( function(choice){
  193. if(!choice) return defaultchoice || choices[0];
  194. if(choice && isNaN(+choice)) return choice;
  195. return choices[(+choice) - 1];
  196. })
  197. }
  198. }
  199. var any = function(iterable, continueOnFailure) {
  200. // var cancelsignal = Symbol()
  201. if(!iterable.reduce) iterable.reduce = reduce
  202. // console.log('iterable.reduce ' + iterable.reduce)
  203. var cancelsignal = "cancelme{mangledrunid}"
  204. return iterable.reduce(
  205. function(p, tasq, i ,a) {
  206. // console.dir(a)
  207. // console.log('Entered')
  208. var handleError = function(err, pVal){
  209. if(err !== cancelsignal) {
  210. // Cancel only once on first failure.
  211. console.warn('Possible failure for task with result : ' )
  212. console.log('Failed : ' + err.message + ' ')
  213. console.dir(pVal)
  214. console.dir(p)
  215. if(i>0 && a[i-1].info) console.dir(a[i-1].info)
  216. console.error('Error : ' + err.stack)
  217. console.error(a[i-1])
  218. a[i-1] ? console.log("tasq : " + a[i-1].toString()) : null;
  219. if(!continueOnFailure) {console.log("Cancelling remaining on any one failure ..."); throw cancelsignal}
  220. else return pVal;
  221. // tasq ? console.log("tasq : " + tasq.toString()) : null; // Previous task is what failed not the one we are going to run.
  222. }
  223. }
  224. if(Promise.resolve(p) === p ) {
  225. if(i>0 && a[i-1].info) p.info = a[i-1].info;
  226. console.dir(' p.then is ' + p.then)
  227. return p.then( function(pVal){
  228. // Falsy values are no longer treated as task failure exceptions. Specially for Promises.
  229. // Even tasq function wrappers are required to return promises that eventually either resolve or reject..
  230. // Failures are known for promises on reject.
  231. // In future if we support direct sync function execution with a result examination for failure
  232. // we could examine the result of the function as falsy's... or a result evaluator handler needs to be passed in...
  233. // if(!pVal) handleError({ error : true, message : 'Failed without result' }, pVal)
  234. // Truthy values are failures if obj has error=true.
  235. if(pVal && pVal.error) handleError(pVal, pVal)
  236. var trycall = function(tasq){
  237. try {
  238. var result = tasq() // PB : TODO -- Handle scope for call
  239. if(tasq.resultHandler) return tasq.resultHandler(result)
  240. // else (Promise.resolve(result) === result ) ? result.start() : null
  241. return result
  242. } catch (error) {
  243. console.error(error);
  244. console.error('Error : ' + error ? error.stack : 'No stack')
  245. if(!continueOnFailure) throw error; // PB : TODO -- Support array of results for any with or without continueonfailure.
  246. }
  247. }
  248. var handleNext = function(){
  249. // console.log('Task finished with result : ')
  250. // console.dir(pVal)
  251. if(i>0 && a[i-1].info) console.dir(a[i-1].info)
  252. if(!tasq && !continueOnFailure) { console.log('Error : No task specified.'); throw false;}
  253. else if(!tasq) { console.log('Error : No task specified.'); return false;}
  254. return (Promise.resolve(tasq) === tasq ) ? tasq /*.start()*/ : trycall(tasq) ;
  255. }
  256. if(Promise.resolve(pVal) === pVal) {
  257. // Passed in function retured a promise. We still need to wait for it.
  258. pVal.then(function(pVal){ return handleNext(); })
  259. }
  260. else return handleNext()
  261. })['catch'](function(error) {
  262. if(error !== cancelsignal) {
  263. console.log('E3 : i = ' + i);
  264. if(error.result) console.error(error.result)
  265. console.error('Error : ' + (error.message || error.messages))
  266. console.error('Error : ' + error.stack)
  267. tasq ? console.log("tasq : " + tasq.toString()) : null;
  268. console.log('debugData 3-------------------------');
  269. // handleError()
  270. throw error
  271. }
  272. else throw cancelsignal;
  273. })
  274. }
  275. else if(!p) {
  276. handleError({ error : true, message : 'Failed without result' }, pVal)
  277. console.log("Bypass remaining on prior failure");
  278. return false; // All remaining tasks will return false in the any results even if they are promisies still running or functions not initiated.
  279. }
  280. else return p; // A truthy value
  281. }
  282. , Promise.resolve(true)
  283. );
  284. }
  285. // __Promise = ovrrides
  286. // PB : TODO -- iterators are messed up in cscript without enumerables...
  287. function forEach(eachFn, o){
  288. // console.dir(this)
  289. // console.log('------------------------------------')
  290. // console.log(''+ {})
  291. // console.log('------------------------------------')
  292. if('' + this === '[object Object]') {
  293. // console.log('' + this)
  294. // console.dir(this)
  295. // var o = this
  296. // for(var i in o){ console.log(i + ' : ' + o[i])}
  297. for(var i in this){
  298. if(i === 'forEach') continue; // Enumerable in cscript not supported ???
  299. // console.log(i)
  300. eachFn(this[i], i, this)
  301. }
  302. }
  303. else {
  304. for(var i=0; i<this.length; i++) eachFn(this[i], i, this)
  305. }
  306. }
  307. function reduce(reducnFn, iv){
  308. var acc = iv
  309. for(var i=0; i<this.length; i++) {acc = reducnFn(acc, this[i], i, this) }
  310. return acc;
  311. }
  312. function map(eachFn){
  313. var mapped = []
  314. for(var i=0; i<this.length; i++) mapped.push(eachFn(this[i]))
  315. return mapped
  316. }
  317. var wait = function(cb, ms) { WScript.Sleep(ms); cb() }
  318. var fso = new ActiveXObject('Scripting.FileSystemObject');
  319. var existsSync = function(filepath){ return fso.FileExists(filepath) }
  320. var fs = {
  321. writeFileSync : function(filepath, text) {
  322. // console.log('------------------writeFileSync----------------------')
  323. // console.log(filepath)
  324. // console.log('------------------writeFileSync----------------------')
  325. var fh = fso.CreateTextFile(filepath, true);
  326. fh.WriteLine(text);
  327. fh.Close();
  328. }
  329. , mkdirSync : function(path) {
  330. fso.CreateFolder(path)
  331. }
  332. , readFileSync : function(filepath){
  333. var objFileToRead = fso.OpenTextFile(filepath,1)
  334. var strFileText = objFileToRead.ReadAll()
  335. objFileToRead.Close()
  336. return strFileText
  337. }
  338. , unlinkSync : function(filepath){ fso.DeleteFile(filepath) }
  339. }
  340. var path = {
  341. resolve : function(path){ return fso.GetAbsolutePathName(path) }
  342. , dirname : function(filepath) {
  343. var normalized = this.normalize(filepath)
  344. var li = normalized.lastIndexOf("\\")
  345. if( li > -1) {
  346. return normalized.substring(0, li)
  347. }
  348. }
  349. , normalize : function(path){
  350. return path.replace(/\//g,'\\');
  351. }
  352. }
  353. // Detect or specify install directory.
  354. var selectedinstance = { root : path.resolve(".") }
  355. var existsSyncFolder = function(path){
  356. return fso.FolderExists(path)
  357. }
  358. var shell = new ActiveXObject('shell.application');
  359. promises.forEach = forEach
  360. function startPromises(){
  361. promises.forEach(function(p){
  362. // console.log(p.chain)
  363. p.start();
  364. // promises.splice(0,1)
  365. })
  366. }
  367. function batchshellescape(str) {
  368. return str.replace('=', '^=')
  369. }
  370. function nodeShellExec(command, cargs, options){
  371. // for(var arg=0; arg < cargs.length; arg++) {
  372. // // cargs[arg] = '"' + batchshellescape(cargs[arg]) +'"';
  373. // cargs[arg] = '"' + cargs[arg] +'"';
  374. // }
  375. var elevatedshellexecute = function(cmd, argstr){
  376. shell.ShellExecute(cmd, argstr , "", "", 1);
  377. }
  378. var shellExec = function(cmd, argstr){
  379. var objShell = WScript.createobject("wscript.shell")
  380. // console.log(argstr.join( ' '))
  381. console.log(cmd + ' ' + argstr.join(' '))
  382. var oExec = objShell.Exec(cmd + ' ' + argstr.join(' '))
  383. var result = {}
  384. var shellresult = { shell : objShell, result : result }
  385. var WshRunning = 0
  386. var WshFinished = 1
  387. var WshFailed = 2
  388. while(oExec.Status === WshRunning){
  389. WScript.StdOut.write('s.')
  390. WScript.Sleep(500)
  391. }
  392. var strOutput = '\n'
  393. switch(oExec.Status) {
  394. case WshFinished :
  395. strOutput = oExec.StdOut.ReadAll()
  396. result.success = true;
  397. result.code = 0
  398. break;
  399. case WshFailed :
  400. strOutput = oExec.StdErr.ReadAll()
  401. result.success = false;
  402. result.code = WshFailed
  403. break;
  404. default : strOutput = 'failed'
  405. break;
  406. }
  407. result.result = command + ' ' + cargs + ' exited with code ' + result.code
  408. result.messages = [strOutput]
  409. // console.log(strOutput)
  410. // WScript.Echo(oExec.Status)
  411. // WScript.Echo(oExec.ProcessID)
  412. // WScript.Echo(oExec.ExitCode)
  413. // console.log(objShell.StdOut.ReadAll)
  414. // console.log(objShell.StdErr.ReadAll)
  415. // objShell = WScript.createobject("wscript.shell")
  416. objShell = null;
  417. return shellresult;
  418. }
  419. var p = null;
  420. var pworker = function(resolve, reject){
  421. // console.dir(p)
  422. var pfx = selectedinstance.root + '\\.elxr\\run-' + runtimestamp + '\\' + stampedFilePfx(new Date())
  423. // console.log('p.chain.length ================ ' + p.chain.length)
  424. options = options || {
  425. runFile : path.normalize( pfx + "out.txt")
  426. // runFile : null
  427. }
  428. var runFile = null;
  429. var runFile = options.runFile || pfx + command + cargs + "out.txt";
  430. // console.log(runFile)
  431. var args = cargs.concat()
  432. // runFile ? (args.push(">"), args.push(runFile)) : cargs
  433. // console.log(command + ' ' + args.join(' '))
  434. // command = 'cmd'
  435. // args = ['/c', 'start',
  436. // '/WAIT', selectedinstance.root + '/Downloads' + '/' + 'Git-2.33.0.2-64-bit.exe'
  437. // , '/VERYSILENT'
  438. // // , '/MERGETASKS=!runcode' // This is required only for vscode...
  439. // ]
  440. var runbat = path.normalize(pfx + "run.bat")
  441. // console.log('runbat : ' + runbat)
  442. fs.writeFileSync(runbat,
  443. '@echo off \r\n' +
  444. (options.cwd ? 'cd ' + options.cwd + ' \r\n' : '') +
  445. // ' cmd /k notepad.exe \r\n' +
  446. command + ' ' + args.join(' ') + ' \r\n' +
  447. 'cmd /c echo done >> ' + runFile + ' \r\n' +
  448. 'echo done'
  449. )
  450. // fs.writeFileSync(runFile, 'started')
  451. // WScript.Quit()
  452. // elevatedshellexecute(runFile)
  453. // while(!existsSync(runbat)) { wait(function(){
  454. // console.log('awiting batch : ' + runbat)
  455. // // shellExec( 'start', ['/W', '/b', runbat])
  456. // // shellExec( 'cmd', ['/k', '/b', runbat])
  457. // shellExec( command, args)
  458. // // cmd /b /c
  459. // }, 500) }
  460. console.log(options.waitmsg || ('awaiting ' + command + ' ' + args.join(' ')))
  461. var shellresult = shellExec( 'cmd', [ '/c', runbat])
  462. // var shellresult = shellExec( 'cmd', ['/c', runbat])
  463. // var shellresult = shellExec( command, args)
  464. var wrapup = function(result) {
  465. // console.log('Wrapping up')
  466. try {
  467. // console.log('resolving.....................');
  468. // console.log('--------------P' + result.messages.join(' ').trim() +'P--------------')
  469. // if(result.messages.join().trim()) resolve(result)
  470. // else reject(result)
  471. resolve(result)
  472. }
  473. catch(e){
  474. // console.dir(e)
  475. if(e.message === 'Input past end of file') {
  476. // console.log('---------------------------------------')
  477. // console.dir(result)
  478. resolve(result)
  479. }
  480. else {
  481. // console.dir(e)
  482. reject(e)
  483. }
  484. }
  485. }
  486. // if(runFile){
  487. // var waitr = function(){
  488. // WScript.StdOut.write('w.')
  489. // if(existsSync(runFile)) {
  490. // var strOutput = fs.readFileSync(runFile)
  491. // shellresult.result.messages = [strOutput]
  492. // wrapup(shellresult.result)
  493. // fs.unlinkSync(runFile)
  494. // }
  495. // // console.dir(shellresult.result)
  496. // wait( waitr, 500)
  497. // }
  498. // // console.log(wait)
  499. // wait( waitr, 500)
  500. // }
  501. // else {
  502. // console.log('There is no runfile.')
  503. console.log(shellresult.strOutput)
  504. wrapup(shellresult.result)
  505. // }
  506. }
  507. p = new Promise(pworker)
  508. // promises.push(p)
  509. // // Promise tThens don't get hooked up... we need to postpone promise starting until all the thens are registered...
  510. // wait(function(){
  511. // console.log('p.chain.length' + p.chain.length)
  512. // p.start() } , 5000) // Bind and setTImeout is not supported by JScript
  513. return p;
  514. }
  515. createPromiseClass(/*ovrrides*/)
  516. __main( selectedinstance )
  517. function createPromiseClass(overrides) {
  518. function reject(e){
  519. var p = this;
  520. console.log('Promise Rejection : ' + p.fn)
  521. console.dir(e)
  522. // throw e;f
  523. if(p.state !== PromiseClass.PENDING) { console.error ('Error : Promise Rejection can only be called once')}
  524. var __i = 0;
  525. var __e = e;
  526. do {
  527. for(var i = __i; i < p.chain.length; i++, __i = i) if(p.chain[i].isCatch) break;
  528. try {
  529. for(var i = __i; i < p.chain.length; i++, __i = i) if(p.chain[i].isCatch) { p.chain[i](__e); break; }
  530. __i++;
  531. __e = null;
  532. }
  533. catch(e){ __i++; __e = e}
  534. } while(__e)
  535. do {
  536. try { for(var i = __i; i < p.chain.length; i++, __i = i) if(!p.chain[i].isCatch) { p.result = p.chain[i](p.result); } }
  537. catch(e){
  538. __i ++;
  539. do {
  540. try {
  541. for(var i = __i; i < p.chain.length; i++, __i = i) if(p.chain[i].isCatch) { p.chain[i](__e); break; }
  542. __i ++;
  543. __e = null;
  544. }
  545. catch(e){ __i++; __e = e}
  546. } while(__e)
  547. }
  548. } while ( __i < p.chain.length )
  549. p.state = PromiseClass.REJECTED;
  550. }
  551. function resolve(result){
  552. var p = this;
  553. // console.log(result + ' resolve was called with chain length ' + p.chain.length )
  554. if(p.state !== PromiseClass.PENDING) { console.error ('Error : Promise Resolve can only be called once')}
  555. p.result = result;
  556. if(PromiseClass.resolve(p.result) === p.result) {
  557. // console.log( 'result is still a promise waiting for result and promisechain' )
  558. waitForResult(p.result, function(r){ p.processchain(r) })
  559. }
  560. else {
  561. // console.log( 'result is value waiting for promisechain' )
  562. // console.dir(result)
  563. return p.processchain(result)
  564. }
  565. };
  566. function processchain(r){
  567. var __i = 0;
  568. var i = __i;
  569. var __e = null;
  570. p = this;
  571. // console.log('processchain chain.length : ' + p.chain.length)
  572. function __processchain(r){
  573. function waitForThen(p){
  574. if(i < p.chain.length) {
  575. if(!p.chain[i].isCatch) {
  576. // console.log('chain idx : ' + i + ' Executing : then ' + p.result + ' ' + p.chain[i])
  577. try {
  578. p.result = p.chain[i](p.result)
  579. if(PromiseClass.resolve(p.result) === p.result) {
  580. // console.log('chain idx : ' + i + ' result is still a promise starting it ')
  581. // console.dir(p.result.chain)
  582. // console.log('p.result.start : ' + p.result.start + ' ------------------ ')
  583. p.result.start()
  584. // console.log(p.result.fn + ' ------------------ ')
  585. waitForResult(p.result, function(r){
  586. // console.log('we waited')
  587. // WScript.write('.')
  588. p.result = r; i++; __i = i;
  589. waitForThen(p)
  590. })
  591. }
  592. else {
  593. i++; __i = i;
  594. waitForThen(p)
  595. }
  596. }
  597. catch(e) {
  598. i++; __i = i;
  599. __e = e;
  600. console.log('failed on index ' + __i + p.chain[__i-1] )
  601. console.dir(e)
  602. waitForCatch(p);
  603. }
  604. }
  605. else {
  606. // console.log(i + ' Skipping catch : ' + p.result + ' ' + p.chain[i])
  607. i++; __i = i;
  608. waitForThen(p)
  609. }
  610. }
  611. else return p.state = PromiseClass.FULFILLED;
  612. }
  613. function waitForCatch(p) {
  614. if(i < p.chain.length) {
  615. if(p.chain[i].isCatch) {
  616. console.log('chain idx : ' + i + ' Executing : catch : ' + p.result + ' ' + p.chain[i])
  617. try {
  618. p.result = p.chain[i](__e);
  619. if(PromiseClass.resolve(p.result) === p.result) {
  620. p.result.start()
  621. waitForResult(p.result, function(r){
  622. p.result = r; i++; __i = i;
  623. })
  624. waitForThen(p)
  625. }
  626. else {
  627. p.result = r; i++; __i = i;
  628. waitForThen(p)
  629. }
  630. }
  631. catch(e){ i++; __i = i;; __e = e; waitForCatch(p) }
  632. }
  633. else {
  634. i++; __i = i;
  635. waitForCatch(p)
  636. }
  637. }
  638. else return p.state = PromiseClass.REJECTED
  639. }
  640. waitForThen(p);
  641. }
  642. __processchain(r)
  643. }
  644. var create = function(fn){
  645. var p = {
  646. then : function(thenfn){
  647. // console.log('Adding then')
  648. thenfn.isThen = true
  649. // if(Object.prototype.toString.call(p.chain) !== '[object Array]') console.dir(p.chain)
  650. p.chain.push(thenfn)
  651. return p;
  652. }
  653. , 'catch' : function(catchfn) {
  654. catchfn.isCatch = true
  655. p.chain.push(catchfn)
  656. return p;
  657. }
  658. , start : function(){
  659. if(this.started) {
  660. console.error('Cannot start more than once...')
  661. return p
  662. };
  663. this.started = true;
  664. this.fn = fn;
  665. try { fn( function(r){
  666. // console.log('calling presolve in starter ')
  667. p.resolve(r) } , function(r){ p.reject(r) } ) }
  668. catch(e){
  669. // console.log('start catch : ' + e)
  670. // console.log('p.chain.length : ' + p.chain.length)
  671. // // console.dir(p)
  672. // console.dir(e)
  673. // console.log(fn)
  674. p.reject(e)
  675. }
  676. return p
  677. }
  678. , state : PromiseClass.PENDING
  679. , chain : []
  680. , reject : reject
  681. , resolve : resolve
  682. , processchain : processchain
  683. }
  684. p.chain.forEach = forEach;
  685. return p;
  686. }
  687. var PromiseClass = function(fn /*, donotstart */){
  688. var p = create(fn)
  689. // if(!donotstart) {
  690. // wait(function(){
  691. // console.log('p.chain.length' + p.chain.length)
  692. // p.start() } , 500) // Bind and setTImeout is not supported by JScript
  693. // }
  694. return p
  695. }
  696. PromiseClass.PENDING = 1
  697. PromiseClass.FULFILLED = 2
  698. PromiseClass.REJECTED = 3
  699. // PromiseClass.STARTED = 4
  700. PromiseClass.isSETTLED = function(p){ p.state === PromiseClass.FULFILLED || p.state === PromiseClass.REJECTED }
  701. PromiseClass.resolve = function(v){
  702. if(v && v.then) return v;
  703. var p = create(function(resolve, reject){
  704. resolve(v)
  705. });
  706. // console.log('p.chain in resolve. length ' + p.chain.length)
  707. // p.result = v;
  708. // wait(function(){ p.processchain(v) }, 0)
  709. return p;
  710. }
  711. function waitForResult(p, cb){
  712. if(!p) return cb(p)
  713. if(p.state !== PromiseClass.PENDING) cb(p.result)
  714. // console.log(p.state + ' Waiting for ..... ' + p.runFile)
  715. if(p.runFile && false) {
  716. while(!existsSync(p.runFile) && p.state === PromiseClass.PENDING) {
  717. console.log('Waiting for ResultFle'); wait(cb, 500)
  718. }
  719. cb(p.result)
  720. }
  721. else {
  722. // while(p.state === PromiseClass.PENDING) {
  723. // console.log('Waiting for Result')
  724. function waiter(){
  725. // console.log(p.result)
  726. if(p.state === PromiseClass.PENDING) wait(waiter, 500);
  727. else return cb(p.result)
  728. }
  729. wait(waiter, 500)
  730. // }
  731. }
  732. }
  733. PromiseClass.all = any; // Serialized...
  734. PromiseClass.__all = function(arr){
  735. arr.forEach = forEach;
  736. var resultPs = [];
  737. var results = [];
  738. console.log('All : ' + arr.length)
  739. var pAll = new PromiseClass(function(resolve, reject){
  740. console.log('All started : ' + pAll)
  741. // console.dir(pAll)
  742. arr.forEach(function(p){
  743. if(!p.then) { var pfn = p;
  744. p = new PromiseClass(function(resolve, reject){
  745. try{
  746. resolve(pfn())
  747. }
  748. catch(e){
  749. reject(e)
  750. }
  751. })
  752. p.start()
  753. }
  754. else {
  755. // !p.start ? p.start = function(){return p} : null
  756. // p.start()
  757. // .then( function(){ waitForResult(p, function(r){ results.push(r) }) })
  758. }
  759. resultPs.push(p)
  760. // waitForResult(p, function(r){ results.push(r) })
  761. })
  762. // PB : TODO -- This is the same as processchain!!!
  763. var allwaitr = function(){
  764. var allResolved = true
  765. console.log('resultPs : ' + resultPs.length)
  766. for(var rIdx =0; rIdx < resultPs.length; rIdx++ ){
  767. if(resultPs[rIdx]) {
  768. allResolved = false
  769. waitForResult(resultPs[rIdx], function(r){
  770. if(Promise.resolve(r) !== r) results[rIdx] = r; resultPs[rIdx] = null;
  771. })
  772. break;
  773. }
  774. }
  775. if(allResolved) {
  776. // console.log('All Reseloved')
  777. // console.dir(results)
  778. resolve(results)
  779. }
  780. else wait(allwaitr, 500)
  781. }
  782. wait(allwaitr, 500)
  783. })
  784. // pAll.chain = arr;
  785. return pAll
  786. }
  787. // PromiseClass.resolve = overrides.resolve;
  788. Promise = PromiseClass;
  789. return PromiseClass;
  790. }
  791. }
  792. function __main( selectedinstance ){
  793. var downloadsdir = path.dirname(selectedinstance.root) + '\\Downloads';
  794. var callsheltask = function(args) {
  795. // console.log('callsheltask : ' + args)
  796. return function() { return nodeShellExec.apply(null, args) } }
  797. var instanceName = 'elixir'
  798. var reposerver = 'https://git.bbh.org.in';
  799. var gitUser = 'guest';
  800. var gitpassword = 'guest';
  801. var gitEmail = 'guest@bbh.org.in';
  802. var gitPreinstalled = true;
  803. var BUILD_VERSION = '[VI]Version: {version} - built on {date}[/VI]';
  804. function getVersion() { return BUILD_VERSION; }
  805. console.log(getVersion())
  806. function ensureDirectoryExistence(filePath) {
  807. var dirname = path.dirname(filePath);
  808. if (existsSyncFolder(dirname)) {
  809. return filePath;
  810. }
  811. ensureDirectoryExistence(dirname);
  812. fs.mkdirSync(dirname);
  813. return filePath;
  814. }
  815. var getTaskCheckExists = function(command, options) {
  816. options = options || {}
  817. return function() {
  818. var runFile = path.normalize(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/' + stampedFilePfx(new Date()) + 'where' + command + "out.txt");
  819. var p = nodeShellExec.apply(null, ['cmd', ['/c', 'where', command], { runFile : runFile } ])
  820. p.runFile = runFile;
  821. if (options.ignorefailures) {
  822. return p.then(function(v) {
  823. // WScript.Echo('firstThen ' + v);
  824. return v })['catch']( function(e) {
  825. console.error(e);
  826. // Ignore. Not a major error if where command fails !!!
  827. throw e;
  828. })
  829. }
  830. else return p.then(function() {
  831. // WScript.Echo('firstThen ddd');
  832. return v });
  833. }
  834. }
  835. function verifyAndInstallPrerequisites() {
  836. fs.writeFileSync(ensureDirectoryExistence(downloadsdir + '/readme.txt'), getVersion() + ' Your local downloads for this instance');
  837. var downloadbatch =
  838. "::************************************************************************** \r\n \
  839. :Download_ <url> <File> \r\n \
  840. Powershell.exe ^\r\n \
  841. $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'; ^\r\n \
  842. [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols; ^\r\n \
  843. (New-Object System.Net.WebClient).DownloadFile('%1','%2') \r\n \
  844. exit /b \r\n \
  845. ::**************************************************************************";
  846. ensureDirectoryExistence(path.normalize(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/readme.txt'))
  847. fs.writeFileSync(path.normalize(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat'), downloadbatch);
  848. var downloadtasks = [];
  849. var installtasks = [];
  850. prerequisites.forEach(function(preq) {
  851. WScript.Echo(all)
  852. if(!all && preq.optional) return
  853. var p = preq.exists().then(function(exists) {
  854. if (exists && !preq.forceinstall) console.log( preq.shellcmd + ' exists');
  855. else {
  856. console.log('----------------------------')
  857. console.log(exists) // PB : ??? Boolean true becomes -1 ???
  858. console.log('----------------------------')
  859. if(!exists) console.log(preq.shellcmd + ' is not installed');
  860. else console.log(preq.shellcmd + ' is installed but forceinstall was specifed so re-installing');
  861. return preq.preinstallsteps().then(function(){
  862. // console.log(' task.install : ' + preq.install)
  863. installtasks.push( function(){ return preq.install() } );
  864. })
  865. }
  866. })
  867. // .then(function(res){ console.log( 'preinstallsteps ' + res)});
  868. downloadtasks.push( p )
  869. });
  870. // console.log('downloadtasks')
  871. // console.dir(downloadtasks[0])
  872. var p = Promise.all(downloadtasks).then(function(){
  873. // console.log('calling install tasks : ' + installtasks.length)
  874. return any(installtasks) })
  875. // console.log('Promise.all.chain : ' + p.chain)
  876. return p
  877. }
  878. // var choiceHandler = function(choices, choice) {
  879. // console.log('chosen : ' + choice)
  880. // var decision = choices['d'];
  881. // if (choice && choice === 'd' || !choice) {
  882. // decision = choices['d']
  883. // }
  884. // else if (isNaN((+choice))) {
  885. // decision = choice
  886. // }
  887. // else decision = choices[choice-1]
  888. // if(!decision) throw 'Invalid selection : ' + decision
  889. // return decision
  890. // }
  891. // prereq definition helpers. We can't do proper inheritance in cscript. So fallback to global functions.
  892. function exists(next){
  893. var self = this;
  894. console.log('checking existence of ' + self.shellcmd)
  895. return getTaskCheckExists(self.shellcmd, { ignorefailures: true })().then(function(exists) {
  896. // console.log('-------------exists=======================')
  897. // console.dir(exists)
  898. // console.log(self.shellcmd)
  899. // console.log(exists.messages.join(' ').toLowerCase().indexOf(self.shellcmd.toLowerCase()))
  900. if(exists && (exists.messages.join(' ').toLowerCase().indexOf(self.shellcmd.toLowerCase()) > -1) ) {
  901. console.log(' ' + self.shellcmd + ' exists')
  902. return true;
  903. }
  904. else {
  905. console.log(' ' + self.shellcmd + ' doesnt exist')
  906. return false
  907. }
  908. })['catch'](function(e){
  909. // console.log('-------------exists catch=======================')
  910. console.dir(e)
  911. return false;
  912. })
  913. }
  914. function install() {
  915. var self = this;
  916. var ifns = [self.installcmd]
  917. if(!ifns.map) ifns.map = map;
  918. console.log('Installing')
  919. return any(ifns.map(callsheltask))['catch'](function(e){
  920. if(e.code === 1602) {
  921. console.warn("Installation was probably cancelled.")
  922. }
  923. else throw e
  924. }).then(function(){
  925. return self.postinstallsteps && self.postinstallsteps()
  926. })
  927. }
  928. function unique(arr) {
  929. var hash = {}, result = [];
  930. for ( var i = 0, l = arr.length; i < l; ++i ) {
  931. if ( !hash.hasOwnProperty(arr[i]) ) { //it works with objects! in FF, at least
  932. hash[ arr[i] ] = true;
  933. result.push(arr[i]);
  934. }
  935. }
  936. return result;
  937. }
  938. // var ENV = Object.assign({}, process.env); // Shallow clone it.
  939. // WScript.echo( ENV("Path") )
  940. function sysAddPathVar(path){
  941. return true; // PB : TODO -- Not yet enabled. Remove sys path from path before saving.
  942. // Object.assign({
  943. // inherit: true, shell: true, env: ENV, title: `${command} ${args}`
  944. // }, options)
  945. // var newpath = ENV("Path").split(';');
  946. // newpath = Array.from(new Set(newpath.push(path))).join(';')
  947. var newpath = [];
  948. newpath.push(path)
  949. newpath = unique(newpath).join(';')
  950. // path.split(';').forEach(pel => { var kv = pel.split('='); kv[0] === key ? null : newpath.push(pel); } )
  951. return any([nodeShellExec('setx', [/*'/m',*/ 'PATH', '"%PATH%;' + newpath + '"' ])
  952. // , nodeShellExec('set', [/*'/m',*/ 'PATH', '"%PATH%;' + newpath + '"' ])
  953. ] );
  954. }
  955. var getCmdString = function(args){ return args[0] + ' ' + args[1].join(' ') }
  956. var getgitshelltask = function(args, onEachError) { return function(){
  957. console.log('----------getgitshelltask--------------called')
  958. return nodeShellExec( "cmd", ['/c', getCmdString(args)], args[2])
  959. // .catch( onEachError || function(e){ console.error(e) })
  960. }
  961. }
  962. var createTasq = function(args, shellT, onEachError) {
  963. var tasq = shellT ? shellT(args) : ( function(){
  964. return any([nodeShellExec.apply(null, args)])
  965. // .catch( onEachError || function(e){ console.error(e) } )
  966. })
  967. tasq.toString = function(){ return JSON.stringify(args)}
  968. return tasq;
  969. }
  970. var execserial = function(tasklist, task, shellT, onEachError){
  971. var exec = function(taskArgs){
  972. console.log('executing ' + task)
  973. var thistask = task.concat();
  974. thistask[1] = thistask[1].concat()
  975. thistask[1].push.apply(thistask[1], taskArgs)
  976. return createTasq(thistask, shellT)
  977. }
  978. tasklist.map = map
  979. console.log('execlist ' + tasklist.map(exec))
  980. return any(tasklist.map(exec))
  981. }
  982. function resetgitconfig(){
  983. // https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage
  984. // Git Credential storage...
  985. // git config --global credential.helper 'store --file ~/.gitcredentials'
  986. // git credential-store --file ~/.gitcredentials store
  987. // // notepad C:/Program Files/Git/etc/gitconfig
  988. // git config --global --unset credential
  989. // git config --edit --system
  990. // git config --global credential.helper "store --file ~/gitcredentials"
  991. // git credential fill
  992. // git credential-store --file ~/git.store store
  993. // Find system git config
  994. // git config --global --edit
  995. // git config --list --show-origin
  996. // git config --list --show-origin --show-scope
  997. // https://stackoverflow.com/questions/35942754/how-can-i-save-username-and-password-in-git
  998. // Recipie
  999. // git config --global --unset credentials.helper
  1000. // cd /path/to/my/repo
  1001. // git config --unset credential.helper
  1002. // git config --global credential.helper "store --file ~/.elxrcredentials"
  1003. // git config credential.helper 'store --file ~/.elxrcredentials'
  1004. //-- git config credential.*.username my_user_name
  1005. //-- git config credential.https://gitlab.com.username my_user_name
  1006. // git credential fill
  1007. // git config --global credential.modalprompt false // doesnst work.
  1008. // core askpass = ;;; https://stackoverflow.com/questions/37182847/how-do-i-disable-git-credential-manager-for-windows
  1009. var options = {
  1010. inherit: true, shell: true //, env: process.env
  1011. , cwd: selectedinstance.root
  1012. // , runas: processedArgs.runas
  1013. }
  1014. var task = ['git', ['config'], options]
  1015. var tasklist = [
  1016. // ['--global', '--unset credentials.helper']
  1017. // ['--unset', 'credentials.helper']
  1018. // ,
  1019. // ['credential.helper', `'store --file git_repo_credentials'`]
  1020. ['--global', 'credential.helper', '"store --file ~/.elxrcredentials"']
  1021. , ['--global', '--replace-all', 'user.name', gitUser]
  1022. , ['--global', '--replace-all', 'user.email', gitEmail]
  1023. // , ['--list']
  1024. // , ['credential', 'fill']
  1025. ]
  1026. console.log(tasklist)
  1027. var onEachError = function(e) { console.error( e.messages.join('\n') + e.result + '\n' + util.inspect(e) + '\n') }
  1028. var shellT = function(args) {
  1029. return getgitshelltask(args, onEachError)
  1030. // .catch(e => console.error( e.messages.join('\n') + e.result + '\n' + util.inspect(e) + '\n' + tasq.toString()) )
  1031. }
  1032. return execserial(tasklist, task, shellT, onEachError ).then(function(){
  1033. // git credential-store --file ./.elxrcredentials store
  1034. console.log('gathering git credentials')
  1035. var userhome = '~'
  1036. if(isWin()) userhome = '%userprofile%'
  1037. var host = reposerver.replace('https://','').replace('http://','')
  1038. var protocol = reposerver.replace('https://','') === host ? 'https' : 'http'
  1039. fs.writeFileSync('ic.txt', 'host='+host+'\r\nprotocol='+protocol+'\r\nusername='+gitUser+'\r\npassword='+gitpassword)
  1040. return nodeShellExec('git', ['credential-store', '--file', userhome + '/.elxrcredentials', 'store', '<', 'ic.txt'], options)
  1041. })
  1042. }
  1043. var gitpostinstallsteps = function(){
  1044. try {
  1045. // Load just in case someone was smart enough to fill in before install.
  1046. var icf = fs.readFileSync( 'installchoices.js')
  1047. icf = icf.replace('module.exports = ', 'icf = ')
  1048. console.log(icf)
  1049. icf = eval(icf)
  1050. // console.log(icf.reposerver)
  1051. instanceName = icf.instanceName
  1052. reposerver = icf.reposerver;
  1053. gitUser = icf.gitUser;
  1054. gitEmail = icf.gitEmail
  1055. }
  1056. catch(e) {
  1057. console.error(e)
  1058. }
  1059. // gitpassword = icf.??? ; we do not store password it should already be cached in the credential store.
  1060. // PB : TODO -- Detect failure or cancellation before attenpting postinstall steps...
  1061. var steps = [];
  1062. steps.push(
  1063. function(){
  1064. var choices = { 0 : 'elixir' }
  1065. return cli.prompt(choices, 'instanceName', instanceName).then(function(choice){ instanceName = choice } )
  1066. }
  1067. )
  1068. steps.push(
  1069. function(){
  1070. var choices = { 0 : 'https://git.bbh.org.in' }
  1071. return cli.prompt(choices, 'reposerver', reposerver).then(function(choice){ reposerver = choice } )
  1072. }
  1073. )
  1074. steps.push(
  1075. function(){
  1076. var choices = { 0 : 'guest', 1 : 'chessdemo' }
  1077. return cli.prompt(choices, 'git user name', gitUser).then(function(choice){ gitUser = choice } )
  1078. }
  1079. )
  1080. steps.push(
  1081. function(){
  1082. var choices = { }
  1083. return cli.prompt(choices, 'git password', gitpassword).then(function(choice){ gitpassword = choice } )
  1084. }
  1085. )
  1086. steps.push(
  1087. function(){
  1088. var choices = { 0 : 'guest@bbh.org.in', 1 : 'chessdemo@bbh.org.in' }
  1089. return cli.prompt(choices, 'git user email', gitEmail).then(function(choice){ gitEmail = choice })
  1090. }
  1091. )
  1092. return any(steps).then(function(){
  1093. // Save values to add credentials later in index.js...
  1094. // console.log('module.exports = { instanceName : "'+ instanceName +'", reposerver: "'+reposerver+'", gitUser: "'+gitUser+'", gitEmail:"'+gitEmail+'" }')
  1095. fs.writeFileSync( 'installchoices.js', 'module.exports = { instanceName : "'+ instanceName +'", reposerver: "'+reposerver+'", gitUser: "'+gitUser+'", gitEmail:"'+gitEmail+'" }' )
  1096. var steps = [
  1097. // ['git', ['config', '--global', '--add', 'user.name', gitUser]]
  1098. // , ['git', ['config', '--global', '--add', 'user.email', gitEmail]]
  1099. ]
  1100. if(!steps.map) steps.map = map;
  1101. return any(steps.map(callsheltask)).then(function(){
  1102. })
  1103. });
  1104. }
  1105. var prerequisites = [
  1106. {
  1107. shellcmd: 'git',
  1108. url: 'https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe'
  1109. , installer: 'Git-2.33.0.2-64-bit.exe'
  1110. , installcmd: ['cmd', ['/c', 'start',
  1111. '/WAIT', downloadsdir + '/' + 'Git-2.33.0.2-64-bit.exe'
  1112. , '/VERYSILENT'
  1113. // , '/MERGETASKS=!runcode' // This is required only for vscode...
  1114. ]]
  1115. , preinstallsteps: function() {
  1116. var self = this;
  1117. console.log('Git preinstall steps')
  1118. var steps = [];
  1119. // steps.push(
  1120. // function(){
  1121. // // console.log('cli prompt steps')
  1122. // var choices = { 0 : 'guest', 1 : 'chessdemo' }
  1123. // return cli.prompt(choices, 'git user name', gitUser).then(function(choice){ gitUser = choice } )
  1124. // }
  1125. // )
  1126. // steps.push(
  1127. // function(){
  1128. // var choices = { 0 : 'guest@bbh.org.in', 1 : 'chessdemo@bbh.org.in' }
  1129. // return cli.prompt(choices, 'git user email', gitEmail).then(function(choice){ gitEmail = choice })
  1130. // }
  1131. // )
  1132. steps.push(
  1133. function(){
  1134. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1135. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', [self.url, downloadsdir + '/' + self.installer])
  1136. }
  1137. else {
  1138. console.log(self.installer + ' Already exits Download skipped.')
  1139. return Promise.resolve(true)
  1140. }
  1141. }
  1142. )
  1143. return any(steps)
  1144. // return any([any(steps), any(prompts)])
  1145. }
  1146. , installsteps: function () {
  1147. var self = this;
  1148. console.log('Git Installsteps called')
  1149. var ifns = [self.installcmd]
  1150. if(!ifns.map) ifns.map = map;
  1151. return any(ifns.map(callsheltask))['catch'](function(e){
  1152. if(e.code === 1602) {
  1153. console.warn("Installation was probably cancelled.")
  1154. }
  1155. else throw e
  1156. })
  1157. }
  1158. , postinstallsteps: gitpostinstallsteps
  1159. , install: function () {
  1160. gitPreinstalled = false;
  1161. var self = this;
  1162. console.log('Git Install called')
  1163. return any([ /*self.preinstallsteps,*/
  1164. function(){ return self.installsteps() }
  1165. , function() { return resetgitconfig() }
  1166. , function(){ return self.postinstallsteps() }
  1167. ])
  1168. }
  1169. // , verifyAndInstall : function(){
  1170. // var self = this;
  1171. // return self.exists().then( function(exits) {
  1172. // if(exists) return self.getUser(null, function(){ return self.postinstallsteps() } )
  1173. // else return self.install();
  1174. // })
  1175. // }
  1176. , exists : exists
  1177. , getUser : function(repo, onNoResult){
  1178. onNoResult = onNoResult || function(){return false}
  1179. var globalOrLocal = '--global';
  1180. if(!repo) globalOrLocal = '--global';
  1181. else globalOrLocal = '--local'
  1182. var fns = [['git', ['config', globalOrLocal, '--get-all', 'user.name']]]
  1183. if(!ifns.map) ifns.map = map;
  1184. return any(fns.map(callsheltask)).then(function(result){
  1185. // not yet configured.
  1186. if(!result.success) return onNoResult()
  1187. else {
  1188. var users = result.messages[0].trim().split('\n');
  1189. if(users.length === 0 ||
  1190. users.length === 1 && users[0] === 'guest') {
  1191. return onNoResult()
  1192. }
  1193. else return users[0]; // PB : TODO == We should probably prompt with all the users available for selection !
  1194. }
  1195. })
  1196. ['catch'](function(e){
  1197. console.log(e)
  1198. return onNoResult()
  1199. })
  1200. }
  1201. }
  1202. ,
  1203. {
  1204. shellcmd: 'node',
  1205. url: 'https://nodejs.org/dist/v14.17.6/node-v14.17.6-x64.msi'
  1206. , installer: 'node-v14.17.3-x64.msi'
  1207. , installcmd: ['MSIEXEC.exe', ['/i'
  1208. , path.normalize(downloadsdir + '/' + 'node-v14.17.3-x64.msi')
  1209. , 'ACCEPT=YES', '/passive']]
  1210. , install : install
  1211. , exists : exists
  1212. , preinstallsteps: function() {
  1213. var self = this;
  1214. console.log('Node preinstall steps')
  1215. // console.log(this.installcmd)
  1216. // console.log(path.normalize(downloadsdir + '/' + 'node-v14.17.3-x64.msi'))
  1217. var steps = [];
  1218. steps.push(
  1219. function(){
  1220. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1221. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', ['"' + self.url + '"', downloadsdir + '/' + self.installer]
  1222. , { waitmsg : 'downloading '+ self.shellcmd +' please wait' })
  1223. }
  1224. else {
  1225. console.log(self.installer + ' Already exits Download skipped.')
  1226. return Promise.resolve(true)
  1227. }
  1228. }
  1229. )
  1230. return any(steps)
  1231. // return any([any(steps), any(prompts)])
  1232. }
  1233. }
  1234. , {
  1235. shellcmd: 'python'
  1236. , optional : true
  1237. , url: 'https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi'
  1238. , installer: 'python-2.7.18.amd64.msi'
  1239. , installcmd: ['MSIEXEC.exe', ['/i'
  1240. , path.normalize(downloadsdir + '/' + 'python-2.7.18.amd64.msi')
  1241. , 'ACCEPT=YES', '/passive']]
  1242. , preinstallsteps: function() {
  1243. var self = this;
  1244. console.log(self.shellcmd + ' preinstall steps')
  1245. var steps = [];
  1246. steps.push(
  1247. function(){
  1248. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1249. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', [self.url, downloadsdir + '/' + self.installer]
  1250. , { waitmsg : 'downloading '+ self.shellcmd +' please wait' })
  1251. }
  1252. else {
  1253. console.log(self.installer + ' Already exits Download skipped.')
  1254. return Promise.resolve(true)
  1255. }
  1256. }
  1257. )
  1258. return any(steps)
  1259. // return any([any(steps), any(prompts)])
  1260. }
  1261. , install : install
  1262. , postinstallsteps : function() { return sysAddPathVar('%USERPROFILE%\\AppData/Local\\Microsoft\\WindowsApps') }
  1263. , exists : exists
  1264. }
  1265. , {
  1266. shellcmd: 'code'
  1267. , optional : true
  1268. , url: 'https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user'
  1269. , installer: 'VSCodeUserSetup-x64-1.65.2.exe'
  1270. , installcmd: ['cmd /c', ['start /WAIT ' + downloadsdir + '/' + 'VSCodeUserSetup-x64-1.65.2.exe /VERYSILENT'
  1271. // , '/MERGETASKS=!runcode' // This is required only for vscode...
  1272. ]]
  1273. , preinstallsteps: function() {
  1274. var self = this;
  1275. console.log(self.shellcmd + ' preinstall steps')
  1276. var steps = [];
  1277. steps.push(
  1278. function(){
  1279. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1280. console.log(self.url)
  1281. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', ['"' + self.url + '"', downloadsdir + '/' + self.installer]
  1282. , { waitmsg : 'downloading '+ self.shellcmd +' please wait' })
  1283. }
  1284. else {
  1285. console.log(self.installer + ' Already exits Download skipped.')
  1286. return Promise.resolve(true)
  1287. }
  1288. }
  1289. )
  1290. return any(steps)
  1291. // return any([any(steps), any(prompts)])
  1292. }
  1293. , install : install
  1294. , postinstallsteps : function() { return sysAddPathVar('%USERPROFILE%\\AppData/Local\\Microsoft\\WindowsApps') }
  1295. , exists : exists
  1296. }
  1297. , {
  1298. // C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Ssms.exe
  1299. // SQL Management studio 2018
  1300. shellcmd: 'sqlcmd.exe', // 'Ssms.exe',
  1301. url: 'https://aka.ms/ssmsfullsetup'
  1302. , installer: 'SSMS-Setup-ENU.exe'
  1303. , installcmd: ['cmd', ['/c', 'start',
  1304. '/WAIT', downloadsdir + '/' + 'SSMS-Setup-ENU.exe'
  1305. , '/IAcceptSQLServerLicenseTerms'
  1306. //, 'SSMSInstallRoot=%systemdrive%\\Program Files (x86)\\Microsoft SQL Server\\140\\Tools\\Binn\\ManagementStudio'
  1307. ]]
  1308. , install : install
  1309. , exists : exists
  1310. , preinstallsteps: function() {
  1311. var self = this;
  1312. console.log('smss 2018 preinstall steps')
  1313. var steps = [];
  1314. steps.push(
  1315. function(){
  1316. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1317. console.log(self.url)
  1318. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', ['"' + self.url + '"', downloadsdir + '/' + self.installer]
  1319. , { waitmsg : 'downloading '+ self.shellcmd +' please wait' })
  1320. }
  1321. else {
  1322. console.log(self.installer + ' Already exits Download skipped.')
  1323. return Promise.resolve(true)
  1324. }
  1325. }
  1326. )
  1327. return any(steps)
  1328. // return any([any(steps), any(prompts)])
  1329. }
  1330. }
  1331. , {
  1332. shellcmd: 'sqlservr.exe',
  1333. url: 'https://go.microsoft.com/fwlink/?linkid=866658'
  1334. , installer: 'SQL2019-SSEI-Expr.exe'
  1335. , installcmd: ['cmd', ['/c', 'start',
  1336. '/WAIT', downloadsdir + '/' + 'SQL2019-SSEI-Expr.exe'
  1337. , ''
  1338. //, 'SSMSInstallRoot=%systemdrive%\\Program Files (x86)\\Microsoft SQL Server\\140\\Tools\\Binn\\ManagementStudio'
  1339. ]]
  1340. , install : install
  1341. , exists : function(){
  1342. var self = this;
  1343. var installedpath = 'C:\\Program Files\\Microsoft SQL Server\\MSSQL15.SQLEXPRESS\\MSSQL\\Binn\\sqlservr.exe'
  1344. console.log('checking existence of ' + installedpath)
  1345. return Promise.resolve(existsSync(installedpath))
  1346. }
  1347. , preinstallsteps: function() {
  1348. var self = this;
  1349. console.log('sqlexpress preinstall steps')
  1350. var steps = [];
  1351. steps.push(
  1352. function(){
  1353. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1354. console.log(self.url)
  1355. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', ['"' + self.url + '"', downloadsdir + '/' + self.installer]
  1356. , { waitmsg : 'downloading '+ self.shellcmd +' please wait' })
  1357. }
  1358. else {
  1359. console.log(self.installer + ' Already exits Download skipped.')
  1360. return Promise.resolve(true)
  1361. }
  1362. }
  1363. )
  1364. return any(steps)
  1365. // return any([any(steps), any(prompts)])
  1366. }
  1367. }
  1368. , {
  1369. shellcmd: 'mysql',
  1370. url: 'https://dev.mysql.com/get/Downloads/MySQLInstaller/mysql-installer-community-8.0.30.0.msi' //'https://dev.mysql.com/get/Downloads/MySQLInstaller/mysql-installer-community-8.0.29.0.msi'
  1371. , installer: 'mysql-installer-community-8.0.30.0.msi'
  1372. , installcmd: ['MSIEXEC.exe', ['/i'
  1373. , path.normalize(downloadsdir + '/' + 'mysql-installer-community-8.0.30.0.msi')
  1374. //, 'ACCEPT=YES', '/passive'
  1375. ]]
  1376. , install : install
  1377. , exists : function(){
  1378. var self = this;
  1379. var mysqldpath = 'C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin\\mysqld.exe'
  1380. console.log('checking existence of ' + mysqldpath)
  1381. return Promise.resolve(existsSync(mysqldpath))
  1382. }
  1383. , preinstallsteps: function() {
  1384. var self = this;
  1385. console.log('mysql preinstall steps')
  1386. var steps = [];
  1387. steps.push(
  1388. function(){
  1389. if (!existsSync(downloadsdir + '/' + self.installer)) {
  1390. console.log(self.url)
  1391. return nodeShellExec(selectedinstance.root + '/.elxr/run-' + runtimestamp + '/download.bat', [self.url, downloadsdir + '/' + self.installer]
  1392. , { waitmsg : 'downloading '+ self.shellcmd +' please wait' })
  1393. }
  1394. else {
  1395. console.log(self.installer + ' Already exits Download skipped.')
  1396. return Promise.resolve(true)
  1397. }
  1398. }
  1399. )
  1400. return any(steps)
  1401. // return any([any(steps), any(prompts)])
  1402. }
  1403. }
  1404. ,
  1405. {
  1406. shellcmd: 'elxr'
  1407. , forceinstall : true
  1408. , installcmd: [ isWin() ? 'npm.cmd' : 'npm' , ['link'], { cwd : selectedinstance.root + '\\elxr' /* cwd should be the cloned dir*/}]
  1409. , preinstallsteps: function() {
  1410. var self = this;
  1411. console.log('Elxr preinstall steps')
  1412. var steps = [];
  1413. steps.push(
  1414. )
  1415. return any([any(steps)])
  1416. }
  1417. , installsteps: function () {
  1418. var self = this;
  1419. console.log('GIt config reconfirm called ' + gitPreinstalled)
  1420. var installIfNotExists = function(){
  1421. var steps = [];
  1422. if(gitPreinstalled) {
  1423. console.log('-------------------------------------')
  1424. console.log('Git was already preinstalled - reconfirming installchoices')
  1425. // Load from previous run and confirm.
  1426. // var reposerver = 'https://git.bbh.org.in';
  1427. // var gitUser = 'guest';
  1428. // var gitEmail = 'guest@bbh.org.in';
  1429. try {
  1430. var icf = fs.readFileSync( 'installchoices.js')
  1431. icf = icf.replace('module.exports = ', 'icf = ')
  1432. console.log(icf)
  1433. icf = eval(icf)
  1434. // console.log(icf.reposerver)
  1435. instanceName = icf.instanceName
  1436. reposerver = icf.reposerver;
  1437. gitUser = icf.gitUser;
  1438. gitEmail = icf.gitEmail
  1439. }
  1440. catch(e) {
  1441. console.error(e)
  1442. }
  1443. console.log('-------------------------------------')
  1444. console.dir(icf)
  1445. // var p = gitpostinstallsteps()
  1446. steps.push(gitpostinstallsteps)
  1447. // steps.push(
  1448. // function(){
  1449. // console.log('cli prompt steps')
  1450. // var choices = { 0 : 'http://git.bbh', 1 : 'https://git.bbh.org.in' }
  1451. // // console.dir(choices)
  1452. // return cli.prompt(choices, 'git repository : ', reposerver).then(function(choice){ reposerver = choice } )
  1453. // }
  1454. // )
  1455. }
  1456. else{
  1457. // var p = Promise.resolve(true)
  1458. steps.push(
  1459. function(){
  1460. var choices = { }
  1461. return cli.prompt(choices, 'git password', gitpassword).then(function(choice){ gitpassword = choice } )
  1462. }
  1463. )
  1464. }
  1465. // resetgitconfig requires the password to be loaded from credential store. Currently just prompt for it.
  1466. return any(steps).then( function(){
  1467. console.log('calling resetgitconfig')
  1468. return resetgitconfig().then(function(){
  1469. console.log('cloning elxr now')
  1470. var ifns = [
  1471. ['git', ['clone', reposerver + '/chess/elxr'] ]
  1472. ]
  1473. if(existsSyncFolder( selectedinstance.root + '\\elxr')) {
  1474. if(existsSyncFolder( selectedinstance.root + '\\elxr\\.git')) {
  1475. // PB : TODO -- use a elxr guid signature to detect more reliably folders named the same that is not us.
  1476. ifns = [ ['git', ['pull'], { cwd : selectedinstance.root + '\\elxr' } ] ]
  1477. }
  1478. else {
  1479. throw 'elxr subfolder not recognized as a git repository. Please cleanup and continue.'
  1480. }
  1481. }
  1482. else console.log(selectedinstance.root + '\\elxr' + ' NOT FOUND ')
  1483. if(!ifns.map) ifns.map = map;
  1484. return any(ifns.map(callsheltask)).then(function(){
  1485. var pkgjson = selectedinstance.root + '\\elxr\\package.json'
  1486. var pkgcontents = fs.readFileSync(pkgjson)
  1487. // PB : TODO -- Remove hardcode use proper replacement url..
  1488. fs.writeFileSync( pkgjson, pkgcontents.replace(/http\:\/\/git\.bbh/g, reposerver));
  1489. return callsheltask(['npm', ['i'], { cwd : '.\\elxr' } ])
  1490. })['catch'](function(e){
  1491. if(e.code === 1602) {
  1492. console.warn("Installation was probably cancelled.")
  1493. }
  1494. else throw e
  1495. })
  1496. })
  1497. } )
  1498. }
  1499. var ifns = [ self.installcmd ]
  1500. if(!ifns.map) ifns.map = map;
  1501. return installIfNotExists().then(function(){
  1502. return any(ifns.map(callsheltask))['catch'](function(e){
  1503. if(e.code === 1602) {
  1504. console.warn("Installation was probably cancelled.")
  1505. }
  1506. else throw e
  1507. })
  1508. })
  1509. }
  1510. , install: function () {
  1511. var self = this;
  1512. console.log('Elxr Install called')
  1513. // PB : TODO -- detect external or internal and change elxr package.json dependencies to point to proper location.
  1514. fs.writeFileSync(selectedinstance.root + '\\ei.bat', 'cmd /c node ' + selectedinstance.root + '\\elxr\\index.js i ' + instanceName)
  1515. return any([ self.preinstallsteps, function(){ return self.installsteps() }
  1516. , nodeShellExec('start', ['/WAIT', '""', '"' + selectedinstance.root + '\\ei.bat' + '"'])
  1517. // , nodeShellExec('start', ['/WAIT', '""', '"C:\\Program Files\\Git\\bin\\sh.exe"', '-c', '"node ' + (selectedinstance.root + '\\elxr\\index.js').replace(/\\/g, '/') + ' i elixir"'])
  1518. // , nodeShellExec('node', [selectedinstance.root + 'elxr\\index.js'])
  1519. ])
  1520. // return any([ /*self.preinstallsteps,*/ function(){ return self.installsteps() }
  1521. // , nodeShellExec('node', [selectedinstance.root + '\\elxr\\index.js', 'init'])
  1522. // // , nodeShellExec('node', [selectedinstance.root + 'elxr\\index.js'])
  1523. // ])
  1524. }
  1525. // , exists : function(){
  1526. // console.log('Elxr PreInstallsteps called')
  1527. // var ifns = [ ['git', ['clone', 'http://git.bbh/chess\\elxr'] ] ]
  1528. // if(existsSyncFolder( selectedinstance.root + '\\elxr')) {
  1529. // if(existsSyncFolder( selectedinstance.root + '\\elxr\\.git')) {
  1530. // // PB : TODO -- use a elxr guid signature to detect more reliably folders named the same that is not us.
  1531. // ifns = [ ['git', ['pull'], { cwd : selectedinstance.root + '\\elxr' } ] ]
  1532. // }
  1533. // else {
  1534. // throw 'elxr subfolder not recognized as a git repository. Please cleanup and continue.'
  1535. // }
  1536. // }
  1537. // else console.log(selectedinstance.root + '\\elxr' + ' NOT FOUND ')
  1538. // if(!ifns.map) ifns.map = map;
  1539. // return any(ifns.map(callsheltask))['catch'](function(e){
  1540. // if(e.code === 1602) {
  1541. // console.warn("Installation was probably cancelled.")
  1542. // }
  1543. // else throw e
  1544. // })
  1545. // }
  1546. , exists : exists
  1547. }
  1548. ]
  1549. if(!prerequisites.forEach) prerequisites.forEach = forEach;
  1550. // nodeShellExec(selectedinstance.root + '/.elxr/run-' + '1629889572461' + '/download.bat'
  1551. // , ['https://github.com/git-for-windows/git/releases/download/v2.31.0.windows.1/Git-2.32.0.2-64-bit.exe'
  1552. // , downloadsdir + '/' + 'Git-2.32.0.2-64-bit.exe']).start()
  1553. promises.push(verifyAndInstallPrerequisites())
  1554. startPromises();
  1555. }