install-run.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED.
  2. //
  3. // This script is intended for usage in an automated build environment where a Node tool may not have
  4. // been preinstalled, or may have an unpredictable version. This script will automatically install the specified
  5. // version of the specified tool (if not already installed), and then pass a command-line to it.
  6. // An example usage would be:
  7. //
  8. // node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io
  9. //
  10. // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/
  11. //
  12. // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
  13. // See the @microsoft/rush package's LICENSE file for details.
  14. /******/ (() => { // webpackBootstrap
  15. /******/ "use strict";
  16. /******/ var __webpack_modules__ = ({
  17. /***/ 832286:
  18. /*!************************************************!*\
  19. !*** ./lib-esnext/utilities/npmrcUtilities.js ***!
  20. \************************************************/
  21. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  22. __webpack_require__.r(__webpack_exports__);
  23. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  24. /* harmony export */ isVariableSetInNpmrcFile: () => (/* binding */ isVariableSetInNpmrcFile),
  25. /* harmony export */ syncNpmrc: () => (/* binding */ syncNpmrc)
  26. /* harmony export */ });
  27. /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! fs */ 179896);
  28. /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__);
  29. /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! path */ 16928);
  30. /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__);
  31. // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
  32. // See LICENSE in the project root for license information.
  33. // IMPORTANT - do not use any non-built-in libraries in this file
  34. /**
  35. * This function reads the content for given .npmrc file path, and also trims
  36. * unusable lines from the .npmrc file.
  37. *
  38. * @returns
  39. * The text of the the .npmrc.
  40. */
  41. // create a global _combinedNpmrc for cache purpose
  42. const _combinedNpmrcMap = new Map();
  43. function _trimNpmrcFile(options) {
  44. const { sourceNpmrcPath, linesToPrepend, linesToAppend } = options;
  45. const combinedNpmrcFromCache = _combinedNpmrcMap.get(sourceNpmrcPath);
  46. if (combinedNpmrcFromCache !== undefined) {
  47. return combinedNpmrcFromCache;
  48. }
  49. let npmrcFileLines = [];
  50. if (linesToPrepend) {
  51. npmrcFileLines.push(...linesToPrepend);
  52. }
  53. if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) {
  54. npmrcFileLines.push(...fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(sourceNpmrcPath).toString().split('\n'));
  55. }
  56. if (linesToAppend) {
  57. npmrcFileLines.push(...linesToAppend);
  58. }
  59. npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim());
  60. const resultLines = [];
  61. // This finds environment variable tokens that look like "${VAR_NAME}"
  62. const expansionRegExp = /\$\{([^\}]+)\}/g;
  63. // Comment lines start with "#" or ";"
  64. const commentRegExp = /^\s*[#;]/;
  65. // Trim out lines that reference environment variables that aren't defined
  66. for (let line of npmrcFileLines) {
  67. let lineShouldBeTrimmed = false;
  68. //remove spaces before or after key and value
  69. line = line
  70. .split('=')
  71. .map((lineToTrim) => lineToTrim.trim())
  72. .join('=');
  73. // Ignore comment lines
  74. if (!commentRegExp.test(line)) {
  75. const environmentVariables = line.match(expansionRegExp);
  76. if (environmentVariables) {
  77. for (const token of environmentVariables) {
  78. // Remove the leading "${" and the trailing "}" from the token
  79. const environmentVariableName = token.substring(2, token.length - 1);
  80. // Is the environment variable defined?
  81. if (!process.env[environmentVariableName]) {
  82. // No, so trim this line
  83. lineShouldBeTrimmed = true;
  84. break;
  85. }
  86. }
  87. }
  88. }
  89. if (lineShouldBeTrimmed) {
  90. // Example output:
  91. // "; MISSING ENVIRONMENT VARIABLE: //my-registry.com/npm/:_authToken=${MY_AUTH_TOKEN}"
  92. resultLines.push('; MISSING ENVIRONMENT VARIABLE: ' + line);
  93. }
  94. else {
  95. resultLines.push(line);
  96. }
  97. }
  98. const combinedNpmrc = resultLines.join('\n');
  99. //save the cache
  100. _combinedNpmrcMap.set(sourceNpmrcPath, combinedNpmrc);
  101. return combinedNpmrc;
  102. }
  103. function _copyAndTrimNpmrcFile(options) {
  104. const { logger, sourceNpmrcPath, targetNpmrcPath, linesToPrepend, linesToAppend } = options;
  105. logger.info(`Transforming ${sourceNpmrcPath}`); // Verbose
  106. logger.info(` --> "${targetNpmrcPath}"`);
  107. const combinedNpmrc = _trimNpmrcFile({
  108. sourceNpmrcPath,
  109. linesToPrepend,
  110. linesToAppend
  111. });
  112. fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(targetNpmrcPath, combinedNpmrc);
  113. return combinedNpmrc;
  114. }
  115. function syncNpmrc(options) {
  116. const { sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish, logger = {
  117. // eslint-disable-next-line no-console
  118. info: console.log,
  119. // eslint-disable-next-line no-console
  120. error: console.error
  121. }, createIfMissing = false, linesToAppend, linesToPrepend } = options;
  122. const sourceNpmrcPath = path__WEBPACK_IMPORTED_MODULE_1__.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish');
  123. const targetNpmrcPath = path__WEBPACK_IMPORTED_MODULE_1__.join(targetNpmrcFolder, '.npmrc');
  124. try {
  125. if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath) || createIfMissing) {
  126. // Ensure the target folder exists
  127. if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(targetNpmrcFolder)) {
  128. fs__WEBPACK_IMPORTED_MODULE_0__.mkdirSync(targetNpmrcFolder, { recursive: true });
  129. }
  130. return _copyAndTrimNpmrcFile({
  131. sourceNpmrcPath,
  132. targetNpmrcPath,
  133. logger,
  134. linesToAppend,
  135. linesToPrepend
  136. });
  137. }
  138. else if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(targetNpmrcPath)) {
  139. // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target
  140. logger.info(`Deleting ${targetNpmrcPath}`); // Verbose
  141. fs__WEBPACK_IMPORTED_MODULE_0__.unlinkSync(targetNpmrcPath);
  142. }
  143. }
  144. catch (e) {
  145. throw new Error(`Error syncing .npmrc file: ${e}`);
  146. }
  147. }
  148. function isVariableSetInNpmrcFile(sourceNpmrcFolder, variableKey) {
  149. const sourceNpmrcPath = `${sourceNpmrcFolder}/.npmrc`;
  150. //if .npmrc file does not exist, return false directly
  151. if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) {
  152. return false;
  153. }
  154. const trimmedNpmrcFile = _trimNpmrcFile({ sourceNpmrcPath });
  155. const variableKeyRegExp = new RegExp(`^${variableKey}=`, 'm');
  156. return trimmedNpmrcFile.match(variableKeyRegExp) !== null;
  157. }
  158. //# sourceMappingURL=npmrcUtilities.js.map
  159. /***/ }),
  160. /***/ 535317:
  161. /*!********************************!*\
  162. !*** external "child_process" ***!
  163. \********************************/
  164. /***/ ((module) => {
  165. module.exports = require("child_process");
  166. /***/ }),
  167. /***/ 179896:
  168. /*!*********************!*\
  169. !*** external "fs" ***!
  170. \*********************/
  171. /***/ ((module) => {
  172. module.exports = require("fs");
  173. /***/ }),
  174. /***/ 370857:
  175. /*!*********************!*\
  176. !*** external "os" ***!
  177. \*********************/
  178. /***/ ((module) => {
  179. module.exports = require("os");
  180. /***/ }),
  181. /***/ 16928:
  182. /*!***********************!*\
  183. !*** external "path" ***!
  184. \***********************/
  185. /***/ ((module) => {
  186. module.exports = require("path");
  187. /***/ })
  188. /******/ });
  189. /************************************************************************/
  190. /******/ // The module cache
  191. /******/ var __webpack_module_cache__ = {};
  192. /******/
  193. /******/ // The require function
  194. /******/ function __webpack_require__(moduleId) {
  195. /******/ // Check if module is in cache
  196. /******/ var cachedModule = __webpack_module_cache__[moduleId];
  197. /******/ if (cachedModule !== undefined) {
  198. /******/ return cachedModule.exports;
  199. /******/ }
  200. /******/ // Create a new module (and put it into the cache)
  201. /******/ var module = __webpack_module_cache__[moduleId] = {
  202. /******/ // no module.id needed
  203. /******/ // no module.loaded needed
  204. /******/ exports: {}
  205. /******/ };
  206. /******/
  207. /******/ // Execute the module function
  208. /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
  209. /******/
  210. /******/ // Return the exports of the module
  211. /******/ return module.exports;
  212. /******/ }
  213. /******/
  214. /************************************************************************/
  215. /******/ /* webpack/runtime/compat get default export */
  216. /******/ (() => {
  217. /******/ // getDefaultExport function for compatibility with non-harmony modules
  218. /******/ __webpack_require__.n = (module) => {
  219. /******/ var getter = module && module.__esModule ?
  220. /******/ () => (module['default']) :
  221. /******/ () => (module);
  222. /******/ __webpack_require__.d(getter, { a: getter });
  223. /******/ return getter;
  224. /******/ };
  225. /******/ })();
  226. /******/
  227. /******/ /* webpack/runtime/define property getters */
  228. /******/ (() => {
  229. /******/ // define getter functions for harmony exports
  230. /******/ __webpack_require__.d = (exports, definition) => {
  231. /******/ for(var key in definition) {
  232. /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  233. /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  234. /******/ }
  235. /******/ }
  236. /******/ };
  237. /******/ })();
  238. /******/
  239. /******/ /* webpack/runtime/hasOwnProperty shorthand */
  240. /******/ (() => {
  241. /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  242. /******/ })();
  243. /******/
  244. /******/ /* webpack/runtime/make namespace object */
  245. /******/ (() => {
  246. /******/ // define __esModule on exports
  247. /******/ __webpack_require__.r = (exports) => {
  248. /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  249. /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  250. /******/ }
  251. /******/ Object.defineProperty(exports, '__esModule', { value: true });
  252. /******/ };
  253. /******/ })();
  254. /******/
  255. /************************************************************************/
  256. var __webpack_exports__ = {};
  257. // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
  258. (() => {
  259. /*!*******************************************!*\
  260. !*** ./lib-esnext/scripts/install-run.js ***!
  261. \*******************************************/
  262. __webpack_require__.r(__webpack_exports__);
  263. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  264. /* harmony export */ RUSH_JSON_FILENAME: () => (/* binding */ RUSH_JSON_FILENAME),
  265. /* harmony export */ findRushJsonFolder: () => (/* binding */ findRushJsonFolder),
  266. /* harmony export */ getNpmPath: () => (/* binding */ getNpmPath),
  267. /* harmony export */ installAndRun: () => (/* binding */ installAndRun),
  268. /* harmony export */ runWithErrorAndStatusCode: () => (/* binding */ runWithErrorAndStatusCode)
  269. /* harmony export */ });
  270. /* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! child_process */ 535317);
  271. /* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(child_process__WEBPACK_IMPORTED_MODULE_0__);
  272. /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 179896);
  273. /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__);
  274. /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! os */ 370857);
  275. /* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_2__);
  276. /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! path */ 16928);
  277. /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
  278. /* harmony import */ var _utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utilities/npmrcUtilities */ 832286);
  279. // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
  280. // See LICENSE in the project root for license information.
  281. /* eslint-disable no-console */
  282. const RUSH_JSON_FILENAME = 'rush.json';
  283. const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER';
  284. const INSTALL_RUN_LOCKFILE_PATH_VARIABLE = 'INSTALL_RUN_LOCKFILE_PATH';
  285. const INSTALLED_FLAG_FILENAME = 'installed.flag';
  286. const NODE_MODULES_FOLDER_NAME = 'node_modules';
  287. const PACKAGE_JSON_FILENAME = 'package.json';
  288. /**
  289. * Parse a package specifier (in the form of name\@version) into name and version parts.
  290. */
  291. function _parsePackageSpecifier(rawPackageSpecifier) {
  292. rawPackageSpecifier = (rawPackageSpecifier || '').trim();
  293. const separatorIndex = rawPackageSpecifier.lastIndexOf('@');
  294. let name;
  295. let version = undefined;
  296. if (separatorIndex === 0) {
  297. // The specifier starts with a scope and doesn't have a version specified
  298. name = rawPackageSpecifier;
  299. }
  300. else if (separatorIndex === -1) {
  301. // The specifier doesn't have a version
  302. name = rawPackageSpecifier;
  303. }
  304. else {
  305. name = rawPackageSpecifier.substring(0, separatorIndex);
  306. version = rawPackageSpecifier.substring(separatorIndex + 1);
  307. }
  308. if (!name) {
  309. throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`);
  310. }
  311. return { name, version };
  312. }
  313. let _npmPath = undefined;
  314. /**
  315. * Get the absolute path to the npm executable
  316. */
  317. function getNpmPath() {
  318. if (!_npmPath) {
  319. try {
  320. if (_isWindows()) {
  321. // We're on Windows
  322. const whereOutput = child_process__WEBPACK_IMPORTED_MODULE_0__.execSync('where npm', { stdio: [] }).toString();
  323. const lines = whereOutput.split(os__WEBPACK_IMPORTED_MODULE_2__.EOL).filter((line) => !!line);
  324. // take the last result, we are looking for a .cmd command
  325. // see https://github.com/microsoft/rushstack/issues/759
  326. _npmPath = lines[lines.length - 1];
  327. }
  328. else {
  329. // We aren't on Windows - assume we're on *NIX or Darwin
  330. _npmPath = child_process__WEBPACK_IMPORTED_MODULE_0__.execSync('command -v npm', { stdio: [] }).toString();
  331. }
  332. }
  333. catch (e) {
  334. throw new Error(`Unable to determine the path to the NPM tool: ${e}`);
  335. }
  336. _npmPath = _npmPath.trim();
  337. if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(_npmPath)) {
  338. throw new Error('The NPM executable does not exist');
  339. }
  340. }
  341. return _npmPath;
  342. }
  343. function _ensureFolder(folderPath) {
  344. if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(folderPath)) {
  345. const parentDir = path__WEBPACK_IMPORTED_MODULE_3__.dirname(folderPath);
  346. _ensureFolder(parentDir);
  347. fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync(folderPath);
  348. }
  349. }
  350. /**
  351. * Create missing directories under the specified base directory, and return the resolved directory.
  352. *
  353. * Does not support "." or ".." path segments.
  354. * Assumes the baseFolder exists.
  355. */
  356. function _ensureAndJoinPath(baseFolder, ...pathSegments) {
  357. let joinedPath = baseFolder;
  358. try {
  359. for (let pathSegment of pathSegments) {
  360. pathSegment = pathSegment.replace(/[\\\/]/g, '+');
  361. joinedPath = path__WEBPACK_IMPORTED_MODULE_3__.join(joinedPath, pathSegment);
  362. if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(joinedPath)) {
  363. fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync(joinedPath);
  364. }
  365. }
  366. }
  367. catch (e) {
  368. throw new Error(`Error building local installation folder (${path__WEBPACK_IMPORTED_MODULE_3__.join(baseFolder, ...pathSegments)}): ${e}`);
  369. }
  370. return joinedPath;
  371. }
  372. function _getRushTempFolder(rushCommonFolder) {
  373. const rushTempFolder = process.env[RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME];
  374. if (rushTempFolder !== undefined) {
  375. _ensureFolder(rushTempFolder);
  376. return rushTempFolder;
  377. }
  378. else {
  379. return _ensureAndJoinPath(rushCommonFolder, 'temp');
  380. }
  381. }
  382. /**
  383. * Compare version strings according to semantic versioning.
  384. * Returns a positive integer if "a" is a later version than "b",
  385. * a negative integer if "b" is later than "a",
  386. * and 0 otherwise.
  387. */
  388. function _compareVersionStrings(a, b) {
  389. const aParts = a.split(/[.-]/);
  390. const bParts = b.split(/[.-]/);
  391. const numberOfParts = Math.max(aParts.length, bParts.length);
  392. for (let i = 0; i < numberOfParts; i++) {
  393. if (aParts[i] !== bParts[i]) {
  394. return (Number(aParts[i]) || 0) - (Number(bParts[i]) || 0);
  395. }
  396. }
  397. return 0;
  398. }
  399. /**
  400. * Resolve a package specifier to a static version
  401. */
  402. function _resolvePackageVersion(logger, rushCommonFolder, { name, version }) {
  403. if (!version) {
  404. version = '*'; // If no version is specified, use the latest version
  405. }
  406. if (version.match(/^[a-zA-Z0-9\-\+\.]+$/)) {
  407. // If the version contains only characters that we recognize to be used in static version specifiers,
  408. // pass the version through
  409. return version;
  410. }
  411. else {
  412. // version resolves to
  413. try {
  414. const rushTempFolder = _getRushTempFolder(rushCommonFolder);
  415. const sourceNpmrcFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushCommonFolder, 'config', 'rush');
  416. (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)({
  417. sourceNpmrcFolder,
  418. targetNpmrcFolder: rushTempFolder,
  419. logger
  420. });
  421. const npmPath = getNpmPath();
  422. // This returns something that looks like:
  423. // ```
  424. // [
  425. // "3.0.0",
  426. // "3.0.1",
  427. // ...
  428. // "3.0.20"
  429. // ]
  430. // ```
  431. //
  432. // if multiple versions match the selector, or
  433. //
  434. // ```
  435. // "3.0.0"
  436. // ```
  437. //
  438. // if only a single version matches.
  439. const spawnSyncOptions = {
  440. cwd: rushTempFolder,
  441. stdio: [],
  442. shell: _isWindows()
  443. };
  444. const platformNpmPath = _getPlatformPath(npmPath);
  445. const npmVersionSpawnResult = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformNpmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier', '--json'], spawnSyncOptions);
  446. if (npmVersionSpawnResult.status !== 0) {
  447. throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`);
  448. }
  449. const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString();
  450. const parsedVersionOutput = JSON.parse(npmViewVersionOutput);
  451. const versions = Array.isArray(parsedVersionOutput)
  452. ? parsedVersionOutput
  453. : [parsedVersionOutput];
  454. let latestVersion = versions[0];
  455. for (let i = 1; i < versions.length; i++) {
  456. const latestVersionCandidate = versions[i];
  457. if (_compareVersionStrings(latestVersionCandidate, latestVersion) > 0) {
  458. latestVersion = latestVersionCandidate;
  459. }
  460. }
  461. if (!latestVersion) {
  462. throw new Error('No versions found for the specified version range.');
  463. }
  464. return latestVersion;
  465. }
  466. catch (e) {
  467. throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`);
  468. }
  469. }
  470. }
  471. let _rushJsonFolder;
  472. /**
  473. * Find the absolute path to the folder containing rush.json
  474. */
  475. function findRushJsonFolder() {
  476. if (!_rushJsonFolder) {
  477. let basePath = __dirname;
  478. let tempPath = __dirname;
  479. do {
  480. const testRushJsonPath = path__WEBPACK_IMPORTED_MODULE_3__.join(basePath, RUSH_JSON_FILENAME);
  481. if (fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(testRushJsonPath)) {
  482. _rushJsonFolder = basePath;
  483. break;
  484. }
  485. else {
  486. basePath = tempPath;
  487. }
  488. } while (basePath !== (tempPath = path__WEBPACK_IMPORTED_MODULE_3__.dirname(basePath))); // Exit the loop when we hit the disk root
  489. if (!_rushJsonFolder) {
  490. throw new Error(`Unable to find ${RUSH_JSON_FILENAME}.`);
  491. }
  492. }
  493. return _rushJsonFolder;
  494. }
  495. /**
  496. * Detects if the package in the specified directory is installed
  497. */
  498. function _isPackageAlreadyInstalled(packageInstallFolder) {
  499. try {
  500. const flagFilePath = path__WEBPACK_IMPORTED_MODULE_3__.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
  501. if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(flagFilePath)) {
  502. return false;
  503. }
  504. const fileContents = fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(flagFilePath).toString();
  505. return fileContents.trim() === process.version;
  506. }
  507. catch (e) {
  508. return false;
  509. }
  510. }
  511. /**
  512. * Delete a file. Fail silently if it does not exist.
  513. */
  514. function _deleteFile(file) {
  515. try {
  516. fs__WEBPACK_IMPORTED_MODULE_1__.unlinkSync(file);
  517. }
  518. catch (err) {
  519. if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') {
  520. throw err;
  521. }
  522. }
  523. }
  524. /**
  525. * Removes the following files and directories under the specified folder path:
  526. * - installed.flag
  527. * -
  528. * - node_modules
  529. */
  530. function _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath) {
  531. try {
  532. const flagFile = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME);
  533. _deleteFile(flagFile);
  534. const packageLockFile = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, 'package-lock.json');
  535. if (lockFilePath) {
  536. fs__WEBPACK_IMPORTED_MODULE_1__.copyFileSync(lockFilePath, packageLockFile);
  537. }
  538. else {
  539. // Not running `npm ci`, so need to cleanup
  540. _deleteFile(packageLockFile);
  541. const nodeModulesFolder = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME);
  542. if (fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(nodeModulesFolder)) {
  543. const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler');
  544. fs__WEBPACK_IMPORTED_MODULE_1__.renameSync(nodeModulesFolder, path__WEBPACK_IMPORTED_MODULE_3__.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`));
  545. }
  546. }
  547. }
  548. catch (e) {
  549. throw new Error(`Error cleaning the package install folder (${packageInstallFolder}): ${e}`);
  550. }
  551. }
  552. function _createPackageJson(packageInstallFolder, name, version) {
  553. try {
  554. const packageJsonContents = {
  555. name: 'ci-rush',
  556. version: '0.0.0',
  557. dependencies: {
  558. [name]: version
  559. },
  560. description: "DON'T WARN",
  561. repository: "DON'T WARN",
  562. license: 'MIT'
  563. };
  564. const packageJsonPath = path__WEBPACK_IMPORTED_MODULE_3__.join(packageInstallFolder, PACKAGE_JSON_FILENAME);
  565. fs__WEBPACK_IMPORTED_MODULE_1__.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2));
  566. }
  567. catch (e) {
  568. throw new Error(`Unable to create package.json: ${e}`);
  569. }
  570. }
  571. /**
  572. * Run "npm install" in the package install folder.
  573. */
  574. function _installPackage(logger, packageInstallFolder, name, version, command) {
  575. try {
  576. logger.info(`Installing ${name}...`);
  577. const npmPath = getNpmPath();
  578. const platformNpmPath = _getPlatformPath(npmPath);
  579. const result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformNpmPath, [command], {
  580. stdio: 'inherit',
  581. cwd: packageInstallFolder,
  582. env: process.env,
  583. shell: _isWindows()
  584. });
  585. if (result.status !== 0) {
  586. throw new Error(`"npm ${command}" encountered an error`);
  587. }
  588. logger.info(`Successfully installed ${name}@${version}`);
  589. }
  590. catch (e) {
  591. throw new Error(`Unable to install package: ${e}`);
  592. }
  593. }
  594. /**
  595. * Get the ".bin" path for the package.
  596. */
  597. function _getBinPath(packageInstallFolder, binName) {
  598. const binFolderPath = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin');
  599. const resolvedBinName = _isWindows() ? `${binName}.cmd` : binName;
  600. return path__WEBPACK_IMPORTED_MODULE_3__.resolve(binFolderPath, resolvedBinName);
  601. }
  602. /**
  603. * Returns a cross-platform path - windows must enclose any path containing spaces within double quotes.
  604. */
  605. function _getPlatformPath(platformPath) {
  606. return _isWindows() && platformPath.includes(' ') ? `"${platformPath}"` : platformPath;
  607. }
  608. function _isWindows() {
  609. return os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32';
  610. }
  611. /**
  612. * Write a flag file to the package's install directory, signifying that the install was successful.
  613. */
  614. function _writeFlagFile(packageInstallFolder) {
  615. try {
  616. const flagFilePath = path__WEBPACK_IMPORTED_MODULE_3__.join(packageInstallFolder, INSTALLED_FLAG_FILENAME);
  617. fs__WEBPACK_IMPORTED_MODULE_1__.writeFileSync(flagFilePath, process.version);
  618. }
  619. catch (e) {
  620. throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`);
  621. }
  622. }
  623. function installAndRun(logger, packageName, packageVersion, packageBinName, packageBinArgs, lockFilePath = process.env[INSTALL_RUN_LOCKFILE_PATH_VARIABLE]) {
  624. const rushJsonFolder = findRushJsonFolder();
  625. const rushCommonFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushJsonFolder, 'common');
  626. const rushTempFolder = _getRushTempFolder(rushCommonFolder);
  627. const packageInstallFolder = _ensureAndJoinPath(rushTempFolder, 'install-run', `${packageName}@${packageVersion}`);
  628. if (!_isPackageAlreadyInstalled(packageInstallFolder)) {
  629. // The package isn't already installed
  630. _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath);
  631. const sourceNpmrcFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushCommonFolder, 'config', 'rush');
  632. (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)({
  633. sourceNpmrcFolder,
  634. targetNpmrcFolder: packageInstallFolder,
  635. logger
  636. });
  637. _createPackageJson(packageInstallFolder, packageName, packageVersion);
  638. const command = lockFilePath ? 'ci' : 'install';
  639. _installPackage(logger, packageInstallFolder, packageName, packageVersion, command);
  640. _writeFlagFile(packageInstallFolder);
  641. }
  642. const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`;
  643. const statusMessageLine = new Array(statusMessage.length + 1).join('-');
  644. logger.info('\n' + statusMessage + '\n' + statusMessageLine + '\n');
  645. const binPath = _getBinPath(packageInstallFolder, packageBinName);
  646. const binFolderPath = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin');
  647. // Windows environment variables are case-insensitive. Instead of using SpawnSyncOptions.env, we need to
  648. // assign via the process.env proxy to ensure that we append to the right PATH key.
  649. const originalEnvPath = process.env.PATH || '';
  650. let result;
  651. try {
  652. // `npm` bin stubs on Windows are `.cmd` files
  653. // Node.js will not directly invoke a `.cmd` file unless `shell` is set to `true`
  654. const platformBinPath = _getPlatformPath(binPath);
  655. process.env.PATH = [binFolderPath, originalEnvPath].join(path__WEBPACK_IMPORTED_MODULE_3__.delimiter);
  656. result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformBinPath, packageBinArgs, {
  657. stdio: 'inherit',
  658. windowsVerbatimArguments: false,
  659. shell: _isWindows(),
  660. cwd: process.cwd(),
  661. env: process.env
  662. });
  663. }
  664. finally {
  665. process.env.PATH = originalEnvPath;
  666. }
  667. if (result.status !== null) {
  668. return result.status;
  669. }
  670. else {
  671. throw result.error || new Error('An unknown error occurred.');
  672. }
  673. }
  674. function runWithErrorAndStatusCode(logger, fn) {
  675. process.exitCode = 1;
  676. try {
  677. const exitCode = fn();
  678. process.exitCode = exitCode;
  679. }
  680. catch (e) {
  681. logger.error('\n\n' + e.toString() + '\n\n');
  682. }
  683. }
  684. function _run() {
  685. const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, rawPackageSpecifier /* qrcode@^1.2.0 */, packageBinName /* qrcode */, ...packageBinArgs /* [-f, myproject/lib] */] = process.argv;
  686. if (!nodePath) {
  687. throw new Error('Unexpected exception: could not detect node path');
  688. }
  689. if (path__WEBPACK_IMPORTED_MODULE_3__.basename(scriptPath).toLowerCase() !== 'install-run.js') {
  690. // If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control
  691. // to the script that (presumably) imported this file
  692. return;
  693. }
  694. if (process.argv.length < 4) {
  695. console.log('Usage: install-run.js <package>@<version> <command> [args...]');
  696. console.log('Example: install-run.js qrcode@1.2.2 qrcode https://rushjs.io');
  697. process.exit(1);
  698. }
  699. const logger = { info: console.log, error: console.error };
  700. runWithErrorAndStatusCode(logger, () => {
  701. const rushJsonFolder = findRushJsonFolder();
  702. const rushCommonFolder = _ensureAndJoinPath(rushJsonFolder, 'common');
  703. const packageSpecifier = _parsePackageSpecifier(rawPackageSpecifier);
  704. const name = packageSpecifier.name;
  705. const version = _resolvePackageVersion(logger, rushCommonFolder, packageSpecifier);
  706. if (packageSpecifier.version !== version) {
  707. console.log(`Resolved to ${name}@${version}`);
  708. }
  709. return installAndRun(logger, name, version, packageBinName, packageBinArgs);
  710. });
  711. }
  712. _run();
  713. //# sourceMappingURL=install-run.js.map
  714. })();
  715. module.exports = __webpack_exports__;
  716. /******/ })()
  717. ;
  718. //# sourceMappingURL=install-run.js.map