nvm-sh / nvm

Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions
MIT License
79.76k stars 7.99k forks source link

Move most logic out of sourced bash function #337

Open creationix opened 10 years ago

creationix commented 10 years ago

I fear putting a lot of functionality into a bash function. It's a very tricky environment and people like to use nvm in places like zsh that are mostly compatible.

The only thing we need a bash function for is modifying the current $PATH. Everything else has permanent side effects (like downloading and installing node, copying packages, creating symlinks, etc) and can be done in a subshell where you can choose bash (or node or python) in your shebang line.

For maintainability, I think it would be nice to move all logic out of the main nvm.sh as possible into standalone scripts that are called from the main function.

Comments?

creationix commented 10 years ago

Also I've been playing with fish which is entirely incompatible with nvm because it's language is not a bash dialect. It would be cool if I could use most of the code from nvm in my fish environment and only rewrite the bits required to make it work in fish.

ljharb commented 10 years ago

Making it more portable seems like a great idea.

creationix commented 10 years ago

We could have a platform/shell independent core with a defined scripting language and then various frontends for different platforms. They could be optimized for OSX sh, linux bash, zsh, fish, even windows cmd.exe.

The part I'm not clear on is what should the shared logic be written in? I guess bash would be a good choice for all but windows, but I'd really like to be able to have node itself used for a lot of this work. Things like parsing JSON are much easier in a JS environment than in bash. But then you have the chicken-and-egg problem of needing node to install node.

lua + libuv https://github.com/creationix/luv seems like a pretty good fit except for the fact that the binaries would be platform dependent. Python isn't too bad either, but I hate needing python to install a js runtime.

Ideas?

ljharb commented 10 years ago

Let's just write it in JS! https://github.com/arturadib/shelljs

ljharb commented 10 years ago

altho that would require node :-p

koenpunt commented 10 years ago

I like how rbenv is working. But I'm not sure if that is bash specific or that it works in every shell..

sanderhahn commented 10 years ago

Just looked into how rbenv works. Rbenv uses "eval $(script)" instead of "source script.sh". The script generates commands that are executed in the parent shell. Generated commands such as export/alias are simple and work in all shells. I took the liberty of doing a minimal nvm clone using this approach in: https://github.com/sanderhahn/nodenv/blob/master/nodenv and it seems to work. The script downloads binaries and adjust paths accordingly and lacks the more advanced management features.

Downloading a stable node binary to bootstrap nvm using a module seems like an attractive option. Each time when a new node binary is downloaded using nvm, it could trigger installing the nvm module once again. Or make an alias that always runs the nvm module against the initial downloaded node. Advantage is that the bootstrap shell code is minimal and the management code is portable javascript.

sanderhahn commented 10 years ago

Lua + libuv: lua doesn't seem to support json natively? Would be nice to have a luvit/luajit/luarocks binary distribution available like nodejs. Perl is available on most unix systems and is way more powerful that sh scripting :)

focusaurus commented 10 years ago

but I hate needing python to install a js runtime

Well, technically you don't need python for just the node repl, but once your project needs an npm package with binary add-ons, don't you always end up needing python because node-gyp requires it? If you are going to have another dependency, python seems like the best candidate to me. The version that comes with OSX and Linux is generally suitable for this purpose. I can say for sure if you add something less mainstream than node like lua, I'm out.

koenpunt commented 10 years ago

@focusaurus +1

Also, is there a compatibility table or something for rbenv support?

mgol commented 10 years ago

rbenv introduces overhead because of all this shim handling and can introduce issues. I like that nvm is simple prepending to $PATH, not a lot of potential to break.

I don't know a lot about rbenv but I'd be cautious before changing the way nvm works too much. See: https://twitter.com/jcoglan/status/453188831584718848 and: https://twitter.com/jcoglan/status/453250500117680129

qfox commented 9 years ago

I think it should be something simple with some windowsfier that will transpile sources to cmd or powershell and also something for mac os x shell.

It will work only if we will have CI with a testing environment for most of supported platforms and shells.

It can be even simplified ES3-like code with a bunch of transpilers and helpers in core (proxies or c-like templates) to make a magic based on Esprima or something. Probably it should be a separate project ;-\

What you think?

edit: Probably shelljs is a good point to start.

Also you should take a look at https://github.com/BYVoid/Batsh — I think it's almost what we want. It needs to make some fixes for our purposes probably. But it already has bash and bat support.

underbluewaters commented 8 years ago

This is more of an issue on slower platforms. For example, my Raspberry PI 2+

root@barry:/home/pi# time source /home/pi/.nvm/nvm.sh

real    0m14.941s
user    0m11.300s
sys 0m1.340s
ljharb commented 8 years ago

fwiw, making any progress on this is blocked by #400 - I don't want to make any structural changes until there's an easy way for people to auto-update.