@pnpm/exe 11.0.0-beta.2 → 11.0.0-beta.3

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.
Files changed (79) hide show
  1. package/dist/node_modules/@gar/promise-retry/LICENSE +1 -0
  2. package/dist/node_modules/@gar/promise-retry/lib/index.js +43 -9
  3. package/dist/node_modules/@gar/promise-retry/lib/retry.js +109 -0
  4. package/dist/node_modules/@gar/promise-retry/package.json +1 -4
  5. package/dist/node_modules/@npmcli/redact/LICENSE +21 -0
  6. package/dist/node_modules/@npmcli/redact/lib/deep-map.js +71 -0
  7. package/dist/node_modules/@npmcli/redact/lib/error.js +28 -0
  8. package/dist/node_modules/@npmcli/redact/lib/index.js +44 -0
  9. package/dist/node_modules/@npmcli/redact/lib/matchers.js +88 -0
  10. package/dist/node_modules/@npmcli/redact/lib/server.js +59 -0
  11. package/dist/node_modules/@npmcli/redact/lib/utils.js +202 -0
  12. package/dist/node_modules/{unique-slug → @npmcli/redact}/package.json +21 -18
  13. package/dist/node_modules/brace-expansion/dist/commonjs/index.js +3 -1
  14. package/dist/node_modules/brace-expansion/dist/esm/index.js +3 -1
  15. package/dist/node_modules/brace-expansion/package.json +1 -1
  16. package/dist/node_modules/cacache/lib/content/write.js +2 -2
  17. package/dist/node_modules/cacache/lib/entry-index.js +2 -2
  18. package/dist/node_modules/cacache/lib/util/tmp.js +6 -0
  19. package/dist/node_modules/cacache/package.json +4 -5
  20. package/dist/node_modules/make-fetch-happen/lib/remote.js +4 -2
  21. package/dist/node_modules/make-fetch-happen/package.json +2 -1
  22. package/dist/node_modules/picomatch/lib/constants.js +4 -0
  23. package/dist/node_modules/picomatch/lib/parse.js +301 -0
  24. package/dist/node_modules/picomatch/lib/picomatch.js +11 -3
  25. package/dist/node_modules/picomatch/package.json +2 -3
  26. package/dist/node_modules/tar/dist/commonjs/create.js +3 -4
  27. package/dist/node_modules/tar/dist/commonjs/get-write-flag.js +7 -4
  28. package/dist/node_modules/tar/dist/commonjs/header.js +14 -27
  29. package/dist/node_modules/tar/dist/commonjs/index.min.js +3 -3
  30. package/dist/node_modules/tar/dist/commonjs/list.js +2 -7
  31. package/dist/node_modules/tar/dist/commonjs/make-command.js +3 -12
  32. package/dist/node_modules/tar/dist/commonjs/mkdir.js +5 -6
  33. package/dist/node_modules/tar/dist/commonjs/normalize-windows-path.js +1 -1
  34. package/dist/node_modules/tar/dist/commonjs/pack.js +3 -8
  35. package/dist/node_modules/tar/dist/commonjs/parse.js +12 -22
  36. package/dist/node_modules/tar/dist/commonjs/path-reservations.js +2 -2
  37. package/dist/node_modules/tar/dist/commonjs/read-entry.js +2 -6
  38. package/dist/node_modules/tar/dist/commonjs/replace.js +5 -10
  39. package/dist/node_modules/tar/dist/commonjs/unpack.js +38 -63
  40. package/dist/node_modules/tar/dist/commonjs/winchars.js +1 -1
  41. package/dist/node_modules/tar/dist/commonjs/write-entry.js +12 -13
  42. package/dist/node_modules/tar/dist/esm/create.js +3 -4
  43. package/dist/node_modules/tar/dist/esm/get-write-flag.js +7 -4
  44. package/dist/node_modules/tar/dist/esm/header.js +14 -27
  45. package/dist/node_modules/tar/dist/esm/index.min.js +3 -3
  46. package/dist/node_modules/tar/dist/esm/list.js +2 -7
  47. package/dist/node_modules/tar/dist/esm/make-command.js +3 -12
  48. package/dist/node_modules/tar/dist/esm/mkdir.js +5 -6
  49. package/dist/node_modules/tar/dist/esm/normalize-windows-path.js +1 -1
  50. package/dist/node_modules/tar/dist/esm/pack.js +4 -9
  51. package/dist/node_modules/tar/dist/esm/parse.js +13 -23
  52. package/dist/node_modules/tar/dist/esm/path-reservations.js +2 -2
  53. package/dist/node_modules/tar/dist/esm/read-entry.js +2 -6
  54. package/dist/node_modules/tar/dist/esm/replace.js +6 -11
  55. package/dist/node_modules/tar/dist/esm/unpack.js +38 -63
  56. package/dist/node_modules/tar/dist/esm/winchars.js +1 -1
  57. package/dist/node_modules/tar/dist/esm/write-entry.js +14 -15
  58. package/dist/node_modules/tar/package.json +9 -4
  59. package/dist/pnpm.mjs +7586 -6579
  60. package/dist/worker.js +140 -50
  61. package/package.json +12 -9
  62. package/pn +1 -0
  63. package/pnpx +1 -0
  64. package/pnx +1 -0
  65. package/prepare.js +12 -3
  66. package/setup.js +28 -1
  67. package/dist/node_modules/imurmurhash/imurmurhash.js +0 -138
  68. package/dist/node_modules/imurmurhash/imurmurhash.min.js +0 -12
  69. package/dist/node_modules/imurmurhash/package.json +0 -40
  70. package/dist/node_modules/retry/License +0 -21
  71. package/dist/node_modules/retry/index.js +0 -1
  72. package/dist/node_modules/retry/lib/retry.js +0 -100
  73. package/dist/node_modules/retry/lib/retry_operation.js +0 -162
  74. package/dist/node_modules/retry/package.json +0 -36
  75. package/dist/node_modules/unique-filename/LICENSE +0 -5
  76. package/dist/node_modules/unique-filename/lib/index.js +0 -7
  77. package/dist/node_modules/unique-filename/package.json +0 -53
  78. package/dist/node_modules/unique-slug/LICENSE +0 -15
  79. package/dist/node_modules/unique-slug/lib/index.js +0 -11
@@ -9,12 +9,7 @@ export const makeCommand = (syncFile, asyncFile, syncNoFile, asyncNoFile, valida
9
9
  cb = entries;
10
10
  entries = undefined;
11
11
  }
12
- if (!entries) {
13
- entries = [];
14
- }
15
- else {
16
- entries = Array.from(entries);
17
- }
12
+ entries = !entries ? [] : Array.from(entries);
18
13
  const opt = dealias(opt_);
19
14
  validate?.(opt, entries);
20
15
  if (isSyncFile(opt)) {
@@ -25,9 +20,7 @@ export const makeCommand = (syncFile, asyncFile, syncNoFile, asyncNoFile, valida
25
20
  }
26
21
  else if (isAsyncFile(opt)) {
27
22
  const p = asyncFile(opt, entries);
28
- // weirdness to make TS happy
29
- const c = cb ? cb : undefined;
30
- return c ? p.then(() => c(), c) : p;
23
+ return cb ? p.then(() => cb(), cb) : p;
31
24
  }
32
25
  else if (isSyncNoFile(opt)) {
33
26
  if (typeof cb === 'function') {
@@ -42,9 +35,7 @@ export const makeCommand = (syncFile, asyncFile, syncNoFile, asyncNoFile, valida
42
35
  return asyncNoFile(opt, entries);
43
36
  /* c8 ignore start */
44
37
  }
45
- else {
46
- throw new Error('impossible options??');
47
- }
38
+ throw new Error('impossible options??');
48
39
  /* c8 ignore stop */
49
40
  }, {
50
41
  syncFile,
@@ -65,7 +65,7 @@ export const mkdir = (dir, opt, cb) => {
65
65
  mkdir_(cwd, parts, mode, unlink, cwd, undefined, done);
66
66
  };
67
67
  const mkdir_ = (base, parts, mode, unlink, cwd, created, cb) => {
68
- if (!parts.length) {
68
+ if (parts.length === 0) {
69
69
  return cb(null, created);
70
70
  }
71
71
  const p = parts.shift();
@@ -76,8 +76,7 @@ const onmkdir = (part, parts, mode, unlink, cwd, created, cb) => (er) => {
76
76
  if (er) {
77
77
  fs.lstat(part, (statEr, st) => {
78
78
  if (statEr) {
79
- statEr.path =
80
- statEr.path && normalizeWindowsPath(statEr.path);
79
+ statEr.path = statEr.path && normalizeWindowsPath(statEr.path);
81
80
  cb(statEr);
82
81
  }
83
82
  else if (st.isDirectory()) {
@@ -106,7 +105,7 @@ const onmkdir = (part, parts, mode, unlink, cwd, created, cb) => (er) => {
106
105
  };
107
106
  const checkCwdSync = (dir) => {
108
107
  let ok = false;
109
- let code = undefined;
108
+ let code;
110
109
  try {
111
110
  ok = fs.statSync(dir).isDirectory();
112
111
  }
@@ -152,14 +151,14 @@ export const mkdirSync = (dir, opt) => {
152
151
  }
153
152
  const sub = normalizeWindowsPath(path.relative(cwd, dir));
154
153
  const parts = sub.split('/');
155
- let created = undefined;
154
+ let created;
156
155
  for (let p = parts.shift(), part = cwd; p && (part += '/' + p); p = parts.shift()) {
157
156
  part = normalizeWindowsPath(path.resolve(part));
158
157
  try {
159
158
  fs.mkdirSync(part, mode);
160
159
  created = created || part;
161
160
  }
162
- catch (er) {
161
+ catch {
163
162
  const st = fs.lstatSync(part);
164
163
  if (st.isDirectory()) {
165
164
  continue;
@@ -5,5 +5,5 @@
5
5
  const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
6
6
  export const normalizeWindowsPath = platform !== 'win32' ?
7
7
  (p) => p
8
- : (p) => p && p.replace(/\\/g, '/');
8
+ : (p) => p && p.replaceAll(/\\/g, '/');
9
9
  //# sourceMappingURL=normalize-windows-path.js.map
@@ -26,7 +26,7 @@ import { Minipass } from 'minipass';
26
26
  import * as zlib from 'minizlib';
27
27
  import { Yallist } from 'yallist';
28
28
  import { ReadEntry } from './read-entry.js';
29
- import { warnMethod, } from './warn-method.js';
29
+ import { warnMethod } from './warn-method.js';
30
30
  const EOF = Buffer.alloc(1024);
31
31
  const ONSTAT = Symbol('onStat');
32
32
  const ENDED = Symbol('ended');
@@ -86,7 +86,6 @@ export class Pack extends Minipass {
86
86
  [PROCESSING] = false;
87
87
  [ENDED] = false;
88
88
  constructor(opt = {}) {
89
- //@ts-ignore
90
89
  super();
91
90
  this.opt = opt;
92
91
  this.file = opt.file || '';
@@ -106,9 +105,7 @@ export class Pack extends Minipass {
106
105
  }
107
106
  this.portable = !!opt.portable;
108
107
  if (opt.gzip || opt.brotli || opt.zstd) {
109
- if ((opt.gzip ? 1 : 0) +
110
- (opt.brotli ? 1 : 0) +
111
- (opt.zstd ? 1 : 0) >
108
+ if ((opt.gzip ? 1 : 0) + (opt.brotli ? 1 : 0) + (opt.zstd ? 1 : 0) >
112
109
  1) {
113
110
  throw new TypeError('gzip, brotli, zstd are mutually exclusive');
114
111
  }
@@ -284,7 +281,7 @@ export class Pack extends Minipass {
284
281
  }
285
282
  }
286
283
  this[PROCESSING] = false;
287
- if (this[ENDED] && !this[QUEUE].length && this[JOBS] === 0) {
284
+ if (this[ENDED] && this[QUEUE].length === 0 && this[JOBS] === 0) {
288
285
  if (this.zip) {
289
286
  this.zip.end(EOF);
290
287
  }
@@ -328,9 +325,7 @@ export class Pack extends Minipass {
328
325
  if (job.ignore) {
329
326
  return;
330
327
  }
331
- if (!this.noDirRecurse &&
332
- job.stat.isDirectory() &&
333
- !job.readdir) {
328
+ if (!this.noDirRecurse && job.stat.isDirectory() && !job.readdir) {
334
329
  const rc = this.readdirCache.get(job.absolute);
335
330
  if (rc) {
336
331
  this[ONREADDIR](job, rc);
@@ -22,7 +22,7 @@ import { BrotliDecompress, Unzip, ZstdDecompress } from 'minizlib';
22
22
  import { Header } from './header.js';
23
23
  import { Pax } from './pax.js';
24
24
  import { ReadEntry } from './read-entry.js';
25
- import { warnMethod, } from './warn-method.js';
25
+ import { warnMethod } from './warn-method.js';
26
26
  const maxMetaEntrySize = 1024 * 1024;
27
27
  const gzipHeader = Buffer.from([0x1f, 0x8b]);
28
28
  const zstdHeader = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);
@@ -89,8 +89,7 @@ export class Parser extends EE {
89
89
  this.file = opt.file || '';
90
90
  // these BADARCHIVE errors can't be detected early. listen on DONE.
91
91
  this.on(DONE, () => {
92
- if (this[STATE] === 'begin' ||
93
- this[SAW_VALID_ENTRY] === false) {
92
+ if (this[STATE] === 'begin' || this[SAW_VALID_ENTRY] === false) {
94
93
  // either less than 1 block of data, or all entries were invalid.
95
94
  // Either way, probably not even a tarball.
96
95
  this.warn('TAR_BAD_ARCHIVE', 'Unrecognized archive format');
@@ -220,8 +219,7 @@ export class Parser extends EE {
220
219
  }
221
220
  else {
222
221
  this[EX] = undefined;
223
- entry.ignore =
224
- entry.ignore || !this.filter(entry.path, entry);
222
+ entry.ignore = entry.ignore || !this.filter(entry.path, entry);
225
223
  if (entry.ignore) {
226
224
  // probably valid, just not something we care about
227
225
  this[EMIT]('ignoredEntry', entry);
@@ -274,7 +272,7 @@ export class Parser extends EE {
274
272
  }
275
273
  [NEXTENTRY]() {
276
274
  do { } while (this[PROCESSENTRY](this[QUEUE].shift()));
277
- if (!this[QUEUE].length) {
275
+ if (this[QUEUE].length === 0) {
278
276
  // At this point, there's nothing in the queue, but we may have an
279
277
  // entry which is being consumed (readEntry).
280
278
  // If we don't, then we definitely can handle more data.
@@ -324,7 +322,7 @@ export class Parser extends EE {
324
322
  return ret;
325
323
  }
326
324
  [EMIT](ev, data, extra) {
327
- if (!this[QUEUE].length && !this[READENTRY]) {
325
+ if (this[QUEUE].length === 0 && !this[READENTRY]) {
328
326
  this.emit(ev, data, extra);
329
327
  }
330
328
  else {
@@ -471,11 +469,11 @@ export class Parser extends EE {
471
469
  }
472
470
  this[WRITING] = false;
473
471
  // return false if there's a queue, or if the current entry isn't flowing
474
- const ret = this[QUEUE].length ? false
472
+ const ret = this[QUEUE].length > 0 ? false
475
473
  : this[READENTRY] ? this[READENTRY].flowing
476
474
  : true;
477
475
  // if we have no queue, then that means a clogged READENTRY
478
- if (!ret && !this[QUEUE].length) {
476
+ if (!ret && this[QUEUE].length === 0) {
479
477
  this[READENTRY]?.once('drain', () => this.emit('drain'));
480
478
  }
481
479
  /* c8 ignore next */
@@ -484,8 +482,7 @@ export class Parser extends EE {
484
482
  }
485
483
  [BUFFERCONCAT](c) {
486
484
  if (c && !this[ABORTED]) {
487
- this[BUFFER] =
488
- this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c;
485
+ this[BUFFER] = this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c;
489
486
  }
490
487
  }
491
488
  [MAYBEEND]() {
@@ -544,9 +541,7 @@ export class Parser extends EE {
544
541
  // the buffer. Advance the position and put any remainder in the buffer.
545
542
  let position = 0;
546
543
  const length = chunk.length;
547
- while (position + 512 <= length &&
548
- !this[ABORTED] &&
549
- !this[SAW_EOF]) {
544
+ while (position + 512 <= length && !this[ABORTED] && !this[SAW_EOF]) {
550
545
  switch (this[STATE]) {
551
546
  case 'begin':
552
547
  case 'header':
@@ -567,15 +562,10 @@ export class Parser extends EE {
567
562
  }
568
563
  }
569
564
  if (position < length) {
570
- if (this[BUFFER]) {
571
- this[BUFFER] = Buffer.concat([
572
- chunk.subarray(position),
573
- this[BUFFER],
574
- ]);
575
- }
576
- else {
577
- this[BUFFER] = chunk.subarray(position);
578
- }
565
+ this[BUFFER] =
566
+ this[BUFFER] ?
567
+ Buffer.concat([chunk.subarray(position), this[BUFFER]])
568
+ : chunk.subarray(position);
579
569
  }
580
570
  }
581
571
  end(chunk, encoding, cb) {
@@ -17,7 +17,7 @@ const getDirs = (path) => {
17
17
  .split('/')
18
18
  .slice(0, -1)
19
19
  .reduce((set, path) => {
20
- const s = set[set.length - 1];
20
+ const s = set.at(-1);
21
21
  if (s !== undefined) {
22
22
  path = join(s, path);
23
23
  }
@@ -60,7 +60,7 @@ export class PathReservations {
60
60
  this.#queues.set(dir, [new Set([fn])]);
61
61
  }
62
62
  else {
63
- const l = q[q.length - 1];
63
+ const l = q.at(-1);
64
64
  if (l instanceof Set) {
65
65
  l.add(fn);
66
66
  }
@@ -87,9 +87,7 @@ export class ReadEntry extends Minipass {
87
87
  this.ctime = header.ctime;
88
88
  /* c8 ignore start */
89
89
  this.linkpath =
90
- header.linkpath ?
91
- normalizeWindowsPath(header.linkpath)
92
- : undefined;
90
+ header.linkpath ? normalizeWindowsPath(header.linkpath) : undefined;
93
91
  /* c8 ignore stop */
94
92
  this.uname = header.uname;
95
93
  this.gname = header.gname;
@@ -127,9 +125,7 @@ export class ReadEntry extends Minipass {
127
125
  // we slurp in everything except for the path attribute in
128
126
  // a global extended header, because that's weird. Also, any
129
127
  // null/undefined values are ignored.
130
- return !(v === null ||
131
- v === undefined ||
132
- (k === 'path' && gex));
128
+ return !(v === null || v === undefined || (k === 'path' && gex));
133
129
  })));
134
130
  }
135
131
  }
@@ -5,7 +5,7 @@ import path from 'node:path';
5
5
  import { Header } from './header.js';
6
6
  import { list } from './list.js';
7
7
  import { makeCommand } from './make-command.js';
8
- import { isFile, } from './options.js';
8
+ import { isFile } from './options.js';
9
9
  import { Pack, PackSync } from './pack.js';
10
10
  // starting at the head of the file, read a Header
11
11
  // If the checksum is invalid, that's our position to start writing
@@ -34,9 +34,7 @@ const replaceSync = (opt, files) => {
34
34
  POSITION: for (position = 0; position < st.size; position += 512) {
35
35
  for (let bufPos = 0, bytes = 0; bufPos < 512; bufPos += bytes) {
36
36
  bytes = fs.readSync(fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos);
37
- if (position === 0 &&
38
- headBuf[0] === 0x1f &&
39
- headBuf[1] === 0x8b) {
37
+ if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b) {
40
38
  throw new Error('cannot append to compressed archives');
41
39
  }
42
40
  if (!bytes) {
@@ -66,7 +64,7 @@ const replaceSync = (opt, files) => {
66
64
  try {
67
65
  fs.closeSync(fd);
68
66
  }
69
- catch (er) { }
67
+ catch { }
70
68
  }
71
69
  }
72
70
  };
@@ -97,16 +95,14 @@ const replaceAsync = (opt, files) => {
97
95
  let bufPos = 0;
98
96
  const headBuf = Buffer.alloc(512);
99
97
  const onread = (er, bytes) => {
100
- if (er || typeof bytes === 'undefined') {
98
+ if (er || bytes === undefined) {
101
99
  return cb(er);
102
100
  }
103
101
  bufPos += bytes;
104
102
  if (bufPos < 512 && bytes) {
105
103
  return fs.read(fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos, onread);
106
104
  }
107
- if (position === 0 &&
108
- headBuf[0] === 0x1f &&
109
- headBuf[1] === 0x8b) {
105
+ if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b) {
110
106
  return cb(new Error('cannot append to compressed archives'));
111
107
  }
112
108
  // truncated header
@@ -185,8 +181,7 @@ const addFilesSync = (p, files) => {
185
181
  p.end();
186
182
  };
187
183
  const addFilesAsync = async (p, files) => {
188
- for (let i = 0; i < files.length; i++) {
189
- const file = String(files[i]);
184
+ for (const file of files) {
190
185
  if (file.charAt(0) === '@') {
191
186
  await list({
192
187
  file: path.resolve(String(p.cwd), file.slice(1)),
@@ -128,8 +128,7 @@ export class Unpack extends Parser {
128
128
  this.chmod = !!opt.chmod;
129
129
  if (typeof opt.uid === 'number' || typeof opt.gid === 'number') {
130
130
  // need both or neither
131
- if (typeof opt.uid !== 'number' ||
132
- typeof opt.gid !== 'number') {
131
+ if (typeof opt.uid !== 'number' || typeof opt.gid !== 'number') {
133
132
  throw new TypeError('cannot set owner without number uid and gid');
134
133
  }
135
134
  if (opt.preserveOwner) {
@@ -145,13 +144,10 @@ export class Unpack extends Parser {
145
144
  this.setOwner = false;
146
145
  }
147
146
  // default true for root
148
- if (opt.preserveOwner === undefined &&
149
- typeof opt.uid !== 'number') {
150
- this.preserveOwner = !!(process.getuid && process.getuid() === 0);
151
- }
152
- else {
153
- this.preserveOwner = !!opt.preserveOwner;
154
- }
147
+ this.preserveOwner =
148
+ opt.preserveOwner === undefined && typeof opt.uid !== 'number' ?
149
+ !!(process.getuid && process.getuid() === 0)
150
+ : !!opt.preserveOwner;
155
151
  this.processUid =
156
152
  (this.preserveOwner || this.setOwner) && process.getuid ?
157
153
  process.getuid()
@@ -163,9 +159,7 @@ export class Unpack extends Parser {
163
159
  // prevent excessively deep nesting of subfolders
164
160
  // set to `Infinity` to remove this restriction
165
161
  this.maxDepth =
166
- typeof opt.maxDepth === 'number' ?
167
- opt.maxDepth
168
- : DEFAULT_MAX_DEPTH;
162
+ typeof opt.maxDepth === 'number' ? opt.maxDepth : DEFAULT_MAX_DEPTH;
169
163
  // mostly just for testing, but useful in some cases.
170
164
  // Forcibly trigger a chown on every entry, no matter what
171
165
  this.forceChown = opt.forceChown === true;
@@ -223,7 +217,7 @@ export class Unpack extends Parser {
223
217
  return true;
224
218
  // strip off the root
225
219
  const [root, stripped] = stripAbsolutePath(p);
226
- const parts = stripped.replace(/\\/g, '/').split('/');
220
+ const parts = stripped.replaceAll(/\\/g, '/').split('/');
227
221
  if (parts.includes('..') ||
228
222
  /* c8 ignore next */
229
223
  (isWindows && /^[a-z]:\.\.$/i.test(parts[0] ?? ''))) {
@@ -239,20 +233,18 @@ export class Unpack extends Parser {
239
233
  // not ok!
240
234
  return false;
241
235
  }
242
- else {
243
- // Resolve linkpath relative to the entry's directory.
244
- // `path.posix` is safe to use because we're operating on
245
- // tar paths, not a filesystem.
246
- const entryDir = path.posix.dirname(entry.path);
247
- const resolved = path.posix.normalize(path.posix.join(entryDir, parts.join('/')));
248
- // If the resolved path escapes (starts with ..), reject it
249
- if (resolved.startsWith('../') || resolved === '..') {
250
- this.warn('TAR_ENTRY_ERROR', `${field} escapes extraction directory`, {
251
- entry,
252
- [field]: p,
253
- });
254
- return false;
255
- }
236
+ // Resolve linkpath relative to the entry's directory.
237
+ // `path.posix` is safe to use because we're operating on
238
+ // tar paths, not a filesystem.
239
+ const entryDir = path.posix.dirname(entry.path);
240
+ const resolved = path.posix.normalize(path.posix.join(entryDir, parts.join('/')));
241
+ // If the resolved path escapes (starts with ..), reject it
242
+ if (resolved.startsWith('../') || resolved === '..') {
243
+ this.warn('TAR_ENTRY_ERROR', `${field} escapes extraction directory`, {
244
+ entry,
245
+ [field]: p,
246
+ });
247
+ return false;
256
248
  }
257
249
  }
258
250
  if (root) {
@@ -298,12 +290,10 @@ export class Unpack extends Parser {
298
290
  !this[STRIPABSOLUTEPATH](entry, 'linkpath')) {
299
291
  return false;
300
292
  }
301
- if (path.isAbsolute(entry.path)) {
302
- entry.absolute = normalizeWindowsPath(path.resolve(entry.path));
303
- }
304
- else {
305
- entry.absolute = normalizeWindowsPath(path.resolve(this.cwd, entry.path));
306
- }
293
+ entry.absolute =
294
+ path.isAbsolute(entry.path) ?
295
+ normalizeWindowsPath(path.resolve(entry.path))
296
+ : normalizeWindowsPath(path.resolve(this.cwd, entry.path));
307
297
  // if we somehow ended up with a path that escapes the cwd, and we are
308
298
  // not in preservePaths mode, then something is fishy! This should have
309
299
  // been prevented above, so ignore this for coverage.
@@ -398,8 +388,7 @@ export class Unpack extends Parser {
398
388
  entry.uid !== this.processUid) ||
399
389
  (typeof entry.gid === 'number' &&
400
390
  entry.gid !== this.processGid))) ||
401
- (typeof this.uid === 'number' &&
402
- this.uid !== this.processUid) ||
391
+ (typeof this.uid === 'number' && this.uid !== this.processUid) ||
403
392
  (typeof this.gid === 'number' && this.gid !== this.processGid));
404
393
  }
405
394
  [UID](entry) {
@@ -409,9 +398,7 @@ export class Unpack extends Parser {
409
398
  return uint32(this.gid, entry.gid, this.processGid);
410
399
  }
411
400
  [FILE](entry, fullyDone) {
412
- const mode = typeof entry.mode === 'number' ?
413
- entry.mode & 0o7777
414
- : this.fmode;
401
+ const mode = typeof entry.mode === 'number' ? entry.mode & 0o7777 : this.fmode;
415
402
  const stream = new fsm.WriteStream(String(entry.absolute), {
416
403
  // slight lie, but it can be numeric flags
417
404
  flags: getWriteFlag(entry.size),
@@ -474,16 +461,14 @@ export class Unpack extends Parser {
474
461
  const uid = this[UID](entry);
475
462
  const gid = this[GID](entry);
476
463
  if (typeof uid === 'number' && typeof gid === 'number') {
477
- fs.fchown(fd, uid, gid, er => er ?
478
- fs.chown(abs, uid, gid, er2 => done(er2 && er))
479
- : done());
464
+ fs.fchown(fd, uid, gid, er => er ? fs.chown(abs, uid, gid, er2 => done(er2 && er)) : done());
480
465
  }
481
466
  }
482
467
  done();
483
468
  });
484
469
  const tx = this.transform ? this.transform(entry) || entry : entry;
485
470
  if (tx !== entry) {
486
- tx.on('error', (er) => {
471
+ tx.on('error', er => {
487
472
  this[ONERROR](er, entry);
488
473
  fullyDone();
489
474
  });
@@ -492,9 +477,7 @@ export class Unpack extends Parser {
492
477
  tx.pipe(stream);
493
478
  }
494
479
  [DIRECTORY](entry, fullyDone) {
495
- const mode = typeof entry.mode === 'number' ?
496
- entry.mode & 0o7777
497
- : this.dmode;
480
+ const mode = typeof entry.mode === 'number' ? entry.mode & 0o7777 : this.dmode;
498
481
  this[MKDIR](String(entry.absolute), mode, er => {
499
482
  if (er) {
500
483
  this[ONERROR](er, entry);
@@ -630,9 +613,7 @@ export class Unpack extends Parser {
630
613
  }
631
614
  if (st.isDirectory()) {
632
615
  if (entry.type === 'Directory') {
633
- const needChmod = this.chmod &&
634
- entry.mode &&
635
- (st.mode & 0o7777) !== entry.mode;
616
+ const needChmod = this.chmod && entry.mode && (st.mode & 0o7777) !== entry.mode;
636
617
  const afterChmod = (er) => this[MAKEFS](er ?? null, entry, done);
637
618
  if (!needChmod) {
638
619
  return afterChmod();
@@ -742,9 +723,7 @@ export class UnpackSync extends Unpack {
742
723
  }
743
724
  if (st.isDirectory()) {
744
725
  if (entry.type === 'Directory') {
745
- const needChmod = this.chmod &&
746
- entry.mode &&
747
- (st.mode & 0o7777) !== entry.mode;
726
+ const needChmod = this.chmod && entry.mode && (st.mode & 0o7777) !== entry.mode;
748
727
  const [er] = needChmod ?
749
728
  callSync(() => {
750
729
  fs.chmodSync(String(entry.absolute), Number(entry.mode));
@@ -764,9 +743,7 @@ export class UnpackSync extends Unpack {
764
743
  this[MAKEFS](er, entry);
765
744
  }
766
745
  [FILE](entry, done) {
767
- const mode = typeof entry.mode === 'number' ?
768
- entry.mode & 0o7777
769
- : this.fmode;
746
+ const mode = typeof entry.mode === 'number' ? entry.mode & 0o7777 : this.fmode;
770
747
  const oner = (er) => {
771
748
  let closeError;
772
749
  try {
@@ -794,7 +771,7 @@ export class UnpackSync extends Unpack {
794
771
  /* c8 ignore stop */
795
772
  const tx = this.transform ? this.transform(entry) || entry : entry;
796
773
  if (tx !== entry) {
797
- tx.on('error', (er) => this[ONERROR](er, entry));
774
+ tx.on('error', er => this[ONERROR](er, entry));
798
775
  entry.pipe(tx);
799
776
  }
800
777
  tx.on('data', (chunk) => {
@@ -819,7 +796,7 @@ export class UnpackSync extends Unpack {
819
796
  try {
820
797
  fs.utimesSync(String(entry.absolute), atime, mtime);
821
798
  }
822
- catch (utimeser) {
799
+ catch {
823
800
  er = futimeser;
824
801
  }
825
802
  }
@@ -834,7 +811,7 @@ export class UnpackSync extends Unpack {
834
811
  try {
835
812
  fs.chownSync(String(entry.absolute), Number(uid), Number(gid));
836
813
  }
837
- catch (chowner) {
814
+ catch {
838
815
  er = er || fchowner;
839
816
  }
840
817
  }
@@ -843,9 +820,7 @@ export class UnpackSync extends Unpack {
843
820
  });
844
821
  }
845
822
  [DIRECTORY](entry, done) {
846
- const mode = typeof entry.mode === 'number' ?
847
- entry.mode & 0o7777
848
- : this.dmode;
823
+ const mode = typeof entry.mode === 'number' ? entry.mode & 0o7777 : this.dmode;
849
824
  const er = this[MKDIR](String(entry.absolute), mode);
850
825
  if (er) {
851
826
  this[ONERROR](er, entry);
@@ -857,13 +832,13 @@ export class UnpackSync extends Unpack {
857
832
  fs.utimesSync(String(entry.absolute), entry.atime || new Date(), entry.mtime);
858
833
  /* c8 ignore next */
859
834
  }
860
- catch (er) { }
835
+ catch { }
861
836
  }
862
837
  if (this[DOCHOWN](entry)) {
863
838
  try {
864
839
  fs.chownSync(String(entry.absolute), Number(this[UID](entry)), Number(this[GID](entry)));
865
840
  }
866
- catch (er) { }
841
+ catch { }
867
842
  }
868
843
  done();
869
844
  entry.resume();
@@ -887,7 +862,7 @@ export class UnpackSync extends Unpack {
887
862
  }
888
863
  }
889
864
  [ENSURE_NO_SYMLINK](_entry, cwd, parts, done, onError) {
890
- if (this.preservePaths || !parts.length)
865
+ if (this.preservePaths || parts.length === 0)
891
866
  return done();
892
867
  let t = cwd;
893
868
  for (const p of parts) {
@@ -1,7 +1,7 @@
1
1
  // When writing files on Windows, translate the characters to their
2
2
  // 0xf000 higher-encoded versions.
3
3
  const raw = ['|', '<', '>', '?', ':'];
4
- const win = raw.map(char => String.fromCharCode(0xf000 + char.charCodeAt(0)));
4
+ const win = raw.map(char => String.fromCodePoint(0xf000 + Number(char.codePointAt(0))));
5
5
  const toWin = new Map(raw.map((char, i) => [char, win[i]]));
6
6
  const toRaw = new Map(win.map((char, i) => [char, raw[i]]));
7
7
  export const encode = (s) => raw.reduce((s, c) => s.split(c).join(toWin.get(c)), s);