@pnpm/exe 11.20.0 → 11.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.js CHANGED
@@ -8388,21 +8388,18 @@ function removeContentsOfDirSync(dir) {
8388
8388
  // ../fs/indexed-pkg-importer/lib/importIndexedDir.js
8389
8389
  var import_sanitize_filename = __toESM(require_sanitize_filename(), 1);
8390
8390
  var filenameConflictsLogger = logger("_filename-conflicts");
8391
+ var RENAME_RETRY_BUDGET_MS = 6e4;
8392
+ var RENAME_RETRY_BACKOFF_CAP_MS = 100;
8393
+ var FILE_COMPARE_BUFFER_SIZE = 64 * 1024;
8394
+ var renameRetrySleepBuffer = new Int32Array(new SharedArrayBuffer(4));
8391
8395
  function importIndexedDir(importer, newDir, filenames, opts2) {
8392
- if (!opts2.keepModulesDir) {
8393
- if (opts2.safeToSkip) {
8394
- try {
8395
- fs9.mkdirSync(newDir, { recursive: true });
8396
- tryImportIndexedDir(importer, newDir, filenames);
8397
- return;
8398
- } catch (err) {
8399
- if (util6.types.isNativeError(err) && "code" in err && err.code === "EEXIST" && allFilesMatch(newDir, filenames)) {
8400
- return;
8401
- }
8402
- }
8403
- } else if (tryExclusiveImport(importer, newDir, filenames)) {
8404
- return;
8405
- }
8396
+ const dirImport = { importer, newDir, filenames, opts: opts2 };
8397
+ if (opts2.safeToSkip && opts2.resolvedFrom !== "local-dir") {
8398
+ importIntoSharedDir(dirImport);
8399
+ return;
8400
+ }
8401
+ if (!opts2.keepModulesDir && tryExclusiveImport(importer, newDir, filenames)) {
8402
+ return;
8406
8403
  }
8407
8404
  const stage = fastPathTemp(newDir);
8408
8405
  try {
@@ -8416,50 +8413,160 @@ function importIndexedDir(importer, newDir, filenames, opts2) {
8416
8413
  rimrafSync(stage);
8417
8414
  } catch {
8418
8415
  }
8419
- if (util6.types.isNativeError(err) && "code" in err && err.code === "EEXIST") {
8420
- const { uniqueFileMap, conflictingFileNames } = getUniqueFileMap(filenames);
8421
- if (conflictingFileNames.size === 0)
8422
- throw err;
8423
- filenameConflictsLogger.debug({
8424
- conflicts: Object.fromEntries(conflictingFileNames),
8425
- writingTo: newDir
8426
- });
8427
- globalWarn(`Not all files were linked to "${path13.relative(process.cwd(), newDir)}". Some of the files have equal names in different case, which is an issue on case-insensitive filesystems. The conflicting file names are: ${JSON.stringify(Object.fromEntries(conflictingFileNames))}`);
8428
- importIndexedDir(importer, newDir, uniqueFileMap, opts2);
8416
+ if (retryWithFixedFileMap(err, dirImport))
8429
8417
  return;
8418
+ throw err;
8419
+ }
8420
+ try {
8421
+ renameOverwriteSync(stage, newDir);
8422
+ } catch (renameErr) {
8423
+ try {
8424
+ rimrafSync(stage);
8425
+ } catch {
8430
8426
  }
8431
- if (util6.types.isNativeError(err) && "code" in err && err.code === "ENOENT") {
8432
- if (retryWithSanitizedFilenames(importer, newDir, filenames, opts2))
8433
- return;
8427
+ throw renameErr;
8428
+ }
8429
+ }
8430
+ function importIntoSharedDir(dirImport) {
8431
+ const { importer, newDir, filenames } = dirImport;
8432
+ fs9.mkdirSync(path13.dirname(newDir), { recursive: true });
8433
+ let created = false;
8434
+ try {
8435
+ fs9.mkdirSync(newDir);
8436
+ created = true;
8437
+ } catch (err) {
8438
+ if (!util6.types.isNativeError(err) || !("code" in err) || err.code !== "EEXIST")
8434
8439
  throw err;
8440
+ }
8441
+ if (created) {
8442
+ try {
8443
+ tryImportIndexedDir(importer, newDir, filenames);
8444
+ return;
8445
+ } catch (err) {
8446
+ if (retryWithFixedFileMap(err, dirImport))
8447
+ return;
8448
+ }
8449
+ }
8450
+ if (allFilesMatch(newDir, filenames))
8451
+ return;
8452
+ try {
8453
+ repairIndexedDir(dirImport);
8454
+ } catch (err) {
8455
+ if (retryWithFixedFileMap(err, dirImport))
8456
+ return;
8457
+ throw err;
8458
+ }
8459
+ }
8460
+ function repairIndexedDir({ importer, newDir, filenames }) {
8461
+ makeFileMapDirs(newDir, filenames, { clearBlockers: true });
8462
+ let packageJsonSrc;
8463
+ for (const [f, src2] of filenames) {
8464
+ if (f === "package.json") {
8465
+ packageJsonSrc = src2;
8466
+ continue;
8467
+ }
8468
+ replaceFileIfDifferent(importer.importFile, src2, path13.join(newDir, f));
8469
+ }
8470
+ if (packageJsonSrc !== void 0) {
8471
+ replaceFileIfDifferent(importer.importFile, packageJsonSrc, path13.join(newDir, "package.json"));
8472
+ }
8473
+ }
8474
+ function replaceFileIfDifferent(importFile, src2, dest) {
8475
+ if (mismatchReason(dest, src2) === void 0)
8476
+ return;
8477
+ const tmp = fastPathTemp(dest);
8478
+ try {
8479
+ importFile(src2, tmp);
8480
+ } catch (err) {
8481
+ try {
8482
+ fs9.unlinkSync(tmp);
8483
+ } catch {
8484
+ }
8485
+ throw err;
8486
+ }
8487
+ try {
8488
+ clearDirBlockingFile(dest);
8489
+ renameFileWithRetry(tmp, dest);
8490
+ } catch (err) {
8491
+ try {
8492
+ fs9.unlinkSync(tmp);
8493
+ } catch {
8435
8494
  }
8495
+ if (mismatchReason(dest, src2) === void 0)
8496
+ return;
8436
8497
  throw err;
8437
8498
  }
8438
- if (opts2.safeToSkip) {
8499
+ }
8500
+ function renameFileWithRetry(src2, dest) {
8501
+ const startedAt = Date.now();
8502
+ let backoffMs = 0;
8503
+ for (; ; ) {
8439
8504
  try {
8440
- fs9.renameSync(stage, newDir);
8505
+ fs9.renameSync(src2, dest);
8441
8506
  return;
8442
8507
  } catch (err) {
8443
- if (util6.types.isNativeError(err) && "code" in err && (err.code === "ENOTEMPTY" || err.code === "EEXIST" || err.code === "EPERM")) {
8444
- if (allFilesMatch(newDir, filenames)) {
8445
- try {
8446
- rimrafSync(stage);
8447
- } catch {
8448
- }
8449
- return;
8450
- }
8451
- }
8508
+ if (!isTransientRenameError(err) || Date.now() - startedAt >= RENAME_RETRY_BUDGET_MS)
8509
+ throw err;
8510
+ if (backoffMs > 0)
8511
+ Atomics.wait(renameRetrySleepBuffer, 0, 0, backoffMs);
8512
+ backoffMs = Math.min(backoffMs + 10, RENAME_RETRY_BACKOFF_CAP_MS);
8452
8513
  }
8453
8514
  }
8515
+ }
8516
+ function isTransientRenameError(err) {
8517
+ return process.platform === "win32" && util6.types.isNativeError(err) && "code" in err && (err.code === "EPERM" || err.code === "EACCES" || err.code === "EBUSY");
8518
+ }
8519
+ function clearDirBlockingFile(dest) {
8520
+ let stats;
8454
8521
  try {
8455
- renameOverwriteSync(stage, newDir);
8456
- } catch (renameErr) {
8522
+ stats = fs9.lstatSync(dest);
8523
+ } catch (err) {
8524
+ if (util6.types.isNativeError(err) && "code" in err && err.code === "ENOENT")
8525
+ return;
8526
+ throw err;
8527
+ }
8528
+ if (stats.isDirectory()) {
8529
+ rimrafSync(dest);
8530
+ }
8531
+ }
8532
+ function clearDirentBlockingDir(newDir, relativeDir) {
8533
+ let dir = newDir;
8534
+ for (const segment of relativeDir.split(/[\\/]/)) {
8535
+ dir = path13.join(dir, segment);
8536
+ let stats;
8457
8537
  try {
8458
- rimrafSync(stage);
8459
- } catch {
8538
+ stats = fs9.lstatSync(dir);
8539
+ } catch (err) {
8540
+ if (util6.types.isNativeError(err) && "code" in err && err.code === "ENOENT")
8541
+ return;
8542
+ throw err;
8460
8543
  }
8461
- throw renameErr;
8544
+ if (stats.isDirectory())
8545
+ continue;
8546
+ fs9.unlinkSync(dir);
8547
+ return;
8548
+ }
8549
+ }
8550
+ function retryWithFixedFileMap(err, dirImport) {
8551
+ const { importer, newDir, filenames, opts: opts2 } = dirImport;
8552
+ if (!util6.types.isNativeError(err) || !("code" in err))
8553
+ return false;
8554
+ if (err.code === "EEXIST") {
8555
+ const { uniqueFileMap, conflictingFileNames } = getUniqueFileMap(filenames);
8556
+ if (conflictingFileNames.size === 0)
8557
+ return false;
8558
+ filenameConflictsLogger.debug({
8559
+ conflicts: Object.fromEntries(conflictingFileNames),
8560
+ writingTo: newDir
8561
+ });
8562
+ globalWarn(`Not all files were linked to "${path13.relative(process.cwd(), newDir)}". Some of the files have equal names in different case, which is an issue on case-insensitive filesystems. The conflicting file names are: ${JSON.stringify(Object.fromEntries(conflictingFileNames))}`);
8563
+ importIndexedDir(importer, newDir, uniqueFileMap, opts2);
8564
+ return true;
8462
8565
  }
8566
+ if (err.code === "ENOENT") {
8567
+ return retryWithSanitizedFilenames(dirImport);
8568
+ }
8569
+ return false;
8463
8570
  }
8464
8571
  function tryExclusiveImport(importer, newDir, filenames) {
8465
8572
  fs9.mkdirSync(path13.dirname(newDir), { recursive: true });
@@ -8482,29 +8589,67 @@ function tryExclusiveImport(importer, newDir, filenames) {
8482
8589
  }
8483
8590
  }
8484
8591
  function allFilesMatch(dir, filenames) {
8592
+ const markerSrc = filenames.get("package.json");
8593
+ if (markerSrc !== void 0 && !fileMatches(dir, "package.json", markerSrc))
8594
+ return false;
8485
8595
  for (const [f, src2] of filenames) {
8486
- const target2 = path13.join(dir, f);
8596
+ if (f === "package.json")
8597
+ continue;
8598
+ if (!fileMatches(dir, f, src2))
8599
+ return false;
8600
+ }
8601
+ return true;
8602
+ }
8603
+ function fileMatches(dir, f, src2) {
8604
+ const reason = mismatchReason(path13.join(dir, f), src2);
8605
+ if (reason === void 0)
8606
+ return true;
8607
+ globalInfo(`Re-importing "${dir}" because file "${f}" ${reason}`);
8608
+ return false;
8609
+ }
8610
+ function mismatchReason(target2, src2) {
8611
+ try {
8612
+ const targetStat = fs9.lstatSync(target2, { bigint: true });
8613
+ if (!targetStat.isFile())
8614
+ return "is not a regular file";
8615
+ const srcStat = lib_default.statSync(src2, { bigint: true });
8616
+ const hasSameFileIdentity = targetStat.ino !== 0n && targetStat.dev !== 0n && targetStat.ino === srcStat.ino && targetStat.dev === srcStat.dev;
8617
+ if (hasSameFileIdentity)
8618
+ return void 0;
8619
+ if (targetStat.size !== srcStat.size)
8620
+ return "has a different size";
8621
+ if (!filesHaveEqualContents(target2, src2))
8622
+ return "has different content";
8623
+ return void 0;
8624
+ } catch {
8625
+ return "is missing or unreadable";
8626
+ }
8627
+ }
8628
+ function filesHaveEqualContents(left, right) {
8629
+ const leftBuffer = Buffer.allocUnsafe(FILE_COMPARE_BUFFER_SIZE);
8630
+ const rightBuffer = Buffer.allocUnsafe(FILE_COMPARE_BUFFER_SIZE);
8631
+ const leftFd = fs9.openSync(left, "r");
8632
+ try {
8633
+ const rightFd = fs9.openSync(right, "r");
8487
8634
  try {
8488
- const targetStat = lib_default.statSync(target2);
8489
- const srcStat = lib_default.statSync(src2);
8490
- if (targetStat.ino === srcStat.ino && targetStat.dev === srcStat.dev)
8491
- continue;
8492
- if (targetStat.size !== srcStat.size) {
8493
- globalInfo(`Re-importing "${dir}" because file "${f}" has a different size`);
8494
- return false;
8495
- }
8496
- if (!lib_default.readFileSync(target2).equals(lib_default.readFileSync(src2))) {
8497
- globalInfo(`Re-importing "${dir}" because file "${f}" has different content`);
8498
- return false;
8635
+ for (; ; ) {
8636
+ const leftBytes = fs9.readSync(leftFd, leftBuffer, 0, leftBuffer.length, null);
8637
+ const rightBytes = fs9.readSync(rightFd, rightBuffer, 0, rightBuffer.length, null);
8638
+ if (leftBytes !== rightBytes)
8639
+ return false;
8640
+ if (leftBytes === 0)
8641
+ return true;
8642
+ if (!leftBuffer.subarray(0, leftBytes).equals(rightBuffer.subarray(0, rightBytes)))
8643
+ return false;
8499
8644
  }
8500
- } catch {
8501
- globalInfo(`Re-importing "${dir}" because file "${f}" is missing or unreadable`);
8502
- return false;
8645
+ } finally {
8646
+ fs9.closeSync(rightFd);
8503
8647
  }
8648
+ } finally {
8649
+ fs9.closeSync(leftFd);
8504
8650
  }
8505
- return true;
8506
8651
  }
8507
- function retryWithSanitizedFilenames(importer, newDir, filenames, opts2) {
8652
+ function retryWithSanitizedFilenames({ importer, newDir, filenames, opts: opts2 }) {
8508
8653
  const { sanitizedFilenames, invalidFilenames } = sanitizeFilenames(filenames);
8509
8654
  if (invalidFilenames.length === 0)
8510
8655
  return false;
@@ -8525,14 +8670,7 @@ function sanitizeFilenames(filenames) {
8525
8670
  return { sanitizedFilenames, invalidFilenames };
8526
8671
  }
8527
8672
  function tryImportIndexedDir({ importFile, importFileAtomic }, newDir, filenames) {
8528
- const allDirs = /* @__PURE__ */ new Set();
8529
- for (const f of filenames.keys()) {
8530
- const dir = path13.dirname(f);
8531
- if (dir === ".")
8532
- continue;
8533
- allDirs.add(dir);
8534
- }
8535
- Array.from(allDirs).sort((d1, d2) => d1.length - d2.length).forEach((dir) => fs9.mkdirSync(path13.join(newDir, dir), { recursive: true }));
8673
+ makeFileMapDirs(newDir, filenames);
8536
8674
  let packageJsonSrc;
8537
8675
  for (const [f, src2] of filenames) {
8538
8676
  if (f === "package.json") {
@@ -8545,6 +8683,21 @@ function tryImportIndexedDir({ importFile, importFileAtomic }, newDir, filenames
8545
8683
  importFileAtomic(packageJsonSrc, path13.join(newDir, "package.json"));
8546
8684
  }
8547
8685
  }
8686
+ function makeFileMapDirs(newDir, filenames, opts2) {
8687
+ const allDirs = /* @__PURE__ */ new Set();
8688
+ for (const f of filenames.keys()) {
8689
+ const dir = path13.dirname(f);
8690
+ if (dir === ".")
8691
+ continue;
8692
+ allDirs.add(dir);
8693
+ }
8694
+ for (const dir of Array.from(allDirs).sort((d1, d2) => d1.length - d2.length)) {
8695
+ if (opts2?.clearBlockers) {
8696
+ clearDirentBlockingDir(newDir, dir);
8697
+ }
8698
+ fs9.mkdirSync(path13.join(newDir, dir), { recursive: true });
8699
+ }
8700
+ }
8548
8701
  function getUniqueFileMap(fileMap) {
8549
8702
  const lowercaseFiles = /* @__PURE__ */ new Map();
8550
8703
  const conflictingFileNames = /* @__PURE__ */ new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/exe",
3
- "version": "11.20.0",
3
+ "version": "11.22.0",
4
4
  "description": "Fast, disk space efficient package manager",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -35,19 +35,19 @@
35
35
  "detect-libc": "^2.1.2"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@pnpm/linux-arm64": "11.20.0",
39
- "@pnpm/linux-x64": "11.20.0",
40
- "@pnpm/linuxstatic-arm64": "11.20.0",
41
- "@pnpm/linuxstatic-x64": "11.20.0",
42
- "@pnpm/macos-arm64": "11.20.0",
43
- "@pnpm/win-arm64": "11.20.0",
44
- "@pnpm/win-x64": "11.20.0"
38
+ "@pnpm/linux-arm64": "11.22.0",
39
+ "@pnpm/linux-x64": "11.22.0",
40
+ "@pnpm/linuxstatic-arm64": "11.22.0",
41
+ "@pnpm/linuxstatic-x64": "11.22.0",
42
+ "@pnpm/macos-arm64": "11.22.0",
43
+ "@pnpm/win-arm64": "11.22.0",
44
+ "@pnpm/win-x64": "11.22.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@jest/globals": "30.4.1",
48
- "@pnpm/exe": "11.20.0",
48
+ "@pnpm/exe": "11.22.0",
49
49
  "@pnpm/jest-config": "1100.0.22",
50
- "@zkochan/cmd-shim": "^9.0.6",
50
+ "@zkochan/cmd-shim": "^9.0.7",
51
51
  "execa": "npm:safe-execa@0.3.0"
52
52
  },
53
53
  "jest": {