@yarnpkg/fslib
Advanced tools
Comparing version 3.0.0-rc.12 to 3.0.0-rc.14
import { FakeFS } from '../FakeFS'; | ||
import { Path } from '../path'; | ||
export declare enum LinkStrategy { | ||
Allow = "allow", | ||
ReadOnly = "readOnly" | ||
} | ||
export declare type CopyOptions = { | ||
linkStrategy: LinkStrategy | null; | ||
export declare type HardlinkFromIndexStrategy<P> = { | ||
type: `HardlinkFromIndex`; | ||
indexPath: P; | ||
autoRepair?: boolean; | ||
readOnly?: boolean; | ||
}; | ||
export declare type LinkStrategy<P> = HardlinkFromIndexStrategy<P>; | ||
export declare type CopyOptions<P> = { | ||
linkStrategy: LinkStrategy<P> | null; | ||
stableTime: boolean; | ||
@@ -15,2 +18,3 @@ stableSort: boolean; | ||
export declare type LUTimes<P extends Path> = Array<[P, Date | number, Date | number]>; | ||
export declare function copyPromise<P1 extends Path, P2 extends Path>(destinationFs: FakeFS<P1>, destination: P1, sourceFs: FakeFS<P2>, source: P2, opts: CopyOptions): Promise<void>; | ||
export declare function setupCopyIndex<P extends Path>(destinationFs: FakeFS<P>, linkStrategy: Pick<HardlinkFromIndexStrategy<P>, `indexPath`>): Promise<P>; | ||
export declare function copyPromise<P1 extends Path, P2 extends Path>(destinationFs: FakeFS<P1>, destination: P1, sourceFs: FakeFS<P2>, source: P2, opts: CopyOptions<P1>): Promise<void>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.copyPromise = exports.LinkStrategy = void 0; | ||
exports.copyPromise = exports.setupCopyIndex = void 0; | ||
const tslib_1 = require("tslib"); | ||
const fs_1 = tslib_1.__importDefault(require("fs")); | ||
const constants = tslib_1.__importStar(require("../constants")); | ||
const path_1 = require("../path"); | ||
const defaultTime = new Date(constants.SAFE_TIME * 1000); | ||
var LinkStrategy; | ||
(function (LinkStrategy) { | ||
LinkStrategy["Allow"] = "allow"; | ||
LinkStrategy["ReadOnly"] = "readOnly"; | ||
})(LinkStrategy = exports.LinkStrategy || (exports.LinkStrategy = {})); | ||
const defaultTimeMs = defaultTime.getTime(); | ||
async function setupCopyIndex(destinationFs, linkStrategy) { | ||
const hexCharacters = `0123456789abcdef`; | ||
await destinationFs.mkdirPromise(linkStrategy.indexPath, { recursive: true }); | ||
const promises = []; | ||
for (const l1 of hexCharacters) | ||
for (const l2 of hexCharacters) | ||
promises.push(destinationFs.mkdirPromise(destinationFs.pathUtils.join(linkStrategy.indexPath, `${l1}${l2}`), { recursive: true })); | ||
await Promise.all(promises); | ||
return linkStrategy.indexPath; | ||
} | ||
exports.setupCopyIndex = setupCopyIndex; | ||
async function copyPromise(destinationFs, destination, sourceFs, source, opts) { | ||
@@ -35,3 +41,3 @@ const normalizedDestination = destinationFs.pathUtils.normalize(destination); | ||
async function copyImpl(prelayout, postlayout, updateTime, destinationFs, destination, sourceFs, source, opts) { | ||
var _a, _b; | ||
var _a, _b, _c; | ||
const destinationStat = opts.didParentExist ? await maybeLStat(destinationFs, destination) : null; | ||
@@ -65,10 +71,14 @@ const sourceStat = await sourceFs.lstatPromise(source); | ||
} | ||
if (updated || ((_a = destinationStat === null || destinationStat === void 0 ? void 0 : destinationStat.mtime) === null || _a === void 0 ? void 0 : _a.getTime()) !== mtime.getTime() || ((_b = destinationStat === null || destinationStat === void 0 ? void 0 : destinationStat.atime) === null || _b === void 0 ? void 0 : _b.getTime()) !== atime.getTime()) { | ||
postlayout.push(() => updateTime(destination, atime, mtime)); | ||
updated = true; | ||
// We aren't allowed to modify the destination if we work with the index, | ||
// since otherwise we'd accidentally propagate the changes to all projects. | ||
if (((_a = opts.linkStrategy) === null || _a === void 0 ? void 0 : _a.type) !== `HardlinkFromIndex` || !sourceStat.isFile()) { | ||
if (updated || ((_b = destinationStat === null || destinationStat === void 0 ? void 0 : destinationStat.mtime) === null || _b === void 0 ? void 0 : _b.getTime()) !== mtime.getTime() || ((_c = destinationStat === null || destinationStat === void 0 ? void 0 : destinationStat.atime) === null || _c === void 0 ? void 0 : _c.getTime()) !== atime.getTime()) { | ||
postlayout.push(() => updateTime(destination, atime, mtime)); | ||
updated = true; | ||
} | ||
if (destinationStat === null || (destinationStat.mode & 0o777) !== (sourceStat.mode & 0o777)) { | ||
postlayout.push(() => destinationFs.chmodPromise(destination, sourceStat.mode & 0o777)); | ||
updated = true; | ||
} | ||
} | ||
if (destinationStat === null || (destinationStat.mode & 0o777) !== (sourceStat.mode & 0o777)) { | ||
postlayout.push(() => destinationFs.chmodPromise(destination, sourceStat.mode & 0o777)); | ||
updated = true; | ||
} | ||
return updated; | ||
@@ -127,43 +137,41 @@ } | ||
} | ||
const isCloneSupportedCache = new WeakMap(); | ||
function makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { | ||
return async () => { | ||
await opFs.linkPromise(source, destination); | ||
if (linkStrategy === LinkStrategy.ReadOnly) { | ||
// We mutate the stat, otherwise it'll be reset by copyImpl | ||
sourceStat.mode &= ~0o222; | ||
await opFs.chmodPromise(destination, sourceStat.mode); | ||
} | ||
}; | ||
} | ||
function makeCloneLinkOperation(opFs, destination, source, sourceStat, linkStrategy) { | ||
const isCloneSupported = isCloneSupportedCache.get(opFs); | ||
if (typeof isCloneSupported === `undefined`) { | ||
return async () => { | ||
try { | ||
await opFs.copyFilePromise(source, destination, fs_1.default.constants.COPYFILE_FICLONE_FORCE); | ||
isCloneSupportedCache.set(opFs, true); | ||
async function copyFileViaIndex(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts, linkStrategy) { | ||
const sourceHash = await sourceFs.checksumFilePromise(source, { algorithm: `sha1` }); | ||
const indexPath = destinationFs.pathUtils.join(linkStrategy.indexPath, sourceHash.slice(0, 2), `${sourceHash}.dat`); | ||
let indexStat = await maybeLStat(destinationFs, indexPath); | ||
if (destinationStat) { | ||
const isDestinationHardlinkedFromIndex = indexStat && destinationStat.dev === indexStat.dev && destinationStat.ino === indexStat.ino; | ||
const isIndexModified = (indexStat === null || indexStat === void 0 ? void 0 : indexStat.mtimeMs) !== defaultTimeMs; | ||
if (isDestinationHardlinkedFromIndex) | ||
if (isIndexModified && linkStrategy.autoRepair) | ||
indexStat = null; | ||
if (!isDestinationHardlinkedFromIndex) { | ||
if (opts.overwrite) { | ||
prelayout.push(async () => destinationFs.removePromise(destination)); | ||
destinationStat = null; | ||
} | ||
catch (err) { | ||
if (err.code === `ENOSYS` || err.code === `ENOTSUP`) { | ||
isCloneSupportedCache.set(opFs, false); | ||
await makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy)(); | ||
} | ||
else { | ||
throw err; | ||
} | ||
else { | ||
return false; | ||
} | ||
}; | ||
} | ||
} | ||
else { | ||
if (isCloneSupported) { | ||
return async () => opFs.copyFilePromise(source, destination, fs_1.default.constants.COPYFILE_FICLONE_FORCE); | ||
prelayout.push(async () => { | ||
if (!indexStat) { | ||
await destinationFs.lockPromise(indexPath, async () => { | ||
const content = await sourceFs.readFilePromise(source); | ||
await destinationFs.writeFilePromise(indexPath, content); | ||
}); | ||
} | ||
else { | ||
return makeLinkOperation(opFs, destination, source, sourceStat, linkStrategy); | ||
if (!destinationStat) { | ||
await destinationFs.linkPromise(indexPath, destination); | ||
} | ||
} | ||
}); | ||
postlayout.push(async () => { | ||
if (!indexStat) { | ||
await updateTime(indexPath, defaultTime, defaultTime); | ||
} | ||
}); | ||
return false; | ||
} | ||
async function copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { | ||
var _a; | ||
async function copyFileDirect(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { | ||
if (destinationStat !== null) { | ||
@@ -178,13 +186,22 @@ if (opts.overwrite) { | ||
} | ||
const linkStrategy = (_a = opts.linkStrategy) !== null && _a !== void 0 ? _a : null; | ||
const op = destinationFs === sourceFs | ||
? linkStrategy !== null | ||
? makeCloneLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) | ||
: async () => destinationFs.copyFilePromise(source, destination, fs_1.default.constants.COPYFILE_FICLONE) | ||
: linkStrategy !== null | ||
? makeLinkOperation(destinationFs, destination, source, sourceStat, linkStrategy) | ||
: async () => destinationFs.writeFilePromise(destination, await sourceFs.readFilePromise(source)); | ||
prelayout.push(async () => op()); | ||
// TODO: Add support for file cloning, by adding a flag inside the FakeFS | ||
// instances to detect which "namespace" they're part of (for example, the | ||
// NodeFS and the ZipFS would be different namespaces since you can't clone | ||
// from one disk to the other; on the other hand, a CwdFS would share the | ||
// namespace from its base FS and thus would support cloning). | ||
prelayout.push(async () => { | ||
const content = await sourceFs.readFilePromise(source); | ||
await destinationFs.writeFilePromise(destination, content); | ||
}); | ||
return true; | ||
} | ||
async function copyFile(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { | ||
var _a; | ||
if (((_a = opts.linkStrategy) === null || _a === void 0 ? void 0 : _a.type) === `HardlinkFromIndex`) { | ||
return copyFileViaIndex(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts, opts.linkStrategy); | ||
} | ||
else { | ||
return copyFileDirect(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts); | ||
} | ||
} | ||
async function copySymlink(prelayout, postlayout, updateTime, destinationFs, destination, destinationStat, sourceFs, source, sourceStat, opts) { | ||
@@ -191,0 +208,0 @@ if (destinationStat !== null) { |
@@ -256,2 +256,5 @@ /// <reference types="node" /> | ||
}): AsyncGenerator<P, void, unknown>; | ||
checksumFilePromise(path: P, { algorithm }?: { | ||
algorithm?: string; | ||
}): Promise<string>; | ||
removePromise(p: P, { recursive, maxRetries }?: { | ||
@@ -277,3 +280,3 @@ recursive?: boolean; | ||
stableTime?: boolean; | ||
linkStrategy?: LinkStrategy; | ||
linkStrategy?: LinkStrategy<P> | null; | ||
}): Promise<void>; | ||
@@ -285,3 +288,3 @@ copyPromise<P2 extends Path>(destination: P, source: P2, options: { | ||
stableTime?: boolean; | ||
linkStrategy?: LinkStrategy; | ||
linkStrategy?: LinkStrategy<P> | null; | ||
}): Promise<void>; | ||
@@ -288,0 +291,0 @@ /** @deprecated Prefer using `copyPromise` instead */ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.normalizeLineEndings = exports.BasePortableFakeFS = exports.FakeFS = void 0; | ||
const crypto_1 = require("crypto"); | ||
const os_1 = require("os"); | ||
@@ -32,2 +33,17 @@ const copyPromise_1 = require("./algorithms/copyPromise"); | ||
} | ||
async checksumFilePromise(path, { algorithm = `sha512` } = {}) { | ||
const fd = await this.openPromise(path, `r`); | ||
try { | ||
const CHUNK_SIZE = 65536; | ||
const chunk = Buffer.allocUnsafeSlow(CHUNK_SIZE); | ||
const hash = (0, crypto_1.createHash)(algorithm); | ||
let bytesRead = 0; | ||
while ((bytesRead = await this.readPromise(fd, chunk, 0, CHUNK_SIZE)) !== 0) | ||
hash.update(bytesRead === CHUNK_SIZE ? chunk : chunk.slice(0, bytesRead)); | ||
return hash.digest(`hex`); | ||
} | ||
finally { | ||
await this.closePromise(fd); | ||
} | ||
} | ||
async removePromise(p, { recursive = true, maxRetries = 5 } = {}) { | ||
@@ -34,0 +50,0 @@ let stat; |
import * as constants from './constants'; | ||
import * as statUtils from './statUtils'; | ||
export { constants }; | ||
export { LinkStrategy } from './algorithms/copyPromise'; | ||
export type { LinkStrategy } from './algorithms/copyPromise'; | ||
export { setupCopyIndex } from './algorithms/copyPromise'; | ||
export { opendir } from './algorithms/opendir'; | ||
@@ -41,4 +42,4 @@ export { statUtils }; | ||
export { ZipOpenFS } from './ZipOpenFS'; | ||
export { patchFs, extendFs } from './patchFs'; | ||
export { patchFs, extendFs } from './patchFs/patchFs'; | ||
export { xfs } from './xfs'; | ||
export type { XFS } from './xfs'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.xfs = exports.extendFs = exports.patchFs = exports.ZipOpenFS = exports.ZipFS = exports.VirtualFS = exports.ProxiedFS = exports.PosixFS = exports.NodeFS = exports.NoFS = exports.LazyFS = exports.JailFS = exports.CwdFS = exports.FakeFS = exports.AliasFS = exports.toFilename = exports.ppath = exports.npath = exports.Filename = exports.PortablePath = exports.DEFAULT_COMPRESSION_LEVEL = exports.normalizeLineEndings = exports.statUtils = exports.opendir = exports.LinkStrategy = exports.constants = void 0; | ||
exports.xfs = exports.extendFs = exports.patchFs = exports.ZipOpenFS = exports.ZipFS = exports.VirtualFS = exports.ProxiedFS = exports.PosixFS = exports.NodeFS = exports.NoFS = exports.LazyFS = exports.JailFS = exports.CwdFS = exports.FakeFS = exports.AliasFS = exports.toFilename = exports.ppath = exports.npath = exports.Filename = exports.PortablePath = exports.DEFAULT_COMPRESSION_LEVEL = exports.normalizeLineEndings = exports.statUtils = exports.opendir = exports.setupCopyIndex = exports.constants = void 0; | ||
const tslib_1 = require("tslib"); | ||
@@ -10,3 +10,3 @@ const constants = tslib_1.__importStar(require("./constants")); | ||
var copyPromise_1 = require("./algorithms/copyPromise"); | ||
Object.defineProperty(exports, "LinkStrategy", { enumerable: true, get: function () { return copyPromise_1.LinkStrategy; } }); | ||
Object.defineProperty(exports, "setupCopyIndex", { enumerable: true, get: function () { return copyPromise_1.setupCopyIndex; } }); | ||
var opendir_1 = require("./algorithms/opendir"); | ||
@@ -49,3 +49,3 @@ Object.defineProperty(exports, "opendir", { enumerable: true, get: function () { return opendir_1.opendir; } }); | ||
Object.defineProperty(exports, "ZipOpenFS", { enumerable: true, get: function () { return ZipOpenFS_1.ZipOpenFS; } }); | ||
var patchFs_1 = require("./patchFs"); | ||
var patchFs_1 = require("./patchFs/patchFs"); | ||
Object.defineProperty(exports, "patchFs", { enumerable: true, get: function () { return patchFs_1.patchFs; } }); | ||
@@ -52,0 +52,0 @@ Object.defineProperty(exports, "extendFs", { enumerable: true, get: function () { return patchFs_1.extendFs; } }); |
{ | ||
"name": "@yarnpkg/fslib", | ||
"version": "3.0.0-rc.12", | ||
"version": "3.0.0-rc.14", | ||
"stableVersion": "2.7.0", | ||
"license": "BSD-2-Clause", | ||
@@ -8,3 +9,3 @@ "main": "./lib/index.js", | ||
"dependencies": { | ||
"@yarnpkg/libzip": "^3.0.0-rc.12", | ||
"@yarnpkg/libzip": "^3.0.0-rc.14", | ||
"tslib": "^1.13.0" | ||
@@ -34,4 +35,3 @@ }, | ||
}, | ||
"stableVersion": "2.6.1", | ||
"typings": "./lib/index.d.ts" | ||
} |
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
275888
52
7019
3
Updated@yarnpkg/libzip@^3.0.0-rc.14