@yarnpkg/fslib
Advanced tools
Comparing version 3.0.0-rc.15 to 3.0.0-rc.16
@@ -214,2 +214,4 @@ /// <reference types="node" /> | ||
abstract fchmodSync(fd: number, mask: number): void; | ||
abstract fchownPromise(fd: number, uid: number, gid: number): Promise<void>; | ||
abstract fchownSync(fd: number, uid: number, gid: number): void; | ||
abstract chownPromise(p: P, uid: number, gid: number): Promise<void>; | ||
@@ -216,0 +218,0 @@ abstract chownSync(p: P, uid: number, gid: number): void; |
@@ -106,2 +106,4 @@ /// <reference types="node" /> | ||
chmodSync(p: PortablePath, mask: number): void; | ||
fchownPromise(fd: number, uid: number, gid: number): Promise<void>; | ||
fchownSync(fd: number, uid: number, gid: number): void; | ||
chownPromise(p: PortablePath, uid: number, gid: number): Promise<void>; | ||
@@ -108,0 +110,0 @@ chownSync(p: PortablePath, uid: number, gid: number): void; |
@@ -198,2 +198,10 @@ "use strict"; | ||
} | ||
async fchownPromise(fd, uid, gid) { | ||
return await new Promise((resolve, reject) => { | ||
this.realFs.fchown(fd, uid, gid, this.makeCallback(resolve, reject)); | ||
}); | ||
} | ||
fchownSync(fd, uid, gid) { | ||
return this.realFs.fchownSync(fd, uid, gid); | ||
} | ||
async chownPromise(p, uid, gid) { | ||
@@ -200,0 +208,0 @@ return await new Promise((resolve, reject) => { |
@@ -39,2 +39,4 @@ import { FakeFS } from './FakeFS'; | ||
chmodSync(): never; | ||
fchownPromise(): Promise<never>; | ||
fchownSync(): never; | ||
chownPromise(): Promise<never>; | ||
@@ -41,0 +43,0 @@ chownSync(): never; |
@@ -110,2 +110,8 @@ "use strict"; | ||
} | ||
async fchownPromise() { | ||
throw makeError(); | ||
} | ||
fchownSync() { | ||
throw makeError(); | ||
} | ||
async chownPromise() { | ||
@@ -112,0 +118,0 @@ throw makeError(); |
@@ -36,5 +36,10 @@ "use strict"; | ||
} | ||
// FIXME: Missing FakeFS version | ||
chown(uid, gid) { | ||
throw new Error(`Method not implemented.`); | ||
async chown(uid, gid) { | ||
try { | ||
this[kRef](this.chown); | ||
return await this[kBaseFs].fchownPromise(this.fd, uid, gid); | ||
} | ||
finally { | ||
this[kUnref](); | ||
} | ||
} | ||
@@ -41,0 +46,0 @@ async chmod(mode) { |
@@ -15,2 +15,3 @@ "use strict"; | ||
`chownSync`, | ||
`fchownSync`, | ||
`closeSync`, | ||
@@ -49,2 +50,3 @@ `copyFileSync`, | ||
`chmodPromise`, | ||
`fchownPromise`, | ||
`chownPromise`, | ||
@@ -51,0 +53,0 @@ `closePromise`, |
@@ -112,2 +112,4 @@ /// <reference types="node" /> | ||
chmodSync(p: P, mask: number): void; | ||
fchownPromise(fd: number, uid: number, gid: number): Promise<void>; | ||
fchownSync(fd: number, uid: number, gid: number): void; | ||
chownPromise(p: P, uid: number, gid: number): Promise<void>; | ||
@@ -114,0 +116,0 @@ chownSync(p: P, uid: number, gid: number): void; |
@@ -109,2 +109,8 @@ "use strict"; | ||
} | ||
async fchownPromise(fd, uid, gid) { | ||
return this.baseFs.fchownPromise(fd, uid, gid); | ||
} | ||
fchownSync(fd, uid, gid) { | ||
return this.baseFs.fchownSync(fd, uid, gid); | ||
} | ||
async chownPromise(p, uid, gid) { | ||
@@ -111,0 +117,0 @@ return this.baseFs.chownPromise(this.mapToBase(p), uid, gid); |
@@ -170,2 +170,4 @@ /// <reference types="node" /> | ||
chmodSync(p: PortablePath, mask: number): void; | ||
fchownPromise(fd: number, uid: number, gid: number): Promise<void>; | ||
fchownSync(fd: number, uid: number, gid: number): void; | ||
chownPromise(p: PortablePath, uid: number, gid: number): Promise<void>; | ||
@@ -172,0 +174,0 @@ chownSync(p: PortablePath, uid: number, gid: number): void; |
@@ -793,2 +793,8 @@ "use strict"; | ||
} | ||
async fchownPromise(fd, uid, gid) { | ||
return this.chownPromise(this.fdToPath(fd, `fchown`), uid, gid); | ||
} | ||
fchownSync(fd, uid, gid) { | ||
return this.chownSync(this.fdToPath(fd, `fchownSync`), uid, gid); | ||
} | ||
async chownPromise(p, uid, gid) { | ||
@@ -795,0 +801,0 @@ return this.chownSync(p, uid, gid); |
@@ -1,11 +0,5 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import { Libzip } from '@yarnpkg/libzip'; | ||
import { BigIntStats, Stats } from 'fs'; | ||
import { WatchOptions, WatchCallback, Watcher, StatOptions, StatSyncOptions } from './FakeFS'; | ||
import { FakeFS, MkdirOptions, RmdirOptions, WriteFileOptions, OpendirOptions } from './FakeFS'; | ||
import { Dirent, SymlinkType } from './FakeFS'; | ||
import { CreateReadStreamOptions, CreateWriteStreamOptions, BasePortableFakeFS, ExtractHintOptions, WatchFileOptions, WatchFileCallback, StatWatcher } from './FakeFS'; | ||
import { Filename, FSPath, PortablePath } from './path'; | ||
import { MountFS, MountFSOptions } from './MountFS'; | ||
import { ZipFS } from './ZipFS'; | ||
import { PortablePath } from './path'; | ||
/** | ||
@@ -16,16 +10,7 @@ * Extracts the archive part (ending in the first instance of `extension`) from a path. | ||
*/ | ||
export declare const getArchivePart: (path: string, extension: string) => PortablePath | null; | ||
export declare type ZipOpenFSOptions = { | ||
baseFs?: FakeFS<PortablePath>; | ||
filter?: RegExp | null; | ||
export declare function getArchivePart(path: string, extension: string): PortablePath | null; | ||
export declare type ZipOpenFSOptions = Omit<MountFSOptions<ZipFS>, `factoryPromise` | `factorySync` | `getMountPoint`> & { | ||
libzip: Libzip | (() => Libzip); | ||
maxOpenFiles?: number; | ||
readOnlyArchives?: boolean; | ||
useCache?: boolean; | ||
/** | ||
* Maximum age in ms. | ||
* ZipFS instances are pruned from the cache if they aren't accessed within this amount of time. | ||
*/ | ||
maxAge?: number; | ||
/** | ||
* Which file extensions will be interpreted as zip files. Useful for supporting other formats | ||
@@ -38,183 +23,5 @@ * packaged as zips, such as .docx. | ||
}; | ||
export declare class ZipOpenFS extends BasePortableFakeFS { | ||
export declare class ZipOpenFS extends MountFS<ZipFS> { | ||
static openPromise<T>(fn: (zipOpenFs: ZipOpenFS) => Promise<T>, opts: ZipOpenFSOptions): Promise<T>; | ||
private libzipFactory; | ||
private libzipInstance?; | ||
private get libzip(); | ||
private readonly baseFs; | ||
private readonly zipInstances; | ||
private readonly fdMap; | ||
private nextFd; | ||
private readonly filter; | ||
private readonly maxOpenFiles; | ||
private readonly maxAge; | ||
private readonly readOnlyArchives; | ||
private readonly fileExtensions; | ||
private isZip; | ||
private notZip; | ||
private realPaths; | ||
constructor({ libzip, baseFs, filter, maxOpenFiles, readOnlyArchives, useCache, maxAge, fileExtensions }: ZipOpenFSOptions); | ||
getExtractHint(hints: ExtractHintOptions): boolean; | ||
getRealPath(): PortablePath; | ||
saveAndClose(): void; | ||
discardAndClose(): void; | ||
resolve(p: PortablePath): PortablePath; | ||
private remapFd; | ||
openPromise(p: PortablePath, flags: string, mode?: number): Promise<number>; | ||
openSync(p: PortablePath, flags: string, mode?: number): number; | ||
opendirPromise(p: PortablePath, opts?: OpendirOptions): Promise<import("./FakeFS").Dir<PortablePath>>; | ||
opendirSync(p: PortablePath, opts?: OpendirOptions): import("./FakeFS").Dir<PortablePath>; | ||
readPromise(fd: number, buffer: Buffer, offset: number, length: number, position: number): Promise<number>; | ||
readSync(fd: number, buffer: Buffer, offset: number, length: number, position: number): number; | ||
writePromise(fd: number, buffer: Buffer, offset?: number, length?: number, position?: number): Promise<number>; | ||
writePromise(fd: number, buffer: string, position?: number): Promise<number>; | ||
writeSync(fd: number, buffer: Buffer, offset?: number, length?: number, position?: number): number; | ||
writeSync(fd: number, buffer: string, position?: number): number; | ||
closePromise(fd: number): Promise<void>; | ||
closeSync(fd: number): void; | ||
createReadStream(p: PortablePath | null, opts?: CreateReadStreamOptions): import("fs").ReadStream; | ||
createWriteStream(p: PortablePath | null, opts?: CreateWriteStreamOptions): import("fs").WriteStream; | ||
realpathPromise(p: PortablePath): Promise<PortablePath>; | ||
realpathSync(p: PortablePath): PortablePath; | ||
existsPromise(p: PortablePath): Promise<boolean>; | ||
existsSync(p: PortablePath): boolean; | ||
accessPromise(p: PortablePath, mode?: number): Promise<void>; | ||
accessSync(p: PortablePath, mode?: number): void; | ||
statPromise(p: PortablePath): Promise<Stats>; | ||
statPromise(p: PortablePath, opts: (StatOptions & { | ||
bigint?: false | undefined; | ||
}) | undefined): Promise<Stats>; | ||
statPromise(p: PortablePath, opts: StatOptions & { | ||
bigint: true; | ||
}): Promise<BigIntStats>; | ||
statPromise(p: PortablePath, opts?: StatOptions): Promise<Stats | BigIntStats>; | ||
statSync(p: PortablePath): Stats; | ||
statSync(p: PortablePath, opts?: StatSyncOptions & { | ||
bigint?: false | undefined; | ||
throwIfNoEntry: false; | ||
}): Stats | undefined; | ||
statSync(p: PortablePath, opts: StatSyncOptions & { | ||
bigint: true; | ||
throwIfNoEntry: false; | ||
}): BigIntStats | undefined; | ||
statSync(p: PortablePath, opts?: StatSyncOptions & { | ||
bigint?: false | undefined; | ||
}): Stats; | ||
statSync(p: PortablePath, opts: StatSyncOptions & { | ||
bigint: true; | ||
}): BigIntStats; | ||
statSync(p: PortablePath, opts: StatSyncOptions & { | ||
bigint: boolean; | ||
throwIfNoEntry?: false | undefined; | ||
}): Stats | BigIntStats; | ||
fstatPromise(fd: number): Promise<Stats>; | ||
fstatPromise(fd: number, opts: { | ||
bigint: true; | ||
}): Promise<BigIntStats>; | ||
fstatPromise(fd: number, opts?: { | ||
bigint: boolean; | ||
}): Promise<BigIntStats | Stats>; | ||
fstatSync(fd: number): Stats; | ||
fstatSync(fd: number, opts: { | ||
bigint: true; | ||
}): BigIntStats; | ||
fstatSync(fd: number, opts?: { | ||
bigint: boolean; | ||
}): BigIntStats | Stats; | ||
lstatPromise(p: PortablePath): Promise<Stats>; | ||
lstatPromise(p: PortablePath, opts: (StatOptions & { | ||
bigint?: false | undefined; | ||
}) | undefined): Promise<Stats>; | ||
lstatPromise(p: PortablePath, opts: StatOptions & { | ||
bigint: true; | ||
}): Promise<BigIntStats>; | ||
lstatSync(p: PortablePath): Stats; | ||
lstatSync(p: PortablePath, opts?: StatSyncOptions & { | ||
bigint?: false | undefined; | ||
throwIfNoEntry: false; | ||
}): Stats | undefined; | ||
lstatSync(p: PortablePath, opts: StatSyncOptions & { | ||
bigint: true; | ||
throwIfNoEntry: false; | ||
}): BigIntStats | undefined; | ||
lstatSync(p: PortablePath, opts?: StatSyncOptions & { | ||
bigint?: false | undefined; | ||
}): Stats; | ||
lstatSync(p: PortablePath, opts: StatSyncOptions & { | ||
bigint: true; | ||
}): BigIntStats; | ||
lstatSync(p: PortablePath, opts: StatSyncOptions & { | ||
bigint: boolean; | ||
throwIfNoEntry?: false | undefined; | ||
}): Stats | BigIntStats; | ||
fchmodPromise(fd: number, mask: number): Promise<void>; | ||
fchmodSync(fd: number, mask: number): void; | ||
chmodPromise(p: PortablePath, mask: number): Promise<void>; | ||
chmodSync(p: PortablePath, mask: number): void; | ||
chownPromise(p: PortablePath, uid: number, gid: number): Promise<void>; | ||
chownSync(p: PortablePath, uid: number, gid: number): void; | ||
renamePromise(oldP: PortablePath, newP: PortablePath): Promise<void>; | ||
renameSync(oldP: PortablePath, newP: PortablePath): void; | ||
copyFilePromise(sourceP: PortablePath, destP: PortablePath, flags?: number): Promise<void>; | ||
copyFileSync(sourceP: PortablePath, destP: PortablePath, flags?: number): void; | ||
appendFilePromise(p: FSPath<PortablePath>, content: string | Uint8Array, opts?: WriteFileOptions): Promise<void>; | ||
appendFileSync(p: FSPath<PortablePath>, content: string | Uint8Array, opts?: WriteFileOptions): void; | ||
writeFilePromise(p: FSPath<PortablePath>, content: string | NodeJS.ArrayBufferView, opts?: WriteFileOptions): Promise<void>; | ||
writeFileSync(p: FSPath<PortablePath>, content: string | NodeJS.ArrayBufferView, opts?: WriteFileOptions): void; | ||
unlinkPromise(p: PortablePath): Promise<void>; | ||
unlinkSync(p: PortablePath): void; | ||
utimesPromise(p: PortablePath, atime: Date | string | number, mtime: Date | string | number): Promise<void>; | ||
utimesSync(p: PortablePath, atime: Date | string | number, mtime: Date | string | number): void; | ||
mkdirPromise(p: PortablePath, opts?: MkdirOptions): Promise<string | undefined>; | ||
mkdirSync(p: PortablePath, opts?: MkdirOptions): string | undefined; | ||
rmdirPromise(p: PortablePath, opts?: RmdirOptions): Promise<void>; | ||
rmdirSync(p: PortablePath, opts?: RmdirOptions): void; | ||
linkPromise(existingP: PortablePath, newP: PortablePath): Promise<void>; | ||
linkSync(existingP: PortablePath, newP: PortablePath): void; | ||
symlinkPromise(target: PortablePath, p: PortablePath, type?: SymlinkType): Promise<void>; | ||
symlinkSync(target: PortablePath, p: PortablePath, type?: SymlinkType): void; | ||
readFilePromise(p: FSPath<PortablePath>, encoding?: null): Promise<Buffer>; | ||
readFilePromise(p: FSPath<PortablePath>, encoding: BufferEncoding): Promise<string>; | ||
readFilePromise(p: FSPath<PortablePath>, encoding?: BufferEncoding | null): Promise<Buffer | string>; | ||
readFileSync(p: FSPath<PortablePath>, encoding?: null): Buffer; | ||
readFileSync(p: FSPath<PortablePath>, encoding: BufferEncoding): string; | ||
readFileSync(p: FSPath<PortablePath>, encoding?: BufferEncoding | null): Buffer | string; | ||
readdirPromise(p: PortablePath): Promise<Array<Filename>>; | ||
readdirPromise(p: PortablePath, opts: { | ||
withFileTypes: false; | ||
} | null): Promise<Array<Filename>>; | ||
readdirPromise(p: PortablePath, opts: { | ||
withFileTypes: true; | ||
}): Promise<Array<Dirent>>; | ||
readdirPromise(p: PortablePath, opts: { | ||
withFileTypes: boolean; | ||
}): Promise<Array<Filename> | Array<Dirent>>; | ||
readdirSync(p: PortablePath): Array<Filename>; | ||
readdirSync(p: PortablePath, opts: { | ||
withFileTypes: false; | ||
} | null): Array<Filename>; | ||
readdirSync(p: PortablePath, opts: { | ||
withFileTypes: true; | ||
}): Array<Dirent>; | ||
readdirSync(p: PortablePath, opts: { | ||
withFileTypes: boolean; | ||
}): Array<Filename> | Array<Dirent>; | ||
readlinkPromise(p: PortablePath): Promise<PortablePath>; | ||
readlinkSync(p: PortablePath): PortablePath; | ||
truncatePromise(p: PortablePath, len?: number): Promise<void>; | ||
truncateSync(p: PortablePath, len?: number): void; | ||
ftruncatePromise(fd: number, len?: number): Promise<void>; | ||
ftruncateSync(fd: number, len?: number): void; | ||
watch(p: PortablePath, cb?: WatchCallback): Watcher; | ||
watch(p: PortablePath, opts: WatchOptions, cb?: WatchCallback): Watcher; | ||
watchFile(p: PortablePath, cb: WatchFileCallback): StatWatcher; | ||
watchFile(p: PortablePath, opts: WatchFileOptions, cb: WatchFileCallback): StatWatcher; | ||
unwatchFile(p: PortablePath, cb?: WatchFileCallback): void; | ||
private makeCallPromise; | ||
private makeCallSync; | ||
private findZip; | ||
private limitOpenFilesTimeout; | ||
private limitOpenFiles; | ||
private getZipPromise; | ||
private getZipSync; | ||
constructor(opts: ZipOpenFSOptions); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ZipOpenFS = exports.getArchivePart = void 0; | ||
const tslib_1 = require("tslib"); | ||
const fs_1 = require("fs"); | ||
const FakeFS_1 = require("./FakeFS"); | ||
const NodeFS_1 = require("./NodeFS"); | ||
const MountFS_1 = require("./MountFS"); | ||
const ZipFS_1 = require("./ZipFS"); | ||
const watchFile_1 = require("./algorithms/watchFile"); | ||
const errors = tslib_1.__importStar(require("./errors")); | ||
const path_1 = require("./path"); | ||
// Only file descriptors prefixed by those values will be forwarded to the ZipFS | ||
// instances. Note that the highest ZIP_MAGIC bit MUST NOT be set, otherwise the | ||
// resulting fd becomes a negative integer, which isn't supposed to happen per | ||
// the unix rules (caused problems w/ Go). | ||
// | ||
// Those values must be synced with packages/yarnpkg-pnp/sources/esm-loader/fspatch.ts | ||
// | ||
const ZIP_MASK = 0xff000000; | ||
const ZIP_MAGIC = 0x2a000000; | ||
/** | ||
@@ -26,3 +12,3 @@ * Extracts the archive part (ending in the first instance of `extension`) from a path. | ||
*/ | ||
const getArchivePart = (path, extension) => { | ||
function getArchivePart(path, extension) { | ||
let idx = path.indexOf(extension); | ||
@@ -45,24 +31,5 @@ if (idx <= 0) | ||
return path.slice(0, nextCharIdx); | ||
}; | ||
} | ||
exports.getArchivePart = getArchivePart; | ||
class ZipOpenFS extends FakeFS_1.BasePortableFakeFS { | ||
constructor({ libzip, baseFs = new NodeFS_1.NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true, maxAge = 5000, fileExtensions = null }) { | ||
super(); | ||
this.fdMap = new Map(); | ||
this.nextFd = 3; | ||
this.isZip = new Set(); | ||
this.notZip = new Set(); | ||
this.realPaths = new Map(); | ||
this.limitOpenFilesTimeout = null; | ||
this.libzipFactory = typeof libzip !== `function` | ||
? () => libzip | ||
: libzip; | ||
this.baseFs = baseFs; | ||
this.zipInstances = useCache ? new Map() : null; | ||
this.filter = filter; | ||
this.maxOpenFiles = maxOpenFiles; | ||
this.readOnlyArchives = readOnlyArchives; | ||
this.maxAge = maxAge; | ||
this.fileExtensions = fileExtensions; | ||
} | ||
class ZipOpenFS extends MountFS_1.MountFS { | ||
static async openPromise(fn, opts) { | ||
@@ -77,816 +44,52 @@ const zipOpenFs = new ZipOpenFS(opts); | ||
} | ||
get libzip() { | ||
if (typeof this.libzipInstance === `undefined`) | ||
this.libzipInstance = this.libzipFactory(); | ||
return this.libzipInstance; | ||
} | ||
getExtractHint(hints) { | ||
return this.baseFs.getExtractHint(hints); | ||
} | ||
getRealPath() { | ||
return this.baseFs.getRealPath(); | ||
} | ||
saveAndClose() { | ||
(0, watchFile_1.unwatchAllFiles)(this); | ||
if (this.zipInstances) { | ||
for (const [path, { zipFs }] of this.zipInstances.entries()) { | ||
zipFs.saveAndClose(); | ||
this.zipInstances.delete(path); | ||
} | ||
} | ||
} | ||
discardAndClose() { | ||
(0, watchFile_1.unwatchAllFiles)(this); | ||
if (this.zipInstances) { | ||
for (const [path, { zipFs }] of this.zipInstances.entries()) { | ||
zipFs.discardAndClose(); | ||
this.zipInstances.delete(path); | ||
} | ||
} | ||
} | ||
resolve(p) { | ||
return this.baseFs.resolve(p); | ||
} | ||
remapFd(zipFs, fd) { | ||
const remappedFd = this.nextFd++ | ZIP_MAGIC; | ||
this.fdMap.set(remappedFd, [zipFs, fd]); | ||
return remappedFd; | ||
} | ||
async openPromise(p, flags, mode) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.openPromise(p, flags, mode); | ||
}, async (zipFs, { subPath }) => { | ||
return this.remapFd(zipFs, await zipFs.openPromise(subPath, flags, mode)); | ||
}); | ||
} | ||
openSync(p, flags, mode) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.openSync(p, flags, mode); | ||
}, (zipFs, { subPath }) => { | ||
return this.remapFd(zipFs, zipFs.openSync(subPath, flags, mode)); | ||
}); | ||
} | ||
async opendirPromise(p, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.opendirPromise(p, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.opendirPromise(subPath, opts); | ||
}, { | ||
requireSubpath: false, | ||
}); | ||
} | ||
opendirSync(p, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.opendirSync(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.opendirSync(subPath, opts); | ||
}, { | ||
requireSubpath: false, | ||
}); | ||
} | ||
async readPromise(fd, buffer, offset, length, position) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return await this.baseFs.readPromise(fd, buffer, offset, length, position); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`read`); | ||
const [zipFs, realFd] = entry; | ||
return await zipFs.readPromise(realFd, buffer, offset, length, position); | ||
} | ||
readSync(fd, buffer, offset, length, position) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.readSync(fd, buffer, offset, length, position); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`readSync`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.readSync(realFd, buffer, offset, length, position); | ||
} | ||
async writePromise(fd, buffer, offset, length, position) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) { | ||
if (typeof buffer === `string`) { | ||
return await this.baseFs.writePromise(fd, buffer, offset); | ||
} | ||
else { | ||
return await this.baseFs.writePromise(fd, buffer, offset, length, position); | ||
} | ||
} | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`write`); | ||
const [zipFs, realFd] = entry; | ||
if (typeof buffer === `string`) { | ||
return await zipFs.writePromise(realFd, buffer, offset); | ||
} | ||
else { | ||
return await zipFs.writePromise(realFd, buffer, offset, length, position); | ||
} | ||
} | ||
writeSync(fd, buffer, offset, length, position) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) { | ||
if (typeof buffer === `string`) { | ||
return this.baseFs.writeSync(fd, buffer, offset); | ||
} | ||
else { | ||
return this.baseFs.writeSync(fd, buffer, offset, length, position); | ||
} | ||
} | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`writeSync`); | ||
const [zipFs, realFd] = entry; | ||
if (typeof buffer === `string`) { | ||
return zipFs.writeSync(realFd, buffer, offset); | ||
} | ||
else { | ||
return zipFs.writeSync(realFd, buffer, offset, length, position); | ||
} | ||
} | ||
async closePromise(fd) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return await this.baseFs.closePromise(fd); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`close`); | ||
this.fdMap.delete(fd); | ||
const [zipFs, realFd] = entry; | ||
return await zipFs.closePromise(realFd); | ||
} | ||
closeSync(fd) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.closeSync(fd); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`closeSync`); | ||
this.fdMap.delete(fd); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.closeSync(realFd); | ||
} | ||
createReadStream(p, opts) { | ||
if (p === null) | ||
return this.baseFs.createReadStream(p, opts); | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.createReadStream(p, opts); | ||
}, (zipFs, { archivePath, subPath }) => { | ||
const stream = zipFs.createReadStream(subPath, opts); | ||
// This is a very hacky workaround. `ZipOpenFS` shouldn't have to work with `NativePath`s. | ||
// Ref: https://github.com/yarnpkg/berry/pull/3774 | ||
// TODO: think of a better solution | ||
stream.path = path_1.npath.fromPortablePath(this.pathUtils.join(archivePath, subPath)); | ||
return stream; | ||
}); | ||
} | ||
createWriteStream(p, opts) { | ||
if (p === null) | ||
return this.baseFs.createWriteStream(p, opts); | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.createWriteStream(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.createWriteStream(subPath, opts); | ||
}); | ||
} | ||
async realpathPromise(p) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.realpathPromise(p); | ||
}, async (zipFs, { archivePath, subPath }) => { | ||
let realArchivePath = this.realPaths.get(archivePath); | ||
if (typeof realArchivePath === `undefined`) { | ||
realArchivePath = await this.baseFs.realpathPromise(archivePath); | ||
this.realPaths.set(archivePath, realArchivePath); | ||
} | ||
return this.pathUtils.join(realArchivePath, this.pathUtils.relative(path_1.PortablePath.root, await zipFs.realpathPromise(subPath))); | ||
}); | ||
} | ||
realpathSync(p) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.realpathSync(p); | ||
}, (zipFs, { archivePath, subPath }) => { | ||
let realArchivePath = this.realPaths.get(archivePath); | ||
if (typeof realArchivePath === `undefined`) { | ||
realArchivePath = this.baseFs.realpathSync(archivePath); | ||
this.realPaths.set(archivePath, realArchivePath); | ||
} | ||
return this.pathUtils.join(realArchivePath, this.pathUtils.relative(path_1.PortablePath.root, zipFs.realpathSync(subPath))); | ||
}); | ||
} | ||
async existsPromise(p) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.existsPromise(p); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.existsPromise(subPath); | ||
}); | ||
} | ||
existsSync(p) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.existsSync(p); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.existsSync(subPath); | ||
}); | ||
} | ||
async accessPromise(p, mode) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.accessPromise(p, mode); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.accessPromise(subPath, mode); | ||
}); | ||
} | ||
accessSync(p, mode) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.accessSync(p, mode); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.accessSync(subPath, mode); | ||
}); | ||
} | ||
async statPromise(p, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.statPromise(p, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.statPromise(subPath, opts); | ||
}); | ||
} | ||
statSync(p, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.statSync(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.statSync(subPath, opts); | ||
}); | ||
} | ||
async fstatPromise(fd, opts) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.fstatPromise(fd, opts); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`fstat`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.fstatPromise(realFd, opts); | ||
} | ||
fstatSync(fd, opts) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.fstatSync(fd, opts); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`fstatSync`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.fstatSync(realFd, opts); | ||
} | ||
async lstatPromise(p, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.lstatPromise(p, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.lstatPromise(subPath, opts); | ||
}); | ||
} | ||
lstatSync(p, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.lstatSync(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.lstatSync(subPath, opts); | ||
}); | ||
} | ||
async fchmodPromise(fd, mask) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.fchmodPromise(fd, mask); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`fchmod`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.fchmodPromise(realFd, mask); | ||
} | ||
fchmodSync(fd, mask) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.fchmodSync(fd, mask); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`fchmodSync`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.fchmodSync(realFd, mask); | ||
} | ||
async chmodPromise(p, mask) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.chmodPromise(p, mask); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.chmodPromise(subPath, mask); | ||
}); | ||
} | ||
chmodSync(p, mask) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.chmodSync(p, mask); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.chmodSync(subPath, mask); | ||
}); | ||
} | ||
async chownPromise(p, uid, gid) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.chownPromise(p, uid, gid); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.chownPromise(subPath, uid, gid); | ||
}); | ||
} | ||
chownSync(p, uid, gid) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.chownSync(p, uid, gid); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.chownSync(subPath, uid, gid); | ||
}); | ||
} | ||
async renamePromise(oldP, newP) { | ||
return await this.makeCallPromise(oldP, async () => { | ||
return await this.makeCallPromise(newP, async () => { | ||
return await this.baseFs.renamePromise(oldP, newP); | ||
}, async () => { | ||
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); | ||
}); | ||
}, async (zipFsO, { subPath: subPathO }) => { | ||
return await this.makeCallPromise(newP, async () => { | ||
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); | ||
}, async (zipFsN, { subPath: subPathN }) => { | ||
if (zipFsO !== zipFsN) { | ||
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); | ||
} | ||
else { | ||
return await zipFsO.renamePromise(subPathO, subPathN); | ||
} | ||
}); | ||
}); | ||
} | ||
renameSync(oldP, newP) { | ||
return this.makeCallSync(oldP, () => { | ||
return this.makeCallSync(newP, () => { | ||
return this.baseFs.renameSync(oldP, newP); | ||
}, () => { | ||
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); | ||
}); | ||
}, (zipFsO, { subPath: subPathO }) => { | ||
return this.makeCallSync(newP, () => { | ||
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); | ||
}, (zipFsN, { subPath: subPathN }) => { | ||
if (zipFsO !== zipFsN) { | ||
throw Object.assign(new Error(`EEXDEV: cross-device link not permitted`), { code: `EEXDEV` }); | ||
} | ||
else { | ||
return zipFsO.renameSync(subPathO, subPathN); | ||
} | ||
}); | ||
}); | ||
} | ||
async copyFilePromise(sourceP, destP, flags = 0) { | ||
const fallback = async (sourceFs, sourceP, destFs, destP) => { | ||
if ((flags & fs_1.constants.COPYFILE_FICLONE_FORCE) !== 0) | ||
throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), { code: `EXDEV` }); | ||
if ((flags & fs_1.constants.COPYFILE_EXCL) && await this.existsPromise(sourceP)) | ||
throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), { code: `EEXIST` }); | ||
let content; | ||
try { | ||
content = await sourceFs.readFilePromise(sourceP); | ||
} | ||
catch (error) { | ||
throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), { code: `EINVAL` }); | ||
} | ||
await destFs.writeFilePromise(destP, content); | ||
constructor(opts) { | ||
let libzipInstance; | ||
const libzipFactory = typeof opts.libzip !== `function` | ||
? () => opts.libzip | ||
: opts.libzip; | ||
const getLibzip = () => { | ||
if (typeof libzipInstance === `undefined`) | ||
libzipInstance = libzipFactory(); | ||
return libzipInstance; | ||
}; | ||
return await this.makeCallPromise(sourceP, async () => { | ||
return await this.makeCallPromise(destP, async () => { | ||
return await this.baseFs.copyFilePromise(sourceP, destP, flags); | ||
}, async (zipFsD, { subPath: subPathD }) => { | ||
return await fallback(this.baseFs, sourceP, zipFsD, subPathD); | ||
}); | ||
}, async (zipFsS, { subPath: subPathS }) => { | ||
return await this.makeCallPromise(destP, async () => { | ||
return await fallback(zipFsS, subPathS, this.baseFs, destP); | ||
}, async (zipFsD, { subPath: subPathD }) => { | ||
if (zipFsS !== zipFsD) { | ||
return await fallback(zipFsS, subPathS, zipFsD, subPathD); | ||
} | ||
else { | ||
return await zipFsS.copyFilePromise(subPathS, subPathD, flags); | ||
} | ||
}); | ||
}); | ||
} | ||
copyFileSync(sourceP, destP, flags = 0) { | ||
const fallback = (sourceFs, sourceP, destFs, destP) => { | ||
if ((flags & fs_1.constants.COPYFILE_FICLONE_FORCE) !== 0) | ||
throw Object.assign(new Error(`EXDEV: cross-device clone not permitted, copyfile '${sourceP}' -> ${destP}'`), { code: `EXDEV` }); | ||
if ((flags & fs_1.constants.COPYFILE_EXCL) && this.existsSync(sourceP)) | ||
throw Object.assign(new Error(`EEXIST: file already exists, copyfile '${sourceP}' -> '${destP}'`), { code: `EEXIST` }); | ||
let content; | ||
try { | ||
content = sourceFs.readFileSync(sourceP); | ||
} | ||
catch (error) { | ||
throw Object.assign(new Error(`EINVAL: invalid argument, copyfile '${sourceP}' -> '${destP}'`), { code: `EINVAL` }); | ||
} | ||
destFs.writeFileSync(destP, content); | ||
}; | ||
return this.makeCallSync(sourceP, () => { | ||
return this.makeCallSync(destP, () => { | ||
return this.baseFs.copyFileSync(sourceP, destP, flags); | ||
}, (zipFsD, { subPath: subPathD }) => { | ||
return fallback(this.baseFs, sourceP, zipFsD, subPathD); | ||
}); | ||
}, (zipFsS, { subPath: subPathS }) => { | ||
return this.makeCallSync(destP, () => { | ||
return fallback(zipFsS, subPathS, this.baseFs, destP); | ||
}, (zipFsD, { subPath: subPathD }) => { | ||
if (zipFsS !== zipFsD) { | ||
return fallback(zipFsS, subPathS, zipFsD, subPathD); | ||
} | ||
else { | ||
return zipFsS.copyFileSync(subPathS, subPathD, flags); | ||
} | ||
}); | ||
}); | ||
} | ||
async appendFilePromise(p, content, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.appendFilePromise(p, content, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.appendFilePromise(subPath, content, opts); | ||
}); | ||
} | ||
appendFileSync(p, content, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.appendFileSync(p, content, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.appendFileSync(subPath, content, opts); | ||
}); | ||
} | ||
async writeFilePromise(p, content, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.writeFilePromise(p, content, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.writeFilePromise(subPath, content, opts); | ||
}); | ||
} | ||
writeFileSync(p, content, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.writeFileSync(p, content, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.writeFileSync(subPath, content, opts); | ||
}); | ||
} | ||
async unlinkPromise(p) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.unlinkPromise(p); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.unlinkPromise(subPath); | ||
}); | ||
} | ||
unlinkSync(p) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.unlinkSync(p); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.unlinkSync(subPath); | ||
}); | ||
} | ||
async utimesPromise(p, atime, mtime) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.utimesPromise(p, atime, mtime); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.utimesPromise(subPath, atime, mtime); | ||
}); | ||
} | ||
utimesSync(p, atime, mtime) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.utimesSync(p, atime, mtime); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.utimesSync(subPath, atime, mtime); | ||
}); | ||
} | ||
async mkdirPromise(p, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.mkdirPromise(p, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.mkdirPromise(subPath, opts); | ||
}); | ||
} | ||
mkdirSync(p, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.mkdirSync(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.mkdirSync(subPath, opts); | ||
}); | ||
} | ||
async rmdirPromise(p, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.rmdirPromise(p, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.rmdirPromise(subPath, opts); | ||
}); | ||
} | ||
rmdirSync(p, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.rmdirSync(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.rmdirSync(subPath, opts); | ||
}); | ||
} | ||
async linkPromise(existingP, newP) { | ||
return await this.makeCallPromise(newP, async () => { | ||
return await this.baseFs.linkPromise(existingP, newP); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.linkPromise(existingP, subPath); | ||
}); | ||
} | ||
linkSync(existingP, newP) { | ||
return this.makeCallSync(newP, () => { | ||
return this.baseFs.linkSync(existingP, newP); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.linkSync(existingP, subPath); | ||
}); | ||
} | ||
async symlinkPromise(target, p, type) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.symlinkPromise(target, p, type); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.symlinkPromise(target, subPath); | ||
}); | ||
} | ||
symlinkSync(target, p, type) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.symlinkSync(target, p, type); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.symlinkSync(target, subPath); | ||
}); | ||
} | ||
async readFilePromise(p, encoding) { | ||
return this.makeCallPromise(p, async () => { | ||
return await this.baseFs.readFilePromise(p, encoding); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.readFilePromise(subPath, encoding); | ||
}); | ||
} | ||
readFileSync(p, encoding) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.readFileSync(p, encoding); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.readFileSync(subPath, encoding); | ||
}); | ||
} | ||
async readdirPromise(p, opts) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.readdirPromise(p, opts); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.readdirPromise(subPath, opts); | ||
}, { | ||
requireSubpath: false, | ||
}); | ||
} | ||
readdirSync(p, opts) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.readdirSync(p, opts); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.readdirSync(subPath, opts); | ||
}, { | ||
requireSubpath: false, | ||
}); | ||
} | ||
async readlinkPromise(p) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.readlinkPromise(p); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.readlinkPromise(subPath); | ||
}); | ||
} | ||
readlinkSync(p) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.readlinkSync(p); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.readlinkSync(subPath); | ||
}); | ||
} | ||
async truncatePromise(p, len) { | ||
return await this.makeCallPromise(p, async () => { | ||
return await this.baseFs.truncatePromise(p, len); | ||
}, async (zipFs, { subPath }) => { | ||
return await zipFs.truncatePromise(subPath, len); | ||
}); | ||
} | ||
truncateSync(p, len) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.truncateSync(p, len); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.truncateSync(subPath, len); | ||
}); | ||
} | ||
async ftruncatePromise(fd, len) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.ftruncatePromise(fd, len); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`ftruncate`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.ftruncatePromise(realFd, len); | ||
} | ||
ftruncateSync(fd, len) { | ||
if ((fd & ZIP_MASK) !== ZIP_MAGIC) | ||
return this.baseFs.ftruncateSync(fd, len); | ||
const entry = this.fdMap.get(fd); | ||
if (typeof entry === `undefined`) | ||
throw errors.EBADF(`ftruncateSync`); | ||
const [zipFs, realFd] = entry; | ||
return zipFs.ftruncateSync(realFd, len); | ||
} | ||
watch(p, a, b) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.watch(p, | ||
// @ts-expect-error | ||
a, b); | ||
}, (zipFs, { subPath }) => { | ||
return zipFs.watch(subPath, | ||
// @ts-expect-error | ||
a, b); | ||
}); | ||
} | ||
watchFile(p, a, b) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.watchFile(p, | ||
// @ts-expect-error | ||
a, b); | ||
}, () => { | ||
return (0, watchFile_1.watchFile)(this, p, a, b); | ||
}); | ||
} | ||
unwatchFile(p, cb) { | ||
return this.makeCallSync(p, () => { | ||
return this.baseFs.unwatchFile(p, cb); | ||
}, () => { | ||
return (0, watchFile_1.unwatchFile)(this, p, cb); | ||
}); | ||
} | ||
async makeCallPromise(p, discard, accept, { requireSubpath = true } = {}) { | ||
if (typeof p !== `string`) | ||
return await discard(); | ||
const normalizedP = this.resolve(p); | ||
const zipInfo = this.findZip(normalizedP); | ||
if (!zipInfo) | ||
return await discard(); | ||
if (requireSubpath && zipInfo.subPath === `/`) | ||
return await discard(); | ||
return await this.getZipPromise(zipInfo.archivePath, async (zipFs) => await accept(zipFs, zipInfo)); | ||
} | ||
makeCallSync(p, discard, accept, { requireSubpath = true } = {}) { | ||
if (typeof p !== `string`) | ||
return discard(); | ||
const normalizedP = this.resolve(p); | ||
const zipInfo = this.findZip(normalizedP); | ||
if (!zipInfo) | ||
return discard(); | ||
if (requireSubpath && zipInfo.subPath === `/`) | ||
return discard(); | ||
return this.getZipSync(zipInfo.archivePath, zipFs => accept(zipFs, zipInfo)); | ||
} | ||
findZip(p) { | ||
if (this.filter && !this.filter.test(p)) | ||
return null; | ||
let filePath = ``; | ||
while (true) { | ||
const pathPartWithArchive = p.substring(filePath.length); | ||
let archivePart; | ||
if (!this.fileExtensions) { | ||
archivePart = (0, exports.getArchivePart)(pathPartWithArchive, `.zip`); | ||
} | ||
else { | ||
for (const ext of this.fileExtensions) { | ||
archivePart = (0, exports.getArchivePart)(pathPartWithArchive, ext); | ||
if (archivePart) { | ||
break; | ||
const fileExtensions = opts.fileExtensions; | ||
const readOnlyArchives = opts.readOnlyArchives; | ||
const getMountPoint = typeof fileExtensions === `undefined` | ||
? path => getArchivePart(path, `.zip`) | ||
: path => { | ||
for (const extension of fileExtensions) { | ||
const result = getArchivePart(path, extension); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
} | ||
if (!archivePart) | ||
return null; | ||
filePath = this.pathUtils.join(filePath, archivePart); | ||
if (this.isZip.has(filePath) === false) { | ||
if (this.notZip.has(filePath)) | ||
continue; | ||
try { | ||
if (!this.baseFs.lstatSync(filePath).isFile()) { | ||
this.notZip.add(filePath); | ||
continue; | ||
} | ||
} | ||
catch { | ||
return null; | ||
} | ||
this.isZip.add(filePath); | ||
} | ||
return { | ||
archivePath: filePath, | ||
subPath: this.pathUtils.join(path_1.PortablePath.root, p.substring(filePath.length)), | ||
}; | ||
} | ||
} | ||
limitOpenFiles(max) { | ||
if (this.zipInstances === null) | ||
return; | ||
const now = Date.now(); | ||
let nextExpiresAt = now + this.maxAge; | ||
let closeCount = max === null ? 0 : this.zipInstances.size - max; | ||
for (const [path, { zipFs, expiresAt, refCount }] of this.zipInstances.entries()) { | ||
if (refCount !== 0 || zipFs.hasOpenFileHandles()) { | ||
continue; | ||
} | ||
else if (now >= expiresAt) { | ||
zipFs.saveAndClose(); | ||
this.zipInstances.delete(path); | ||
closeCount -= 1; | ||
continue; | ||
} | ||
else if (max === null || closeCount <= 0) { | ||
nextExpiresAt = expiresAt; | ||
break; | ||
} | ||
zipFs.saveAndClose(); | ||
this.zipInstances.delete(path); | ||
closeCount -= 1; | ||
} | ||
if (this.limitOpenFilesTimeout === null && ((max === null && this.zipInstances.size > 0) || max !== null)) { | ||
this.limitOpenFilesTimeout = setTimeout(() => { | ||
this.limitOpenFilesTimeout = null; | ||
this.limitOpenFiles(null); | ||
}, nextExpiresAt - now).unref(); | ||
} | ||
} | ||
async getZipPromise(p, accept) { | ||
const getZipOptions = async () => ({ | ||
baseFs: this.baseFs, | ||
libzip: this.libzip, | ||
readOnly: this.readOnlyArchives, | ||
stats: await this.baseFs.statPromise(p), | ||
const factorySync = (baseFs, p) => { | ||
return new ZipFS_1.ZipFS(p, { | ||
baseFs, | ||
libzip: getLibzip(), | ||
readOnly: readOnlyArchives, | ||
stats: baseFs.statSync(p), | ||
}); | ||
}; | ||
const factoryPromise = async (baseFs, p) => { | ||
const zipOptions = { | ||
baseFs, | ||
libzip: getLibzip(), | ||
readOnly: readOnlyArchives, | ||
stats: await baseFs.statPromise(p), | ||
}; | ||
return () => { | ||
return new ZipFS_1.ZipFS(p, zipOptions); | ||
}; | ||
}; | ||
super({ | ||
...opts, | ||
factorySync, | ||
factoryPromise, | ||
getMountPoint, | ||
}); | ||
if (this.zipInstances) { | ||
let cachedZipFs = this.zipInstances.get(p); | ||
if (!cachedZipFs) { | ||
const zipOptions = await getZipOptions(); | ||
// We need to recheck because concurrent getZipPromise calls may | ||
// have instantiated the zip archive while we were waiting | ||
cachedZipFs = this.zipInstances.get(p); | ||
if (!cachedZipFs) { | ||
cachedZipFs = { | ||
zipFs: new ZipFS_1.ZipFS(p, zipOptions), | ||
expiresAt: 0, | ||
refCount: 0, | ||
}; | ||
} | ||
} | ||
// Removing then re-adding the field allows us to easily implement | ||
// a basic LRU garbage collection strategy | ||
this.zipInstances.delete(p); | ||
this.limitOpenFiles(this.maxOpenFiles - 1); | ||
this.zipInstances.set(p, cachedZipFs); | ||
cachedZipFs.expiresAt = Date.now() + this.maxAge; | ||
cachedZipFs.refCount += 1; | ||
try { | ||
return await accept(cachedZipFs.zipFs); | ||
} | ||
finally { | ||
cachedZipFs.refCount -= 1; | ||
} | ||
} | ||
else { | ||
const zipFs = new ZipFS_1.ZipFS(p, await getZipOptions()); | ||
try { | ||
return await accept(zipFs); | ||
} | ||
finally { | ||
zipFs.saveAndClose(); | ||
} | ||
} | ||
} | ||
getZipSync(p, accept) { | ||
const getZipOptions = () => ({ | ||
baseFs: this.baseFs, | ||
libzip: this.libzip, | ||
readOnly: this.readOnlyArchives, | ||
stats: this.baseFs.statSync(p), | ||
}); | ||
if (this.zipInstances) { | ||
let cachedZipFs = this.zipInstances.get(p); | ||
if (!cachedZipFs) { | ||
cachedZipFs = { | ||
zipFs: new ZipFS_1.ZipFS(p, getZipOptions()), | ||
expiresAt: 0, | ||
refCount: 0, | ||
}; | ||
} | ||
// Removing then re-adding the field allows us to easily implement | ||
// a basic LRU garbage collection strategy | ||
this.zipInstances.delete(p); | ||
this.limitOpenFiles(this.maxOpenFiles - 1); | ||
this.zipInstances.set(p, cachedZipFs); | ||
cachedZipFs.expiresAt = Date.now() + this.maxAge; | ||
return accept(cachedZipFs.zipFs); | ||
} | ||
else { | ||
const zipFs = new ZipFS_1.ZipFS(p, getZipOptions()); | ||
try { | ||
return accept(zipFs); | ||
} | ||
finally { | ||
zipFs.saveAndClose(); | ||
} | ||
} | ||
} | ||
} | ||
exports.ZipOpenFS = ZipOpenFS; |
{ | ||
"name": "@yarnpkg/fslib", | ||
"version": "3.0.0-rc.15", | ||
"version": "3.0.0-rc.16", | ||
"stableVersion": "2.7.0", | ||
@@ -9,3 +9,3 @@ "license": "BSD-2-Clause", | ||
"dependencies": { | ||
"@yarnpkg/libzip": "^3.0.0-rc.15", | ||
"@yarnpkg/libzip": "^3.0.0-rc.16", | ||
"tslib": "^2.4.0" | ||
@@ -12,0 +12,0 @@ }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
283434
54
7169
Updated@yarnpkg/libzip@^3.0.0-rc.16