Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Windows paths #33

Merged
merged 33 commits into from
Mar 26, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cf63763
Base work for portable path
Embraser01 Mar 19, 2019
3ea7ac5
Add conversion where needed (still missing some!)
Embraser01 Mar 20, 2019
ca12605
Got it to work on Windows!
Embraser01 Mar 20, 2019
9d9af0e
Convert to portable path when calling 'yarn <path> install'
Embraser01 Mar 20, 2019
e7f88b3
Update config.ts
arcanis Mar 20, 2019
5afdbfe
Use posix where possible
Embraser01 Mar 20, 2019
9d8c602
Use xfs in json-proxy instead of native fs
Embraser01 Mar 20, 2019
9f7baa7
Fix berry json proxy dependencies
Embraser01 Mar 20, 2019
293d4c4
Handle more special cases (globby, pnp), activate Windows Pipeline
Embraser01 Mar 22, 2019
08434df
Fix PATH env variable when spawn process
Embraser01 Mar 22, 2019
91da8f7
Fix azure yaml
Embraser01 Mar 22, 2019
9e2c73a
Fixes plugin loading
arcanis Mar 22, 2019
a84f28a
Updates the checked-in build
Mar 22, 2019
fd90c88
Fixes yarn-path execution
Mar 22, 2019
15e5a14
Debug: Adds logging to findZip
Mar 22, 2019
1006c08
Revert "Debug: Adds logging to findZip"
Mar 22, 2019
06f4cad
Enforces symlinks on Windows
Mar 22, 2019
935ef94
Fixes the cmd scripts
Mar 22, 2019
47996f1
Adds a retry for EBUSY and ENOTEMPTY
Mar 22, 2019
e5cc92a
Fixes process spawning on win32
arcanis Mar 23, 2019
bff06d3
More portable path, prevent translating to portable path if already one
Embraser01 Mar 24, 2019
c03bdb4
Some cleanup for PnP hook on Windows
Embraser01 Mar 25, 2019
73b0472
Merge branch 'master' into windows-portable-path
Embraser01 Mar 25, 2019
3ea0c94
Use only portable path in Native resolution
Embraser01 Mar 25, 2019
a25e7fd
Moves the portable path conversion in dedicated wrappers
Mar 25, 2019
9b58424
Makes fakeFs a parameter to instantiate a PnP API
Mar 25, 2019
7c49825
Updates the PnP hook
Mar 25, 2019
4633d4f
Fixes accidental infinite loop
Mar 25, 2019
b9d8553
Updates the checked-in PnP hook
Mar 25, 2019
22edde3
Fixes how the PnP linker interacts with the PnP API on Windows
Mar 25, 2019
2891c1a
Implements a fs layer to convert paths before they reach zipopenfs
Mar 25, 2019
010898a
Adds a few extra conversions
arcanis Mar 25, 2019
a9bf0fe
Updates the checked-in build
Mar 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implements a fs layer to convert paths before they reach zipopenfs
  • Loading branch information
Maël Nison committed Mar 25, 2019
commit 2891c1a948239dd57cbf2c40da1cc5f37144e99d
217 changes: 183 additions & 34 deletions .pnp.js

Large diffs are not rendered by default.

5,283 changes: 2,716 additions & 2,567 deletions packages/berry-cli/bin/berry.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/berry-fslib/sources/JailFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ export class JailFS extends FakeFS {
}

async unlinkPromise(p: string) {
return await this.baseFs.rmdirPromise(this.fromJailedPath(p));
return await this.baseFs.unlinkPromise(this.fromJailedPath(p));
}

unlinkSync(p: string) {
return this.baseFs.rmdirSync(this.fromJailedPath(p));
return this.baseFs.unlinkSync(this.fromJailedPath(p));
}

async utimesPromise(p: string, atime: Date | string | number, mtime: Date | string | number) {
Expand Down
15 changes: 10 additions & 5 deletions packages/berry-fslib/sources/NodeFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,15 @@ export class NodeFS extends FakeFS {
}

static fromPortablePath(p: string) {
if (process.platform !== `win32`) return p;
if (process.platform !== `win32`)
return p;

// Path should look like "/mnt/n/berry/scripts/plugin-pack.js"
// And transform to "N:\berry/scripts/plugin-pack.js"

const match = p.match(PORTABLE_PREFIX_REGEXP);
if (!match) return p;
if (!match)
return p;

const [, drive, pathWithoutPrefix = ''] = match;
const windowsPath = pathWithoutPrefix.replace(/\//g, '\\');
Expand All @@ -251,18 +253,21 @@ export class NodeFS extends FakeFS {
}

static toPortablePath(p: string) {
if (process.platform !== `win32`) return p;
if (process.platform !== `win32`)
return p;

// Path should look like "N:\berry/scripts/plugin-pack.js"
// And transform to "/mnt/n/berry/scripts/plugin-pack.js"

// Skip if the path is already portable
if (p.startsWith(PORTABLE_PATH_PREFIX)) return p;
if (p.startsWith(PORTABLE_PATH_PREFIX))
return p;

const {root} = win32.parse(p);

// If relative path, just replace win32 slashes by posix slashes
if (!root) return p.replace(/\\/g, '/');
if (!root)
return p.replace(/\\/g, '/');

const driveLetter = root[0].toLowerCase();
const pathWithoutRoot = p.substr(root.length);
Expand Down
187 changes: 187 additions & 0 deletions packages/berry-fslib/sources/PosixFS.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import {posix} from 'path';

import {CreateReadStreamOptions, CreateWriteStreamOptions} from './FakeFS';
import {FakeFS, WriteFileOptions} from './FakeFS';
import {NodeFS} from './NodeFS';

export class PosixFS extends FakeFS {
private readonly baseFs: FakeFS;

constructor(baseFs: FakeFS) {
super();

this.baseFs = baseFs;
}

getRealPath() {
return NodeFS.fromPortablePath(this.baseFs.getRealPath());
}

async openPromise(p: string, flags: string, mode?: number) {
return await this.baseFs.openPromise(NodeFS.toPortablePath(p), flags, mode);
}

openSync(p: string, flags: string, mode?: number) {
return this.baseFs.openSync(NodeFS.toPortablePath(p), flags, mode);
}

async closePromise(fd: number) {
await this.baseFs.closePromise(fd);
}

closeSync(fd: number) {
this.baseFs.closeSync(fd);
}

createReadStream(p: string, opts?: CreateReadStreamOptions) {
return this.baseFs.createReadStream(NodeFS.toPortablePath(p), opts);
}

createWriteStream(p: string, opts?: CreateWriteStreamOptions) {
return this.baseFs.createWriteStream(NodeFS.toPortablePath(p), opts);
}

async realpathPromise(p: string) {
return NodeFS.fromPortablePath(await this.baseFs.realpathPromise(NodeFS.toPortablePath(p)));
}

realpathSync(p: string) {
return NodeFS.fromPortablePath(this.baseFs.realpathSync(NodeFS.toPortablePath(p)));
}

async existsPromise(p: string) {
return await this.baseFs.existsPromise(NodeFS.toPortablePath(p));
}

existsSync(p: string) {
return this.baseFs.existsSync(NodeFS.toPortablePath(p));
}

async statPromise(p: string) {
return await this.baseFs.statPromise(NodeFS.toPortablePath(p));
}

statSync(p: string) {
return this.baseFs.statSync(NodeFS.toPortablePath(p));
}

async lstatPromise(p: string) {
return await this.baseFs.lstatPromise(NodeFS.toPortablePath(p));
}

lstatSync(p: string) {
return this.baseFs.lstatSync(NodeFS.toPortablePath(p));
}

async chmodPromise(p: string, mask: number) {
return await this.baseFs.chmodPromise(NodeFS.toPortablePath(p), mask);
}

chmodSync(p: string, mask: number) {
return this.baseFs.chmodSync(NodeFS.toPortablePath(p), mask);
}

async renamePromise(oldP: string, newP: string) {
return await this.baseFs.renamePromise(NodeFS.toPortablePath(oldP), NodeFS.toPortablePath(newP));
}

renameSync(oldP: string, newP: string) {
return this.baseFs.renameSync(NodeFS.toPortablePath(oldP), NodeFS.toPortablePath(newP));
}

async copyFilePromise(sourceP: string, destP: string, flags?: number) {
return await this.baseFs.copyFilePromise(NodeFS.toPortablePath(sourceP), NodeFS.toPortablePath(destP), flags);
}

copyFileSync(sourceP: string, destP: string, flags?: number) {
return this.baseFs.copyFileSync(NodeFS.toPortablePath(sourceP), NodeFS.toPortablePath(destP), flags);
}

async writeFilePromise(p: string, content: string | Buffer | ArrayBuffer | DataView, opts?: WriteFileOptions) {
return await this.baseFs.writeFilePromise(NodeFS.toPortablePath(p), content, opts);
}

writeFileSync(p: string, content: string | Buffer | ArrayBuffer | DataView, opts?: WriteFileOptions) {
return this.baseFs.writeFileSync(NodeFS.toPortablePath(p), content, opts);
}

async unlinkPromise(p: string) {
return await this.baseFs.unlinkPromise(NodeFS.toPortablePath(p));
}

unlinkSync(p: string) {
return this.baseFs.unlinkSync(NodeFS.toPortablePath(p));
}

async utimesPromise(p: string, atime: Date | string | number, mtime: Date | string | number) {
return await this.baseFs.utimesPromise(NodeFS.toPortablePath(p), atime, mtime);
}

utimesSync(p: string, atime: Date | string | number, mtime: Date | string | number) {
return this.baseFs.utimesSync(NodeFS.toPortablePath(p), atime, mtime);
}

async mkdirPromise(p: string) {
return await this.baseFs.mkdirPromise(NodeFS.toPortablePath(p));
}

mkdirSync(p: string) {
return this.baseFs.mkdirSync(NodeFS.toPortablePath(p));
}

async rmdirPromise(p: string) {
return await this.baseFs.rmdirPromise(NodeFS.toPortablePath(p));
}

rmdirSync(p: string) {
return this.baseFs.rmdirSync(NodeFS.toPortablePath(p));
}

async symlinkPromise(target: string, p: string) {
return await this.baseFs.symlinkPromise(target, NodeFS.toPortablePath(p));
}

symlinkSync(target: string, p: string) {
return this.baseFs.symlinkSync(target, NodeFS.toPortablePath(p));
}

readFilePromise(p: string, encoding: 'utf8'): Promise<string>;
readFilePromise(p: string, encoding?: string): Promise<Buffer>;
async readFilePromise(p: string, encoding?: string) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return await this.baseFs.readFilePromise(NodeFS.toPortablePath(p), encoding);
default:
return await this.baseFs.readFilePromise(NodeFS.toPortablePath(p), encoding);
}
}

readFileSync(p: string, encoding: 'utf8'): string;
readFileSync(p: string, encoding?: string): Buffer;
readFileSync(p: string, encoding?: string) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.baseFs.readFileSync(NodeFS.toPortablePath(p), encoding);
default:
return this.baseFs.readFileSync(NodeFS.toPortablePath(p), encoding);
}
}

async readdirPromise(p: string) {
return await this.baseFs.readdirPromise(NodeFS.toPortablePath(p));
}

readdirSync(p: string) {
return this.baseFs.readdirSync(NodeFS.toPortablePath(p));
}

async readlinkPromise(p: string) {
return NodeFS.fromPortablePath(await this.baseFs.readlinkPromise(NodeFS.toPortablePath(p)));
}

readlinkSync(p: string) {
return NodeFS.fromPortablePath(this.baseFs.readlinkSync(NodeFS.toPortablePath(p)));
}
}
3 changes: 2 additions & 1 deletion packages/berry-fslib/sources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {FakeFS} from './FakeFS';
import {NodeFS} from './NodeFS';

export {AliasFS} from './AliasFS';
export {FakeFS} from './FakeFS';
export {CwdFS} from './CwdFS';
export {JailFS} from './JailFS';
export {NodeFS} from './NodeFS';
export {FakeFS} from './FakeFS';
export {PosixFS} from './PosixFS';
export {ZipFS} from './ZipFS';
export {ZipOpenFS} from './ZipOpenFS';

Expand Down
2 changes: 1 addition & 1 deletion packages/berry-pnp/bundles/hook.js

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions packages/berry-pnp/sources/loader/applyPatch.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {FakeFS, NodeFS, patchFs} from '@berry/fslib';
import fs from 'fs';
import Module from 'module';
import path from 'path';
import {FakeFS, NodeFS, PosixFS, patchFs} from '@berry/fslib';
import fs from 'fs';
import Module from 'module';
import path from 'path';

import {PackageLocator, PnpApi} from '../types';
import {PackageLocator, PnpApi} from '../types';

import {makeError, getIssuerModule} from './internalTools';
import {makeError, getIssuerModule} from './internalTools';

export type ApplyPatchOptions = {
compatibilityMode?: boolean,
Expand Down Expand Up @@ -261,5 +261,5 @@ export function applyPatch(pnpapi: PnpApi, opts: ApplyPatchOptions) {
return false;
};

patchFs(fs, opts.fakeFs);
patchFs(fs, new PosixFS(opts.fakeFs));
};