volta-cli / volta

Volta: JS Toolchains as Code. ⚡
https://volta.sh
Other
10.33k stars 220 forks source link

Problem installing @vue/cli on Windows10 #1010

Open alfianpp opened 2 years ago

alfianpp commented 2 years ago

Hello, I have a problem installing @vue/cli with volta I got a message like this after a successful install and want to run it,

'C:\Users\Alfian' is not recognized as an internal or external command, operable program or batch file.
volta install @vue/cli
success: installed @vue/cli@4.5.13 with executables: vue

volta which vue
C:\Users\Alfian Putra Persada\AppData\Local\Volta\tools\image\packages\@vue/cli\vue

This doesn't happen when installing anything else, for example firebase-tools

Thank you,

charlespierce commented 2 years ago

Hi @alfianpp, that's a tricky one. Base on the error, it looks like it might be related to the username having spaces in it (since it seems to think that only the part before the space is the command). However, what's confusing is that it's not happening for other tools. Volta handles all 3rd party tools effectively the same, so there shouldn't be any difference in behavior between e.g. @vue/cli and firebase-tools. If we were handling the path incorrectly, it would fail for all of those tools, since they're all installed in sibling directories.

The fact that it's failing makes me wonder if there's something internal in @vue/cli that is trying to execute a program and mishandling the spaces, which only shows up because Volta happens to use your home directory instead of a global directory without spaces.

Out of curiosity, could you try running the Vue CLI directly? Either by navigating to the directory that comes out of volta which vue or by running the JS file directly (I'm estimating what the path would be, but you need to find the @vue/cli/bin/vue.js file underneath the Volta image directory)?

node "C:\Users\Alfian Putra Persada\AppData\Local\Volta\tools\image\packages\@vue/cli\node_modules\@vue\cli\bin\vue.js"

That should help us understand if it's Volta mishandling the execution or something within Vue itself.

alfianpp commented 2 years ago

Hi @charlespierce, thanks for replying, I tried running the command you said and got this

node ""C:\Users\Alfian Putra Persada\AppData\Local\Volta\tools\image\packages\@vue\cli\node_modules\@vue\cli\bin\vue.js""

internal/modules/cjs/loader.js:985
  throw err;
  ^

Error: Cannot find module 'C:\Users\Alfian'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:982:15)
    at Function.Module._load (internal/modules/cjs/loader.js:864:27)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
    at internal/main/run_main_module.js:18:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}
charlespierce commented 2 years ago

Hi @alfianpp, sorry for the delay! Looking at that output, I think the issue is actually the combination of the spaces in the username and the name of the package including a scope: The spaces seem to turn the path into an exact path, so appending @vue/cli into it causes Volta to treat it as a folder name ("@vue/cli") instead of two nested folders ("@vue" and "cli").

Out of curiosity, if you navigate to the parent directory (C:\Users\Alfian Putra Persada\AppData\Local\Volta\tools\image\packages\) what folders do you see? Do you see @vue or @vue/cli? I'm guessing you'll see the former which means what Volta is doing to call the binary is incorrect. If I get a chance, I'll see if I can reproduce this locally.

hedgehog1029 commented 2 years ago

I'm also running into this issue, here's the rundown:

λ volta which vue
C:\Users\Henry Le Grys\AppData\Local\Volta\tools\image\packages\@vue/cli\vue

Actual path

so it looks like volta is constructing the command line badly. windows does support forward slashes in paths but it seems like mixing them is mucking something internal up? debug logs might help out here to see exactly where volta is failing...

you should be able to replicate this problem state with volta install @vue/cli

hedgehog1029 commented 2 years ago

okay well i did some investigating and it is not the mixed slashes. it is, in fact, a documented behaviour of cmd.exe:

If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:

    1.  If all of the following conditions are met, then quote characters
        on the command line are preserved:

        - no /S switch
        - exactly two quote characters
        - no special characters between the two quote characters,
          where special is one of: &<>()@^|
        - there are one or more whitespace characters between the
          two quote characters
        - the string between the two quote characters is the name
          of an executable file.

    2.  Otherwise, old behavior is to see if the first character is
        a quote character and if so, strip the leading character and
        remove the last quote character on the command line, preserving
        any text after the last quote character.

rust automatically surrounds arguments with quote characters on windows. since the folder name has an @, the quotes are stripped out of the command line, which then means that the command line is no longer treated as a single path to an executable and instead it trips up at the first space character.

i guess the solution to this is removing the @? presumably we need another way to differentiate scopes with subfolders from just regular unscoped packages...

a-bronx commented 2 years ago

Probably related: names of scoped packages installed by volta (e.g. volta install @types/node) are empty strings in the volta list output:

> volta install typescript ts-node eslint @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser
... (skipped) ...

> volta list
⚡️ Currently active tools:

    Node: v17.0.0 (default)
    Yarn: v1.22.17 (default)
    Tool binaries available:
         (default)
         (default)
         (default)
        eslint (default)
        ts-node, ts-script, ts-node-script, ts-node-cwd, ts-node-transpile-only (default)
        tsc, tsserver (default)

See options for more detailed reports by running `volta list --help`.

The 3 (default) lines above supposed to be something like @types/node (default), @typescript-eslint/eslint-plugin (default) and @typescript-eslint/parser (default)

If the volta list is not supposed to show packages without any binary tool in it, then these 3 lines should not appear at all, I guess.

mattisdada commented 2 years ago

I'm running into the same problem with a space in my username and several namespaced packages. My example is @salesforce/cli. My user path is C:\Users\Matt Work

> sf --version
'C:\Users\Matt' is not recognized as an internal or external command, operable program or batch file

> get-command sf

CommandType     Name                 Version    Source
-----------     ----                 -------    ------
Application     sf.exe               0.0.0.0    C:\Users\Matt Work\AppData\Local\Volta\bin\sf.exe

> cd C:\Users\Matt Work\AppData\Local\Volta\tools\image\packages\@salesforce\cli

cli > .\sf.cmd --version
@salesforce/cli/1.1.0 win32-x64 node-v14.18.1

cli > .\sf.ps1 --version
@salesforce/cli/1.1.0 win32-x64 node-v14.18.1

Running the cmd/ps1 directly out of packages does work, but running the shim fails.

charlespierce commented 2 years ago

@hedgehog1029 Wow that is a nice find! I agree the best solution is probably to find a different schema for scoped packages on Windows to completely avoid the problem.

Another possibility may be to remove the cmd /C wrapper that we use: It's been a long time since we switched, but I believe a major reason for doing that was because Rust's handling of launching Commands on Windows could lead to infinite recursion when the expected path didn't exist. However, in the interim, we added support for detecting and short-circuiting that recursion, so we may be safe to go back to calling commands directly (which I believe would also fix this issue).

AaronBeaudoin commented 3 months ago

Still running into this issue. First I run:

npm install -g @angular/cli

Afterwards I run ng and get:

'C:\Users\Aaron' is not recognized as an internal or external command, operable program or batch file.

If I run where.exe ng I get:

C:\Users\Aaron Beaudoin\AppData\Local\Volta\bin\ng
C:\Users\Aaron Beaudoin\AppData\Local\Volta\bin\ng.exe

If I run C:\Users\"Aaron Beaudoin"\AppData\Local\Volta\tools\image\packages\@angular\cli\ng.cmd --help:

ng <command>

Commands:
  ng add <collection>            Adds support for an external library to your project.
  ng analytics                   Configures the gathering of Angular CLI usage metrics.
  ng build [project]             Compiles an Angular application or library into an output directory named dist/ at the given output path.                                                                                                                                                [aliases: b]
  ng cache                       Configure persistent disk cache and retrieve cache statistics.
  ng completion                  Set up Angular CLI autocompletion for your terminal.
  ng config [json-path] [value]  Retrieves or sets Angular configuration values in the angular.json file for the workspace.
  ng deploy [project]            Invokes the deploy builder for a specified project or for the default project in the workspace.
  ng doc <keyword>               Opens the official Angular documentation (angular.io) in a browser, and searches for a given keyword.                                                                                                                                                    [aliases: d]
  ng e2e [project]               Builds and serves an Angular application, then runs end-to-end tests.                                                                                                                                                                                    [aliases: e]
  ng extract-i18n [project]      Extracts i18n messages from source code.
  ng generate                    Generates and/or modifies files based on a schematic.                                                                                                                                                                                                    [aliases: g]
  ng lint [project]              Runs linting tools on Angular application code in a given project folder.
  ng new [name]                  Creates a new Angular workspace.                                                                                                                                                                                                                         [aliases: n]
  ng run <target>                Runs an Architect target with an optional custom builder configuration defined in your project.
  ng serve [project]             Builds and serves your application, rebuilding on file changes.                                                                                                                                                                                          [aliases: s]
  ng test [project]              Runs unit tests in a project.                                                                                                                                                                                                                            [aliases: t]
  ng update [packages..]         Updates your workspace and its dependencies. See https://update.angular.io/.
  ng version                     Outputs Angular CLI version.                                                                                                                                                                                                                             [aliases: v]

Options:
  --help  Shows a help message for this command in the console.                                                                                                                                                                                                                              [boolean]

For more information, see https://angular.io/cli/.

So the command itself works just fine. But when running through Volta it doesn't work.

charlespierce commented 3 months ago

Hi @AaronBeaudoin, thanks for the extra info, I think I have an idea what's going on! Are you by chance using Git Bash (or a similar Bash emulator) to execute ng? We install a shim for Git Bash specifically (named the same as the command but without the .exe extension) since it has some unintuitive behavior (see this comment for more details).

That shim calls cmd.exe using $0 as the first argument, which is the path to the current executable. However, it mistakenly isn't quoting that argument, so when there is a space in the path, it's not interpreted correctly. As a quick check, if you edit the C:\Users\{username}\AppData\Local\Volta\bin\ng script to the following, does it work?

cmd //C "$0" "$@"

(Which should be only adding quotes around $0)