install-run.js 32 KB

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