Skip to content

Commit

Permalink
fix(fslib): make recursive mkdir return the first created directory (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
merceyz committed Jun 24, 2022
1 parent c301f1d commit 66e75d6
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 21 deletions.
17 changes: 11 additions & 6 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions .yarn/versions/4ef8937b.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
releases:
"@yarnpkg/cli": patch
"@yarnpkg/core": patch
"@yarnpkg/fslib": patch
"@yarnpkg/pnp": patch

declined:
- "@yarnpkg/esbuild-plugin-pnp"
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-exec"
- "@yarnpkg/plugin-file"
- "@yarnpkg/plugin-git"
- "@yarnpkg/plugin-github"
- "@yarnpkg/plugin-http"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-link"
- "@yarnpkg/plugin-nm"
- "@yarnpkg/plugin-npm"
- "@yarnpkg/plugin-npm-cli"
- "@yarnpkg/plugin-pack"
- "@yarnpkg/plugin-patch"
- "@yarnpkg/plugin-pnp"
- "@yarnpkg/plugin-pnpm"
- "@yarnpkg/plugin-stage"
- "@yarnpkg/plugin-typescript"
- "@yarnpkg/plugin-version"
- "@yarnpkg/plugin-workspace-tools"
- vscode-zipfs
- "@yarnpkg/builder"
- "@yarnpkg/doctor"
- "@yarnpkg/extensions"
- "@yarnpkg/json-proxy"
- "@yarnpkg/nm"
- "@yarnpkg/pnpify"
- "@yarnpkg/sdks"
- "@yarnpkg/shell"
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export const createTemporaryFile = async (filePath: PortablePath = `file` as Por
return ppath.resolve(folderPath, filePath as PortablePath);
};

export const mkdirp = async (target: PortablePath): Promise<void> =>
export const mkdirp = async (target: PortablePath): Promise<string | undefined> =>
await xfs.mkdirpPromise(target);

export const writeFile = async (target: PortablePath, body: string | Buffer): Promise<void> => {
Expand Down
2 changes: 1 addition & 1 deletion packages/yarnpkg-core/sources/worker-zip/index.js

Large diffs are not rendered by default.

24 changes: 18 additions & 6 deletions packages/yarnpkg-fslib/sources/FakeFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ export abstract class FakeFS<P extends Path> {
abstract chownPromise(p: P, uid: number, gid: number): Promise<void>;
abstract chownSync(p: P, uid: number, gid: number): void;

abstract mkdirPromise(p: P, opts?: MkdirOptions): Promise<void>;
abstract mkdirSync(p: P, opts?: MkdirOptions): void;
abstract mkdirPromise(p: P, opts?: MkdirOptions): Promise<string | undefined>;
abstract mkdirSync(p: P, opts?: MkdirOptions): string | undefined;

abstract rmdirPromise(p: P, opts?: RmdirOptions): Promise<void>;
abstract rmdirSync(p: P, opts?: RmdirOptions): void;
Expand Down Expand Up @@ -333,13 +333,15 @@ export abstract class FakeFS<P extends Path> {
}
}

async mkdirpPromise(p: P, {chmod, utimes}: {chmod?: number, utimes?: [Date | string | number, Date | string | number]} = {}) {
async mkdirpPromise(p: P, {chmod, utimes}: {chmod?: number, utimes?: [Date | string | number, Date | string | number]} = {}): Promise<string | undefined> {
p = this.resolve(p);
if (p === this.pathUtils.dirname(p))
return;
return undefined;

const parts = p.split(this.pathUtils.sep);

let createdDirectory: P | undefined;

for (let u = 2; u <= parts.length; ++u) {
const subPath = parts.slice(0, u).join(this.pathUtils.sep) as P;

Expand All @@ -354,6 +356,8 @@ export abstract class FakeFS<P extends Path> {
}
}

createdDirectory ??= subPath;

if (chmod != null)
await this.chmodPromise(subPath, chmod);

Expand All @@ -365,15 +369,19 @@ export abstract class FakeFS<P extends Path> {
}
}
}

return createdDirectory;
}

mkdirpSync(p: P, {chmod, utimes}: {chmod?: number, utimes?: [Date | string | number, Date | string | number]} = {}) {
mkdirpSync(p: P, {chmod, utimes}: {chmod?: number, utimes?: [Date | string | number, Date | string | number]} = {}): string | undefined {
p = this.resolve(p);
if (p === this.pathUtils.dirname(p))
return;
return undefined;

const parts = p.split(this.pathUtils.sep);

let createdDirectory: P | undefined;

for (let u = 2; u <= parts.length; ++u) {
const subPath = parts.slice(0, u).join(this.pathUtils.sep) as P;

Expand All @@ -388,6 +396,8 @@ export abstract class FakeFS<P extends Path> {
}
}

createdDirectory ??= subPath;

if (chmod != null)
this.chmodSync(subPath, chmod);

Expand All @@ -399,6 +409,8 @@ export abstract class FakeFS<P extends Path> {
}
}
}

return createdDirectory;
}

copyPromise(destination: P, source: P, options?: {baseFs?: undefined, overwrite?: boolean, stableSort?: boolean, stableTime?: boolean, linkStrategy?: LinkStrategy}): Promise<void>;
Expand Down
6 changes: 4 additions & 2 deletions packages/yarnpkg-fslib/sources/NodeFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,14 @@ export class NodeFS extends BasePortableFakeFS {
}

async mkdirPromise(p: PortablePath, opts?: MkdirOptions) {
return await new Promise<void>((resolve, reject) => {
return await new Promise<string | undefined>((resolve, reject) => {
// @ts-expect-error - Types are outdated, the second argument in the callback is either a string or undefined
this.realFs.mkdir(npath.fromPortablePath(p), opts, this.makeCallback(resolve, reject));
});
}

mkdirSync(p: PortablePath, opts?: MkdirOptions) {
mkdirSync(p: PortablePath, opts?: MkdirOptions): string | undefined {
// @ts-expect-error - Types are outdated, returns either a string or undefined
return this.realFs.mkdirSync(npath.fromPortablePath(p), opts);
}

Expand Down
7 changes: 3 additions & 4 deletions packages/yarnpkg-fslib/sources/ZipFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1240,10 +1240,8 @@ export class ZipFS extends BasePortableFakeFS {
}

mkdirSync(p: PortablePath, {mode = 0o755, recursive = false}: MkdirOptions = {}) {
if (recursive) {
this.mkdirpSync(p, {chmod: mode});
return;
}
if (recursive)
return this.mkdirpSync(p, {chmod: mode});

if (this.readOnly)
throw errors.EROFS(`mkdir '${p}'`);
Expand All @@ -1255,6 +1253,7 @@ export class ZipFS extends BasePortableFakeFS {

this.hydrateDirectory(resolvedP);
this.chmodSync(resolvedP, mode);
return undefined;
}

async rmdirPromise(p: PortablePath, opts?: RmdirOptions) {
Expand Down
22 changes: 22 additions & 0 deletions packages/yarnpkg-fslib/tests/ZipFS.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -901,4 +901,26 @@ describe(`ZipFS`, () => {

zipFs.discardAndClose();
});

it(`should return the first created directory in mkdir recursive`, () => {
const zipFs = new ZipFS(null, {libzip: getLibzipSync()});

expect(zipFs.mkdirSync(`/foo` as PortablePath, {recursive: true})).toEqual(`/foo` as PortablePath);
expect(zipFs.mkdirSync(`/foo` as PortablePath, {recursive: true})).toEqual(undefined);
expect(zipFs.mkdirSync(`/foo/bar/baz` as PortablePath, {recursive: true})).toEqual(`/foo/bar` as PortablePath);
expect(zipFs.mkdirSync(`/foo/bar/baz` as PortablePath, {recursive: true})).toEqual(undefined);

zipFs.discardAndClose();
});

it(`should return the first created directory in mkdirp`, () => {
const zipFs = new ZipFS(null, {libzip: getLibzipSync()});

expect(zipFs.mkdirpSync(`/foo` as PortablePath)).toEqual(`/foo` as PortablePath);
expect(zipFs.mkdirpSync(`/foo` as PortablePath)).toEqual(undefined);
expect(zipFs.mkdirpSync(`/foo/bar/baz` as PortablePath)).toEqual(`/foo/bar` as PortablePath);
expect(zipFs.mkdirpSync(`/foo/bar/baz` as PortablePath)).toEqual(undefined);

zipFs.discardAndClose();
});
});
2 changes: 1 addition & 1 deletion packages/yarnpkg-pnp/sources/hook.js

Large diffs are not rendered by default.

0 comments on commit 66e75d6

Please sign in to comment.