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

Support Windows paths #33

merged 33 commits into from
Mar 26, 2019

Conversation

Embraser01
Copy link
Member

@Embraser01 Embraser01 commented Mar 20, 2019

Following #29, I tried to implement fromPortablePath and toPortablePath in order to make it work on windows.

For now, its just a Draft PR, it's still not fully working but I'm making progress 🎉

I will continue working on it in the coming days

EDIT: I got it to work on windows (yarn install berry itself).

Still some things to look:

  • When yarn config -v, it displays posix paths
  • How do we handle paths in .yarnrc file?
  • Error with ZipFS
  • Build berry yarn build:cli on Windows

Copy link
Member

@arcanis arcanis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a great start, thanks for leading this! I've left a few comments, feel free to address them whenever you like :)

packages/berry-core/sources/Cache.ts Outdated Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Outdated Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Outdated Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Outdated Show resolved Hide resolved
packages/berry-fslib/sources/NodeFS.ts Outdated Show resolved Hide resolved
@Embraser01 Embraser01 marked this pull request as ready for review March 20, 2019 20:13
@arcanis
Copy link
Member

arcanis commented Mar 20, 2019

When yarn config -v, it displays posix paths

Interesting - I wonder whether that's a bug or a feature 🤔

How do we handle paths in .yarnrc file?

Good point - that would be in Configuration.ts, and more precisely here. Similar to how we had to call NodeFS.toPortablePath(args[0]) in the CLI _entry command because the argument was user-provided, in this case we likely need to call NodeFS.toPortablePath(value) in case the user specified an absolute path in its configuration.

@Embraser01
Copy link
Member Author

When yarn config -v, it displays posix paths

For now, It might be enough if we add an explaination in the doc? Its something transparent in most cases and handling it might be more tricky than useful (IMO)

How do we handle paths in .yarnrc file?

Ok, I'm changing this now

@arcanis
Copy link
Member

arcanis commented Mar 20, 2019

For now, It might be enough if we add an explaination in the doc? Its something transparent in most cases and handling it might be more tricky than useful (IMO)

Yup, I concur - I've updated the wording in the help message (I plan to auto-generate the CLI documentation from the website based on the actual source code).

@Embraser01
Copy link
Member Author

There is still some problems, even if we should be able to do a yarn install without problems (except maybe isaacs/rimraf#72).

I'd like to make yarn build:ci work on Windows before merging this 😃

@arcanis
Copy link
Member

arcanis commented Mar 21, 2019

Awesome! What are the current blockers that prevent build:cli from working?

Something that would be very useful too would be to add a Windows build to our Azure CI, this way we can start making sure that future PRs won't make us regress.

@Embraser01
Copy link
Member Author

I enabled the Windows pipeline in the config file.

Current blockers:

  • Handling each case where we use a third lib (e.g. globby) => It should be ok now
  • Got a command not found: run which is caused by

"scripts": {
"build:cli": "run @berry-build-bundle",
"run:cli": "run @berry-run"

@Embraser01
Copy link
Member Author

UPDATE:

Now I have a problem with run.cmd file and related batch files.

The content of these files fail and I don't really know why...

async function makePathWrapper(location: string, name: string, argv0: string, args: Array<string> = []) {
if (process.platform === `win32`) {
await xfs.writeFilePromise(`${location}/${name}.cmd`, `@"${location}\\${name}.cmd" ${args.join(` `)} %*\n`);
} else {
await xfs.writeFilePromise(`${location}/${name}`, `#!/usr/bin/env bash\n"${argv0}" ${args.map(arg => `'${arg.replace(/'/g, `'"'"'`)}'`).join(` `)} "$@"\n`);
await xfs.chmodPromise(`${location}/${name}`, 0o755);
}
}

@arcanis
Copy link
Member

arcanis commented Mar 22, 2019

Current CI state:

Error: ENOENT: no such file or directory, open 'D:\a\1\s\.yarn\virtual\@babel-cli-virtual-d10f4f3334a43d2e0d02cbd0751c6eb087e6ca7cca5d5f05ea03e64051cef75c\node_modules\@babel\cli\package.json'

This is likely because .yarn\virtual\@babel-cli-virtual-[...] is a symlink to a zip archive. It's meant to be picked up as such by the zip layer (here) but it doesn't seem like it is, and it instead cascades to the native filesystem which throws a file not found exception.

To fix that we would need to add some logs in findZip to have a better sense of what it gets as input - maybe it contains backslashes which throw it off?

@arcanis
Copy link
Member

arcanis commented Mar 22, 2019

realArchivePath { realArchivePath: '/mnt/d/a/1/s/.yarn/virtual/@babel-cli-virtual-d10f4f3334a43d2e0d02cbd0751c6eb087e6ca7cca5d5f05ea03e64051cef75c' }
stat { isFile: true, isDir: false, isSymlink: false }

Well, that's not great - seems like the symlink is dropped when cloning the repository 😞

@arcanis
Copy link
Member

arcanis commented Mar 22, 2019

I fixed the symlink problem by enforcing core.symlinks and running git reset --hard as part of the checkout process. Not super great, but it works 😃

This problem looks weird - it's like the Node executable cannot be found, but the path looks legit:

D:\a\1\s\packages\berry-cli>"C:\hostedtoolcache\windows\node\10.15.3\x64\node.exe" D:\a\1\s\scripts\run-yarn.js run @berry-build-bundle 
Error: spawn C:\hostedtoolcache\windows\node\10.15.3\x64\node.exe ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
    at onErrorNT (internal/child_process.js:415:16)
    at process._tickCallback (internal/process/next_tick.js:63:19)

@Embraser01
Copy link
Member Author

Oh right forgot to mention it but I had to enable the core.symlinks to make it work...

So the problem seems to be at the second spawn, I was thinking about the @ in @berry-build-bundle that might be interpreted as something else by cmd.exe?

@arcanis
Copy link
Member

arcanis commented Mar 23, 2019

Fixed! There was two problems:

  • On Windows the parameter to execa must be wrapped between double quotes if it contains spaces (like it does for Program Files). I made a quick patch but it kinda worries me a bit, that seems super weird ...

  • The cwd wasn't converted into the native format before spawning the process, hence the ENOENT even when the path didn't have actual spaces on Azure

The remaining issue seems to be related to the PnP hook, which isn't aware that it needs to transform back and forth the request and issuer parameter it receives from the user. That should be here, can I ask you to take a look when you have some time? I think the best would be to leave the functions as they are, but to expose wrappers here that would transparently make the conversion.

If you use @berry/fslib in this file, just double-check to make sure that the size of the .pnp.js doesn't go through the roof! I think it should be ok because it's already part of the bundle, but better be sure 😊

@Embraser01
Copy link
Member Author

News:

I'm close to having a working build!

The native patch seems to work but I get this error when building:

D:\a\1\s\packages\berry-cli>"C:\hostedtoolcache\windows\node\8.10.0\x64\node.exe" D:\a\1\s\scripts\run-yarn.js run @berry-build-bundle 
The following plugins will be compiled in the final bundle:

- @berry/plugin-essentials
- @berry/plugin-init
- @berry/plugin-constraints
- @berry/plugin-file
- @berry/plugin-github
- @berry/plugin-http
- @berry/plugin-link
- @berry/plugin-npm
- @berry/plugin-pnp


ERROR in ./sources/cli.ts
Module build failed (from /mnt/d/a/1/s/.yarn/virtual/ts-loader-virtual-0bde21af32dc2f5de720bd65957c771fe15fbbc102355b0bfc2f837ac31d251f/node_modules/ts-loader/index.js):
TypeError: Cannot read property 'path' of undefined
    at /mnt/d/a/1/s/.yarn/cache/typescript-npm-3.2.4-b4e9592640fe6a3127f23c3a0ab3ee2d5a89b86447c83a3ca347efb5601d8e62.zip/node_modules/typescript/lib/typescript.js:57417:46
    at Map.forEach (<anonymous>)
    at createResolver (/mnt/d/a/1/s/.yarn/cache/typescript-npm-3.2.4-b4e9592640fe6a3127f23c3a0ab3ee2d5a89b86447c83a3ca347efb5601d8e62.zip/node_modules/typescript/lib/typescript.js:57412:49)
    at Object.createTypeChecker (/mnt/d/a/1/s/.yarn/cache/typescript-npm-3.2.4-b4e9592640fe6a3127f23c3a0ab3ee2d5a89b86447c83a3ca347efb5601d8e62.zip/node_modules/typescript/lib/typescript.js:30777:28)
    at Object.getTypeChecker (/mnt/d/a/1/s/.yarn/cache/typescript-npm-3.2.4-b4e9592640fe6a3127f23c3a0ab3ee2d5a89b86447c83a3ca347efb5601d8e62.zip/node_modules/typescript/lib/typescript.js:86884:79)
    at synchronizeHostData (/mnt/d/a/1/s/.yarn/cache/typescript-npm-3.2.4-b4e9592640fe6a3127f23c3a0ab3ee2d5a89b86447c83a3ca347efb5601d8e62.zip/node_modules/typescript/lib/typescript.js:117554:21)
    at Object.getProgram (/mnt/d/a/1/s/.yarn/cache/typescript-npm-3.2.4-b4e9592640fe6a3127f23c3a0ab3ee2d5a89b86447c83a3ca347efb5601d8e62.zip/node_modules/typescript/lib/typescript.js:117627:13)
    at successfulTypeScriptInstance (/mnt/d/a/1/s/.yarn/virtual/ts-loader-virtual-0bde21af32dc2f5de720bd65957c771fe15fbbc102355b0bfc2f837ac31d251f/node_modules/ts-loader/dist/instances.js:162:80)
    at Object.getTypeScriptInstance (/mnt/d/a/1/s/.yarn/virtual/ts-loader-virtual-0bde21af32dc2f5de720bd65957c771fe15fbbc102355b0bfc2f837ac31d251f/node_modules/ts-loader/dist/instances.js:34:12)
    at Object.loader (/mnt/d/a/1/s/.yarn/virtual/ts-loader-virtual-0bde21af32dc2f5de720bd65957c771fe15fbbc102355b0bfc2f837ac31d251f/node_modules/ts-loader/dist/index.js:17:41)
Error: spawn "C:\hostedtoolcache\windows\node\8.10.0\x64\node.exe" ENOENT
    at notFoundError (/mnt/d/a/1/s/packages/berry-cli/bin/berry.js:67753:26)
    at verifyENOENT (/mnt/d/a/1/s/packages/berry-cli/bin/berry.js:67787:16)
    at ChildProcess.cp.emit (/mnt/d/a/1/s/packages/berry-cli/bin/berry.js:67774:25)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)

Any idea why?

@arcanis
Copy link
Member

arcanis commented Mar 25, 2019

Oh interesting - I think it's just because we should be calling fromPortablePath here (ts-pnp directly uses resolveToUnqualified: https://github.com/arcanis/ts-pnp/blob/master/index.js#L22) 😮

@arcanis
Copy link
Member

arcanis commented Mar 25, 2019

I gave a quick look - it seems that you made it so the API always returns portable paths. I think this detail should be hidden from the API consumer, so the functions should both accept native paths and return them. Does it make sense?

@Embraser01
Copy link
Member Author

I gave a quick look - it seems that you made it so the API always returns portable paths. I think this detail should be hidden from the API consumer, so the functions should both accept native paths and return them. Does it make sense?

Yes, it makes sense... I used only portable path because PnP patch fs and so NodeJS doesn't understand all paths (like files inside Zip).

I can make the API transform back to physical path but it wouldn't work until we transform it back to a portable path.

Example:
pnpapi.resolveToUnqualified('@manaflair/concierge', './') would give

Portable path: /mnt/n/berry/.yarn/cache/@manaflair-concierge-npm-0.12.3-<checksum>.zip/node_modules/@manaflair/concierge
Physical path: N:\berry\.yarn\cache\@manaflair-concierge-npm-0.12.3-<checksum>.zip\node_modules\@manaflair\concierge

How do we deal with this behaviour?

@arcanis
Copy link
Member

arcanis commented Mar 25, 2019

Indeed, I forgot about this! I think the solution would be for the PnP API not to use the actual Node filesystem in the first place - since we need the Zip layer anyway, it only makes sense to directly use the ZipOpenFS instance we've created. I've made a patch to try something in this sense, hopefully that'll help!

@arcanis
Copy link
Member

arcanis commented Mar 25, 2019

We're almost there! The build now works!! 😃

Now there's about 21 tests that fail (out of 167, so that's pretty good!). After a quick look:

  • I think one problem is caused by the syml (@berry/parser) parser and/or stringifier when they face backslashes. They should be compatible with Yaml so I think they are meant to be doubled and surrounded by double quote, but maybe it's not the case.

  • yarn link registers paths using portable paths rather than physical paths. I think I'm fine with keeping this one as-is, but the tests should be fixed by using toPortablePath within the toMatchObject matcher.

  • The link:, portal:, and file: protocols don't properly join the paths together. Given that multiple tests use them to reproduce some tree layouts, fixing this should fix at least 10 tests at once.

  • The file: resolver doesn't support windows-style paths in its regexp.

  • I think the following mask check should be removed to just always ignore chmod on folders.

How do you wish to proceed? I was thinking maybe we can merge this PR to prevent further conflicts, and work on making the remaining tests pass on separate PRs, what do you think?

@arcanis
Copy link
Member

arcanis commented Mar 25, 2019

Additionally, I'm about to order cool new Yarn tshirts to celebrate the v2. To thank you for your help I'd be happy to send you one once I get them. If that's of any interest to you, forward me by email a postal address where you wish to receive it and I'll let you know once I'll have shipped it 🙂

giphy

@Embraser01
Copy link
Member Author

We're almost there! The build now works!! 😃

Awesome! 🎉 🎉
Now I'll see how it behave on a middle sized project 😉

How do you wish to proceed? I was thinking maybe we can merge this PR to prevent further conflicts, and work on making the remaining tests pass on separate PRs, what do you think?

Works for me! I'll start working on it this week I think.

Additionally, I'm about to order cool new Yarn tshirts to celebrate the v2. To thank you for your help I'd be happy to send you one once I get them. If that's of any interest to you, forward me by email a postal address where you wish to receive it and I'll let you know once I'll have shipped it 🙂

Awesome, thanks! I'll email you my postal address soon 😃

@arcanis arcanis merged commit b6dbb68 into yarnpkg:master Mar 26, 2019
@Embraser01 Embraser01 deleted the windows-portable-path branch March 26, 2019 12:24
@arcanis arcanis mentioned this pull request Mar 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants