Would it be feasible to add support for using NTFS junctions rather than mklink
for swapping out the in-use version of node?
Junctions are great because they do not require elevated permissions, which would allow nvm-windows
to be used on (effectively) headless machines, such as build agents. The disadvantage is that they cannot be created across drive letters, but this is an acceptable limitation.
Maybe this could be implemented as a configuration flag and disabled by default. Thoughts on that?
Another point in favour of junctions: they are used by npm
on Windows when using npm link
, so it is already common in the Windows/node world.
I'll consider it for the next version (which I'm working on as time allows). I almost did this for the first releases, but I had a number of requests for cross-drive support, so I'm not sure if this is an acceptable limitation... but the idea of keeping it behind a flag is viable.
symbolic links are more flexible in the targets they support. see mklink.
symbolic links are more flexible in the targets they support. see mklink.
some of are using workin machines though that restrict certain admin actions such as mklink
@edclement Not good for Dev PCs at all. Fight for freedom :)
@edclement - there is literally nothing that can be done if mklink isn't allowed by enterprise policy. I believe this would also affect npm. The entire premise of this project is based on the use of linked directories.
@coreybutler - I use npm link
often. It actually uses junctions. It may be the case that it falls back to using windows junctions when it can't create a symlink. Not sure. I feel like nvm should do the same.
@edclement, @coreybutler I'm reasonably sure that npm link
uses junctions by default (which can be done with mklink /J
, btw). Otherwise, linking would have to be done in an elevated console or npm
would ship with an elevation script, similar to this project.
there is literally nothing that can be done if mklink isn't allowed by enterprise policy
This is true, but I would be surprised if the mklink
executable itself was disallowed. It's just the /D
(create symbolic link) option that requires administrator privileges.
In my original issue description, I suggested toggling use of junction points with a flag, but I now think it should be the default option whenever the source & target drive letters are the same. But I'd be happy either way 馃槃
It does look like npm is using junctions for links, and it also looks like npm suffers from the same issue nvm4w would if it were installed on a separate partition.
I still like the idea of toggling, and I like @jgoz's follow up comment about checking the drive letters. I'm 99% sure I'll implement at least a toggle/flag if I can't find a better alternative to mklink.
modified elevate.cmd as a quick fix if you really need it
@setlocal
@echo off
set CMD=%*
set APP=%1
set newCMD=%CMD:mklink /d=mklink /j%
IF "%newCMD%" == "%CMD%" (
start wscript //nologo "%~dpn0.vbs" %* & exit
) ELSE (
%newCMD%
)
I'm reposting this here since I inadvertantly merged it into the wiki some time ago. Written by Burt Harris:
On Windows, a NTFS junction point can generally be created and deleted without any special privileges; junction points were created as a safer alternative to directory symlinks. If nvm-windows switched its implementation to use NTFS junction points, it could would be simpler, more usable, and present lower security risks.
Using NTFS junctions is really simple, this should give you the idea:
C:\demo>dir
Volume in drive C has no label.
Volume Serial Number is 4C7F-6408
Directory of C:\demo
07/09/2016 02:34 PM <DIR> .
07/09/2016 02:34 PM <DIR> ..
07/09/2016 02:31 PM <DIR> version.1
07/09/2016 02:28 PM <DIR> version.2
0 File(s) 0 bytes
4 Dir(s) 350,868,033,536 bytes free
C:\demo>mklink /j nodejs version.1
Junction created for nodejs <<===>> version.1
C:\demo>type nodejs\test.txt
This is version 1's test.txt
C:\demo>
C:\demo>rd nodejs
C:\demo>mklink /j nodejs version.2
Junction created for nodejs <<===>> version.2
C:\demo>type nodejs\test.txt
This is version 2's test.txt
As can be seen below, a junction point presents a much more understandable directory listing
C:\demo>dir
Volume in drive C has no label.
Volume Serial Number is 4C7F-6408
Directory of C:\demo
07/09/2016 02:35 PM <DIR> .
07/09/2016 02:35 PM <DIR> ..
07/09/2016 02:35 PM <JUNCTION> nodejs [C:\demo\version.2]
07/09/2016 02:31 PM <DIR> version.1
07/09/2016 02:28 PM <DIR> version.2
0 File(s) 0 bytes
5 Dir(s) 350,868,033,536 bytes free
Ideally, one user on a machine installing or removing nvm-windows or Node.js versions using the tool shouldn't effect any other user's experience on the same machine. For this reason, installing junctions in C:\Program Files would still require and administrator. But per-user tools can generally be installed under the path in the APPDATA environment variable, and that's where the per-user nvm junction point should be located. Similarly user-specific NVM_HOME, NVM_SYMLINK and PATH environment variables are preferable to machine-wide ones.
Most helpful comment
I'm reposting this here since I inadvertantly merged it into the wiki some time ago. Written by Burt Harris:
Elevator pitch for Junction Points
On Windows, a NTFS junction point can generally be created and deleted without any special privileges; junction points were created as a safer alternative to directory symlinks. If nvm-windows switched its implementation to use NTFS junction points, it could would be simpler, more usable, and present lower security risks.
The demo
Using NTFS junctions is really simple, this should give you the idea:
As can be seen below, a junction point presents a much more understandable directory listing
Completing the picture
Ideally, one user on a machine installing or removing nvm-windows or Node.js versions using the tool shouldn't effect any other user's experience on the same machine. For this reason, installing junctions in C:\Program Files would still require and administrator. But per-user tools can generally be installed under the path in the APPDATA environment variable, and that's where the per-user nvm junction point should be located. Similarly user-specific NVM_HOME, NVM_SYMLINK and PATH environment variables are preferable to machine-wide ones.