Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

854 lines
24 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: autostart.js
  7. //
  8. // Contents: A script which will connect to a Build Manager machine and
  9. // start a build. This can be used to start builds automatically
  10. // with the task scheduler or by scripts.
  11. //
  12. //----------------------------------------------------------------------------
  13. var RemoteObj = null;
  14. var DEFAULT_IDENTITY_BM = "BuildManager";
  15. var DEFAULT_IDENTITY_BUILDER = "Build";
  16. var strBldMgr;
  17. var strBldMgrIdentity = DEFAULT_IDENTITY_BM;
  18. var strConfigURL = null;
  19. var strEnviroURL = null;
  20. var strConfigXML;
  21. var strEnviroXML;
  22. var strTimeStamp;
  23. var fForceRestart = false;
  24. var fCreateMachines = false;
  25. var fUpdateBinaries = false;
  26. var fSetTimeStamp = false;
  27. var fTryAgain = true;
  28. var aMachines = new Array();
  29. // Capture variables
  30. var fCaptureLogsFromMachine;
  31. var fCaptureLogs;
  32. var strCaptureLogDir;
  33. var strCaptureLogMan;
  34. var strCaptureLogManIdentity;
  35. var g_FSObj;
  36. var vRet = 0;
  37. //
  38. // First, parse command line arguments
  39. //
  40. Error.prototype.toString = Error_ToString;
  41. ParseArguments(WScript.Arguments);
  42. if (fUpdateBinaries)
  43. {
  44. vRet = DoBinariesUpdate();
  45. }
  46. else if (fCaptureLogs)
  47. {
  48. g_FSObj = new ActiveXObject("Scripting.FileSystemObject"); // Parse input Parameter List
  49. if (fCaptureLogsFromMachine)
  50. vRet = CaptureLogsManager(strCaptureLogDir, strCaptureLogMan, strCaptureLogManIdentity);
  51. else
  52. vRet = CaptureLogsEnviro(strCaptureLogDir);
  53. }
  54. else
  55. {
  56. vRet = AutoStart();
  57. }
  58. WScript.Quit(vRet);
  59. function ParseArguments(Arguments)
  60. {
  61. var strArg;
  62. var chArg0;
  63. var chArg1;
  64. var argn;
  65. for(argn = 0; argn < Arguments.length; argn++)
  66. {
  67. strArg = Arguments(argn);
  68. chArg0 = strArg.charAt(0);
  69. chArg1 = strArg.toLowerCase().slice(1);
  70. if (chArg0 != '-' && chArg0 != '/')
  71. {
  72. if (!strConfigURL)
  73. strConfigURL = Arguments(argn);
  74. else if (!strEnviroURL )
  75. strEnviroURL = Arguments(argn);
  76. else
  77. Usage(1);
  78. }
  79. else
  80. {
  81. switch(chArg1)
  82. {
  83. case 'f':
  84. fForceRestart = true;
  85. break;
  86. case 'u':
  87. fUpdateBinaries = true;
  88. fCreateMachines = true;
  89. break;
  90. case 't':
  91. fSetTimeStamp = true;
  92. argn++;
  93. if (argn < Arguments.length)
  94. strTimeStamp = Arguments(argn);
  95. else
  96. Usage(1);
  97. break;
  98. case 'log':
  99. fCaptureLogs = true;
  100. argn++;
  101. if (argn < Arguments.length)
  102. strCaptureLogDir = Arguments(argn);
  103. else
  104. Usage(2);
  105. fCreateMachines = true;
  106. break;
  107. case 'logman':
  108. fCaptureLogsFromMachine = true;
  109. argn++;
  110. if (argn < Arguments.length)
  111. strCaptureLogMan = Arguments(argn);
  112. else
  113. Usage(3);
  114. argn++;
  115. if (argn < Arguments.length)
  116. strCaptureLogManIdentity = Arguments(argn);
  117. else
  118. Usage(4);
  119. break;
  120. default:
  121. Usage(5);
  122. break;
  123. }
  124. }
  125. }
  126. // Insist that the config and enviro templates are supplied.
  127. if (!fCaptureLogsFromMachine && (!strConfigURL || !strEnviroURL))
  128. {
  129. if (!fCaptureLogs)
  130. {
  131. WScript.Echo('!fCaptureLogsFromMachine' + !fCaptureLogsFromMachine);
  132. WScript.Echo('!strConfigURL' + !strConfigURL);
  133. WScript.Echo('!strEnviroURL' + !strEnviroURL);
  134. Usage(6);
  135. }
  136. }
  137. if (fCaptureLogsFromMachine && !fCaptureLogs)
  138. Usage(7);
  139. }
  140. function AutoStart()
  141. {
  142. try
  143. {
  144. var ret;
  145. var err = new Error();
  146. var PublicData;
  147. LoadEnvironmentTemplate();
  148. LoadConfigTemplate();
  149. try
  150. {
  151. var objOD = new ActiveXObject('MTScript.ObjectDaemon', strBldMgr)
  152. RemoteObj = objOD.OpenInterface(strBldMgrIdentity, 'MTScript.Remote', true);
  153. }
  154. catch(ex)
  155. {
  156. if (strBldMgr && strBldMgr.length > 0)
  157. err.description = 'Sorry. Could not connect to machine "' + strBldMgr + '\\' + strBldMgrIdentity + '"';
  158. else
  159. err.description = 'Sorry. Could not connect to the local machine.';
  160. err.description += '\n\tVerify that the machine is available and that mtscript.exe\n\tis running on the machine.';
  161. err.details = ex.description;
  162. throw(err);
  163. }
  164. PublicData = RemoteObj.Exec('getpublic', 'root');
  165. PublicData = eval(PublicData);
  166. CommonVersionCheck("$DROPVERSION: V(2463.0 ) F(autostart.js )$", PublicData);
  167. // Check the current mode of the machine. If it's idle, then switch it
  168. // into master or standalone mode and get it going.
  169. if (PublicData.strMode != 'idle')
  170. {
  171. if (fForceRestart)
  172. {
  173. WScript.Echo('The machine is not idle. Forcing a restart...');
  174. ret = RemoteObj.Exec('setmode', 'idle');
  175. WScript.Sleep(5000);
  176. }
  177. else
  178. {
  179. WScript.Echo('The machine is not idle. Use -f to force a restart.');
  180. return 1;
  181. }
  182. }
  183. while (!StartBuild() && fTryAgain)
  184. {
  185. ret = RemoteObj.Exec('setmode', 'idle');
  186. WScript.Sleep(5000);
  187. fTryAgain = false;
  188. }
  189. WScript.Echo('Build started successfully.');
  190. }
  191. catch(ex)
  192. {
  193. WScript.Echo('An error occurred starting the build:');
  194. WScript.Echo('\t' + ex);
  195. WScript.Echo('');
  196. return 1;
  197. }
  198. return 0;
  199. }
  200. function MachineInfo()
  201. {
  202. this.strName = '';
  203. this.strEnlistment = '';
  204. this.fPostBuild = false;
  205. }
  206. function StartBuild()
  207. {
  208. var ret = 'ok';
  209. var err = new Error();
  210. if (fSetTimeStamp)
  211. {
  212. ret = RemoteObj.Exec('setstringmap', "%today%=" + strTimeStamp);
  213. }
  214. if (ret == 'ok')
  215. {
  216. ret = RemoteObj.Exec('setconfig', strConfigXML);
  217. if (ret == 'ok')
  218. {
  219. ret = RemoteObj.Exec('setenv', strEnviroXML);
  220. if (ret == 'ok')
  221. {
  222. ret = RemoteObj.Exec('setmode', 'master');
  223. if (ret == 'ok')
  224. {
  225. ret = RemoteObj.Exec('start', '');
  226. }
  227. }
  228. else
  229. err.description = 'An error occurred loading the environment template';
  230. }
  231. else if (ret == 'alreadyset')
  232. {
  233. // The machine is busy. Reset it if necessary.
  234. return false;
  235. }
  236. else
  237. err.description = 'An error occurred loading the build template';
  238. }
  239. else
  240. err.description = 'An error occurred setting the timestamp.';
  241. if (ret != 'ok')
  242. {
  243. if (!err.description)
  244. err.description = 'A failure occurred communicating with the machine.';
  245. err.details = ret;
  246. throw(err);
  247. }
  248. return true;
  249. }
  250. function LoadEnvironmentTemplate()
  251. {
  252. var xml = new ActiveXObject('Microsoft.XMLDOM');
  253. var err = new Error();
  254. var node;
  255. fStandaloneMode = false;
  256. xml.async = false;
  257. // It's unlikely they have the schema file available for this template,
  258. // so we turn off schema validation right now. The script engine will
  259. // validate it when we start the build.
  260. xml.validateOnParse = false;
  261. xml.resolveExternals = false;
  262. if (!xml.load(strEnviroURL) || !xml.documentElement)
  263. {
  264. err.description = 'Error loading the environment template ' + strEnviroURL;
  265. err.details = xml.parseError.reason;
  266. throw(err);
  267. }
  268. node = xml.documentElement.selectSingleNode('BuildManager');
  269. if (!node)
  270. {
  271. err.description = 'Invalid environment template file (BuildManager tag missing): ' + strEnviroURL;
  272. throw(err);
  273. }
  274. strBldMgr = node.getAttribute("Name");
  275. strBldMgrIdentity = node.getAttribute("Identity");
  276. if (!strBldMgr)
  277. {
  278. err.description = 'Invalid environment template file (BuildManager tag badly formatted): ' + strEnviroURL;
  279. throw(err);
  280. }
  281. if (!strBldMgrIdentity)
  282. strBldMgrIdentity = DEFAULT_IDENTITY_BM;
  283. if (strBldMgr.toLowerCase() == '%localmachine%' ||
  284. strBldMgr.toLowerCase() == '%remotemachine%')
  285. {
  286. err.description = 'Sorry, cannot use the local machine or remote machine templates from this script';
  287. throw(err);
  288. }
  289. strEnviroXML = 'XML: ' + xml.xml;
  290. if (fCreateMachines)
  291. {
  292. var node;
  293. var strPostBuild;
  294. var nodelist;
  295. var objMach;
  296. // Build the list of machines so we can copy the binaries from each
  297. // one.
  298. strPostBuild = node.getAttribute("PostBuildMachine");
  299. nodelist = xml.documentElement.selectNodes('Machine');
  300. for (node = nodelist.nextNode();
  301. node;
  302. node = nodelist.nextNode())
  303. {
  304. objMach = new MachineInfo();
  305. objMach.strName = node.getAttribute("Name");
  306. objMach.strEnlistment = node.getAttribute("Enlistment");
  307. objMach.Identity = node.getAttribute("Identity");
  308. if (!objMach.Identity || objMach.Identity == '')
  309. objMach.Identity = DEFAULT_IDENTITY_BUILDER;
  310. if (objMach.strName.toLowerCase() == strPostBuild.toLowerCase())
  311. {
  312. objMach.fPostBuild = true;
  313. }
  314. aMachines[aMachines.length] = objMach;
  315. }
  316. }
  317. return true;
  318. }
  319. function LoadConfigTemplate()
  320. {
  321. var xml = new ActiveXObject('Microsoft.XMLDOM');
  322. var err = new Error();
  323. xml.async = false;
  324. // It's unlikely they have the schema file available for this template,
  325. // so we turn off schema validation right now. The script engine will
  326. // validate it when we start the build.
  327. xml.validateOnParse = false;
  328. xml.resolveExternals = false;
  329. if (!xml.load(strConfigURL) || !xml.documentElement)
  330. {
  331. err.description = 'Error loading the config template ' + strConfigURL;
  332. err.details = xml.parseError.reason;
  333. throw(err);
  334. }
  335. strConfigXML = 'XML: ' + xml.xml;
  336. return true;
  337. }
  338. function GetBinariesUNC(mach)
  339. {
  340. var strUNC;
  341. strUNC = '\\\\' + mach.strName + '\\';
  342. try
  343. {
  344. var objOD = new ActiveXObject('MTScript.ObjectDaemon', mach.strName)
  345. RemoteObj = objOD.OpenInterface(mach.Identity, 'MTScript.Remote', true);
  346. }
  347. catch(ex)
  348. {
  349. err.description = 'Sorry. Could not connect to machine "' + mach.strName + '"';
  350. err.description += '\n\tVerify that the machine is available and that mtscript.exe\n\tis running on the machine.';
  351. err.details = ex.description;
  352. throw(err);
  353. }
  354. try
  355. {
  356. strUNC += eval(RemoteObj.Exec('getpublic', 'PrivateData.aEnlistmentInfo[0].hEnvObj["_nttree"]'));
  357. }
  358. catch(ex)
  359. {
  360. err.description = 'Machine ' + mach.strName + '\\' + mach.Identity + ' is not in the correct state. ';
  361. err.description += 'The binaries location cannot be determined. (Was the machine reset?)';
  362. err.details = ex.description;
  363. throw(err);
  364. }
  365. strUNC = strUNC.replace(/\:/ig, '$');
  366. return strUNC;
  367. }
  368. function DoBinariesUpdate()
  369. {
  370. try
  371. {
  372. LoadEnvironmentTemplate();
  373. LoadConfigTemplate();
  374. // The postbuild machine must always be the first machine listed
  375. var i;
  376. for (i = 0; i < aMachines.length; i++)
  377. {
  378. if (aMachines[i].fPostBuild)
  379. {
  380. WScript.Echo(aMachines[i].strName + "\\" + aMachines[i].Identity + " " + GetBinariesUNC(aMachines[i]));
  381. }
  382. }
  383. for (i = 0; i < aMachines.length; i++)
  384. {
  385. if (!aMachines[i].fPostBuild)
  386. {
  387. WScript.Echo(aMachines[i].strName + "\\" + aMachines[i].Identity + " " + GetBinariesUNC(aMachines[i]));
  388. }
  389. }
  390. }
  391. catch(ex)
  392. {
  393. WScript.Echo('An error occurred during update binaries:');
  394. WScript.Echo('\t' + ex);
  395. WScript.Echo('');
  396. return 1;
  397. }
  398. return 0;
  399. }
  400. function Error_ToString()
  401. {
  402. var i;
  403. var str = 'Exception(';
  404. /*
  405. Only some error messages get filled in for "ex".
  406. Specifically the text for disk full never seems
  407. to get set by functions such as CreateTextFile().
  408. */
  409. if (this.number != null && this.description == "")
  410. {
  411. switch(this.number)
  412. {
  413. case -2147024784:
  414. this.description = "There is not enough space on the disk.";
  415. break;
  416. case -2147024894:
  417. this.description = "The system cannot find the file specified.";
  418. break;
  419. case -2147023585:
  420. this.description = "There are currently no logon servers available to service the logon request.";
  421. break;
  422. case -2147023170:
  423. this.description = "The remote procedure call failed.";
  424. break;
  425. case -2147024837:
  426. this.description = "An unexpected network error occurred";
  427. break;
  428. case -2147024890:
  429. this.description = "The handle is invalid.";
  430. break;
  431. default:
  432. this.description = "Error text not set for (" + this.number + ")";
  433. break;
  434. }
  435. }
  436. for(i in this)
  437. {
  438. str += i + ": " + this[i] + " ";
  439. }
  440. return str + ")";
  441. }
  442. // MyEval(expr)
  443. // evaluating uneval'ed objects creates a bunch of junk local variables.
  444. // by putting the eval call in a little subroutine, we avoid keeping those
  445. // locals around.
  446. function MyEval(expr)
  447. {
  448. try
  449. {
  450. return eval(expr);
  451. }
  452. catch(ex)
  453. {
  454. throw ex;
  455. }
  456. }
  457. // CopyFileNoThrow(strSrc, strDst)
  458. // Wrap the FSObj.CopyFile call to prevent it from
  459. // throwing its errors.
  460. function CopyFileNoThrow(strSrc, strDst)
  461. {
  462. try
  463. {
  464. g_FSObj.CopyFile(strSrc, strDst, true);
  465. }
  466. catch(ex)
  467. {
  468. WScript.Echo("Copy failed from " + strSrc + " to " + strDst + " " + ex);
  469. return ex;
  470. }
  471. return null;
  472. }
  473. // CreateFolderNoThrow(strSrc, strDst)
  474. // Wrap the FSObj.MakeFolder call to prevent it from
  475. // throwing its errors.
  476. function CreateFolderNoThrow(strName)
  477. {
  478. try
  479. {
  480. g_FSObj.CreateFolder(strName);
  481. }
  482. catch(ex)
  483. {
  484. return ex;
  485. }
  486. return null;
  487. }
  488. // DirScanNoThrow(strDir)
  489. // Wrap the FSObj.Directory scan functionality to prevent it from
  490. // throwing its errors.
  491. function DirScanNoThrow(strDir)
  492. {
  493. var aFiles = new Array();
  494. try
  495. {
  496. var folder;
  497. var fc;
  498. folder = g_FSObj.GetFolder(strDir);
  499. fc = new Enumerator(folder.files);
  500. for (; !fc.atEnd(); fc.moveNext())
  501. {
  502. aFiles[aFiles.length] = fc.item().Name; // fc.item() returns entire path, fc.item().Name is just the filename
  503. }
  504. }
  505. catch(ex)
  506. {
  507. aFiles.ex = ex;
  508. }
  509. return aFiles;
  510. }
  511. //
  512. // CopyDirectory
  513. // Do a non-recursive directory copy.
  514. //
  515. function CopyDirectory(strSrcDir, strDestDir)
  516. {
  517. var ret = true;
  518. var ex;
  519. var aFiles;
  520. var strFileName = '';
  521. var i;
  522. WScript.Echo("Copy from " + strSrcDir + " to " + strDestDir);
  523. aFiles = DirScanNoThrow(strSrcDir);
  524. if (aFiles.ex)
  525. {
  526. WScript.Echo('Could not dirscan ' + strSrcDir + ', ex=' + ex);
  527. return false;
  528. }
  529. else
  530. {
  531. for(i = 0; i < aFiles.length; ++i)
  532. {
  533. strFileName = aFiles[i];
  534. ex = CopyFileNoThrow(
  535. strSrcDir + '\\' + strFileName,
  536. strDestDir + '\\' + strFileName);
  537. if (ex)
  538. {
  539. WScript.Echo("\t FAILED: " + strFileName);
  540. ret = false;
  541. }
  542. else
  543. WScript.Echo("\t COPIED: " + strFileName);
  544. }
  545. }
  546. return ret;
  547. }
  548. //
  549. // CopyMTScriptLog()
  550. // Copy the highest numbers "mtscript" log file
  551. // from the specified machine.
  552. //
  553. function CopyMTScriptLog(strMachineName, strIdentity, strDestDir)
  554. {
  555. var nLargestIndex = 0;
  556. var aReResult;
  557. var re = new RegExp('^' + strMachineName + '_' + strIdentity + '_MTS.([0-9]+).log$', 'i'); // match files "BUILDCON2_MTScript.051.log"
  558. var ex;
  559. var aFiles;
  560. var strFileName = '';
  561. var i;
  562. var strSrcDir = '\\\\' + strMachineName + "\\bc_build_logs";
  563. aFiles = DirScanNoThrow(strSrcDir);
  564. if (aFiles.ex)
  565. WScript.Echo('Could not dirscan ' + strSrcDir + ', ex=' + ex );
  566. else
  567. {
  568. for(i = 0; i < aFiles.length; ++i)
  569. {
  570. aReResult = re.exec(aFiles[i]);
  571. if (aReResult && Number(aReResult[1]) > nLargestIndex)
  572. {
  573. nLargestIndex = Number(aReResult[1]);
  574. strFileName = aFiles[i];
  575. }
  576. }
  577. if (strFileName == '')
  578. WScript.Echo("No MTSCRIPT log files on " + strMachineName);
  579. else
  580. {
  581. WScript.Echo("Copy from " + strSrcDir + '\\' + strFileName + " to " + strDestDir + '\\' + g_FSObj.GetFilename(strFileName));
  582. ex = CopyFileNoThrow(strSrcDir + '\\' + strFileName, strDestDir + '\\' + g_FSObj.GetFilename(strFileName));
  583. if (ex)
  584. {
  585. WScript.Echo("Failed " + ex);
  586. return false;
  587. }
  588. }
  589. }
  590. return true;
  591. }
  592. //
  593. // CopyLogFiles()
  594. // Copy the build log files from the given machines.
  595. //
  596. function CopyLogFiles(strDestDir, strBuildManagerName, strBuildManagerIdentity, aMachines)
  597. {
  598. var i;
  599. var strDest;
  600. CreateFolderNoThrow(strDestDir);
  601. CopyMTScriptLog(strBuildManagerName, strBuildManagerIdentity, strDestDir);
  602. for( i = 0; i < aMachines.length; ++i)
  603. {
  604. CopyMTScriptLog(aMachines[i].strName, aMachines[i].Identity, strDestDir);
  605. }
  606. /*
  607. Note: The following code tries to guess the filenames of the build log files.
  608. The "real" information can be had from the PublicData of the build manager.
  609. PublicData.aBuild[0].aDepot[ x ].aTask[ y ].strLogPath
  610. PublicData.aBuild[0].aDepot[ x ].aTask[ y ].strErrLogPath
  611. Of course, that would require that the build manager is still alive and well.
  612. */
  613. for( i = 0; i < aMachines.length; ++i)
  614. {
  615. strDest = strDestDir + "\\" + aMachines[i].strName;
  616. CreateFolderNoThrow(strDest);
  617. strDest += '\\' + aMachines[i].Identity;
  618. CreateFolderNoThrow(strDest);
  619. CopyDirectory("\\\\" + aMachines[i].strName + "\\bc_build_logs\\build_logs\\" + aMachines[i].Identity,
  620. strDestDir + "\\" + aMachines[i].strName + '\\' + aMachines[i].Identity);
  621. }
  622. }
  623. //
  624. // CaptureLogsManager()
  625. // Connect to the given build manager
  626. // and query it for its list of build machines,
  627. // The copy the MTSCRIPT and build log files from
  628. // each of those machines.
  629. //
  630. function CaptureLogsManager(strLogDir, strMachineName, strIdentity)
  631. {
  632. var strMode;
  633. var obj;
  634. try
  635. {
  636. WScript.Echo("Attempting connection to " + strMachineName + "\\" + strIdentity);
  637. obj = new ActiveXObject('MTScript.Proxy');
  638. WScript.Echo("Now connecting");
  639. obj.ConnectToMTScript(strMachineName, strIdentity, false);
  640. strMode = obj.Exec('getpublic', 'PublicData.strMode');
  641. strMode = MyEval(strMode);
  642. if (strMode == 'idle')
  643. {
  644. WScript.Echo(strMachineName + "\\" + strIdentity + " is currently idle");
  645. return 1;
  646. }
  647. aMachines = obj.Exec('getpublic', 'PrivateData.objEnviron.Machine');
  648. aMachines = MyEval(aMachines);
  649. for( i = 0; i < aMachines.length; ++i)
  650. {
  651. aMachines[i].strName = aMachines[i].Name;
  652. if (!aMachines[i].Identity || aMachines[i].Identity == '')
  653. aMachines[i].Identity = DEFAULT_IDENTITY_BUILDER;
  654. }
  655. CopyLogFiles(strLogDir, strMachineName, strIdentity, aMachines);
  656. }
  657. catch(ex)
  658. {
  659. WScript.Echo("CaptureLogsManager '" + strMachineName + "\\" + strIdentity + "' failed, ex=" + ex);
  660. return 1;
  661. }
  662. return 0;
  663. }
  664. //
  665. // CaptureLogsEnviro()
  666. // Read the supplied environment template
  667. // and copy the MTSCRIPT and build logs
  668. // from each of the specifed build machines.
  669. //
  670. function CaptureLogsEnviro(strLogDir)
  671. {
  672. try
  673. {
  674. var ret;
  675. if (!strEnviroURL && strConfigURL)
  676. {
  677. strEnviroURL = strConfigURL;
  678. strConfigURL = null;
  679. }
  680. LoadEnvironmentTemplate();
  681. ret = CopyLogFiles(strLogDir, strBldMgr, strBldMgrIdentity, aMachines);
  682. }
  683. catch(ex)
  684. {
  685. WScript.Echo('An error occurred capturing log files:');
  686. WScript.Echo('\t ex=' + ex);
  687. WScript.Echo('');
  688. return 1;
  689. }
  690. return 0;
  691. }
  692. /*
  693. CommonVersionCheck(strLocalVersion, PublicData)
  694. Ensure that this script and the remote script are running the same version.
  695. A copy of this function exists in:
  696. autostart.js
  697. bldcon.hta
  698. utils.js
  699. */
  700. function CommonVersionCheck(strLocalVersion, PublicData)
  701. {
  702. var err = new Error();
  703. var reBuildNum = new RegExp("V\\(([#0-9. ]+)\\)");
  704. var aLocal = reBuildNum.exec(strLocalVersion);
  705. var aPublicBuildNum;
  706. if (!PublicData.strDataVersion)
  707. {
  708. err.description = "autostart version mismatch";
  709. err.details = "Build Manager does not have a version string";
  710. throw err;
  711. }
  712. aPublicBuildNum = reBuildNum.exec(PublicData.strDataVersion);
  713. if (!aLocal || !aPublicBuildNum)
  714. {
  715. err.description = "Invalid version format";
  716. err.details = "UI Version: " + strLocalVersion + ", Build Manager Version: " + PublicData.strDataVersion;
  717. throw err;
  718. }
  719. if (aLocal[1] != aPublicBuildNum[1])
  720. {
  721. err.description = "Version mismatch";
  722. err.details = "UI Version: " + strLocalVersion + ", Build Manager Version: " + PublicData.strDataVersion;
  723. throw err;
  724. }
  725. }
  726. function Usage(x)
  727. {
  728. WScript.Echo('');
  729. WScript.Echo('Usage: bcauto [-f] [-u] [-t] <config> <enviro>');
  730. WScript.Echo('');
  731. WScript.Echo(' -f : If the machine is busy, terminate the build and restart.');
  732. WScript.Echo(' -u : Update: Recombine all the binaries from each of the build');
  733. WScript.Echo(' machines after taking incremental fixes so that postbuild');
  734. WScript.Echo(' can be run again.');
  735. WScript.Echo(' -t <timestamp> : Use timestamp (e.g. 2001/12/15:12:00)');
  736. WScript.Echo(' -log dir : Capture log files to specified directory');
  737. WScript.Echo(' -logman machine identity : Query "machine" with "identity" for list of');
  738. WScript.Echo(' build machines instead of template files.');
  739. WScript.Echo(' ("machine" must be a build manager)');
  740. WScript.Echo(' config : URL or path for the build template.');
  741. WScript.Echo(' enviro : URL or path for the environment template.');
  742. WScript.Echo('');
  743. WScript.Quit(1);
  744. }