joefiorini / vruby

38 stars 0 forks source link

Rewrite in Go #3

Closed joefiorini closed 9 years ago

joefiorini commented 9 years ago

For better cross-platform support and easier installation, this should be written in a compiled language. Go is probably the simplest language with the best cross-platform support therefore it seems the best choice.

samdunne commented 9 years ago

So after looking into some options it seems this would be the framework to try and use: https://github.com/codegangsta/cli

I can look at some basic implementation if you like

joefiorini commented 9 years ago

I've used https://github.com/mitchellh/cli before, that's what I was going to use. Honestly either would be fine. If you want to take a stab at starting this implementation and send a PR that would be awesome. I'm probably not going to have much time this weekend to work on this. Just make sure you keep the examples directory and that they continue to work. Thanks!

joshgoebel commented 9 years ago

Not against Go at all I wonder if Bash is more accessible to most users for contributing, etc?

joefiorini commented 9 years ago

@yyyc514 I definitely appreciate that thought. I think there's a tradeoff between runtime vs. dev-time optimizations. Bash might make it easier to develop & accept contributions, but Go would make it easier to run on multiple platforms, especially Windows where bash is less likely to come by. Another advantage of a compiled language is that a compiled binary is more portable (able to be moved around/run from anywhere) than a shell script.

Plus (IMO) bash is just not that great of a language to code in, but it's great for prototyping!

joshgoebel commented 9 years ago

Oh, I'm no bash lover. I'd prefer Ruby or Python but then you're right back to chicken-before-egg and portability, etc.

Just thought I'd mention it.

joshgoebel commented 9 years ago

I think if you care at all about contributions from the larger Ruby community you should consider allowing this to be retooled in Ruby. virtualenv is written in Python. Only the shell tools (activate, deactivate, etc) are zsh, bash, etc... of course that does require an installed version of the language in question, but I'm not sure that is a truly onerous requirement for a developer of that language.

joefiorini commented 9 years ago

Obviously I have my opinion on this topic, but I don't want to make this decision without more input from the larger community. The question comes down to should vruby be written in a language that compiles to native code or one that is interpreted.

The Use Case

I've been developing vruby with a primary use case in mind: developers who don't use Ruby as their primary language, but switch a lot. There are a lot of developers (myself included) these days who just write javascript but have to jump into Ruby projects occasionally. I feel these developers would be best served with a tool that requires:

(1) Does absolute minimal work required to host ruby versions

One of the biggest problems I've had with the existing version management options is troubleshooting installations, starting with determining if it's a problem of the version manager, the ruby installation or a gem. This would be much easier if the version managers did a little less. No gemsets, no magic commands for version switching, no overriding cd to auto switch. Using this workflow, if I run into a problem while working on a project I know it's either a problem in Ruby or a gem. I can kill all my gems with rm -rf .gem and start over. I can reset my environment by opening a new Terminal window.

(2) Very simple installation via platform package manager

That way installation/uninstallation is simple, predictable and easy. No messing around with piping potentially unsafe scripts from the web or wondering how to uninstall a library after it's installed.

(3) Cross platform support

Runs on Windows and *nix with a minimum of compromises/disorganized code for platform support

(4) Does not require any setup steps to begin using

If Ruby isn't my primary language, I don't want to be adding stuff to my dotfiles just because some project I work on requires Ruby.

(5) Isolates gem dependencies within the given project

To make it easy to start from scratch/troubleshoot when I run into problems

(6) Offers the ability to isolate the Ruby interpreter in the given project

Same as previous, plus the added makes it much more likely that the project will continue to run after years of sitting on a backup drive without having to setup an environment for it again

(7) Uses binary ruby distributions

This may be a bit ambitious at this point, but projects like Tokaido have made it possible to have a purely binary Ruby distribution, which takes installation of new versions down from 10-20 minutes (quite often more than that on slower machines) to literally seconds. A binary distribution also lowers the risk of platform issues, since someone has already worked out dependency issues in order to build the binaries.

Thoughts on Implementation

My thinking has been that a compiled language would make it easier to achieve both (1) and (2) above. I know there is no silver bullet with regards to cross-platform support, but a compiled language would at least help make sure the binary is runnable on other platforms regardless of language support.

I'm certainly open to other thoughts on this. I'm open to any solutions as long as we meet the use cases outlined above. Whatever decision we make, I do not want to stick with bash long term. I'm not very happy with how the existing shell script is going, and would like to clean it all up.

joshgoebel commented 9 years ago

(5) Isolates gem dependencies within the given project

That's what everyone uses Bundler for these days... I specifically use it where it installs the gems local to a project (vs to the system) so I can just zap the bundle whenever I want... the same way you're zapping .gem... of course Bundler still works with your approach, since you're giving each project it's own gem path. It's like gemsets on steroids. :-)

(7) Uses binary ruby distributions

This is nice-ish, but I wouldn't get super caught up in it as an exclusive (vs nice option). Getting Ruby compiled isn't at all hard these days. We have things like ruby-build. In fact I think it'd be helpful if the docs mentioned you could just as easily use a source-built version of ruby with vruby as a pre-built. vruby really shouldn't care about how the ruby was built... as long as it knows where to find it.

Just:

ruby-build ree-1.8.7-2012.02 /opt/vruby/share/ree-1.8.7/
vruby vruby --version ree-1.8.7

No gemsets, no magic commands for version switching, no overriding cd to auto switch.

I actually like the cd auto stuff, but I think that can be a separate small tool that engages the appropriate environment when changing directories - it doesn't have to be part of the environment system itself. I like minimal stuff (that's why I switched from rvm to rb-env long ago) and binstubs are starting to annoy me - that's why I've taken an interest to vruby.

joshgoebel commented 9 years ago

I'm not sure cd project is honestly any better than workon project (or similar), it's just what I've gotten spoiled by. I don't mind magic as long as either I understand it (and it mostly works) or it always works, one or the other. :-)

This whole thing has me thinking about the idea of some over-arching env tool that worked across multiple languages, vs just a single tool per language. Or maybe framework is a better word than tool.

joefiorini commented 9 years ago

This whole thing has me thinking about the idea of some over-arching env tool that worked across multiple languages, vs just a single tool per language.

That thought has crossed my mind too. I'm not sure yet what a tool like that would look like, but I really like the idea. Maybe this project will help us realize that.

joefiorini commented 9 years ago

That's what everyone uses Bundler for these days... I specifically use it where it installs the gems local to a project (vs to the system) so I can just zap the bundle whenever I want... the same way you're zapping .gem

I started doing that too a couple years ago, up until I stopped doing Ruby full time. I'm basically trying to make that workflow even more automatic, without having to worry about using bundle exec or keeping extra bin directors on PATH.

This is nice-ish, but I wouldn't get super caught up in it as an exclusive (vs nice option). Getting Ruby compiled isn't at all hard these days. We have things like ruby-build. In fact I think it'd be helpful if the docs mentioned you could just as easily use a source-built version of ruby with vruby as a pre-built. vruby really shouldn't care about how the ruby was built... as long as it knows where to find it.

Agreed, we should have a BYO Ruby workflow to handle this. The only thing that we need to think about is how we would accomplish goal 6 above with a compiled Ruby. There is no way to copy/move a Ruby once it's compiled somewhere. That's why projects like Tokaido & Traveling Ruby exist.

I like minimal stuff (that's why I switched from rvm to rb-env long ago) and binstubs are starting to annoy me - that's why I've taken an interest to vruby.

:smile: Same here. I've also been developing a general distaste for libraries that are global and require dotfile changes when I set them up (unless of course it makes sense).

joshgoebel commented 9 years ago

I'm basically trying to make that workflow even more automatic, without having to worry about using bundle exec or keeping extra bin directors on PATH.

Well I'm trying to figure that out now - because bundle exec actually does a LOT more than that... it isolates specific gem versions and their binaries... so if I checkout a branch, develop a new feature, bump a few gems, bundle install... then git checkout a different branch and then bundle exec gem will always pick the right version (regardless of which branch i'm in).

So with bundler you can have 2 versions of gem xyz installed and working on 2 different branches and your project and bundle exec will always choose the right version of the gem (because they are all installed).

Without bundler you're left with 2 versions installed and running the binary is likely going to pick the latest (I think). Of course if you use vruby + bundler your actually Ruby code will require the right stuff... but you still have to do bundle exec for binaries to guarantee the right binary.

This might not matter for simple projects, but it's definitely a workflow concern in larger projects I've worked on (when upgrading gems in a branch).

Right now I use rb-env and rbenv-bundler which creates binstubs for all gems that tie into the bundler framework... so rake works instead of bundle exec rake (which I hate), but I'm trying to think of a nice way to have all the benefits listed above without the binstubs - think it's a tough problem.

joefiorini commented 9 years ago

So what exactly does bundle exec do under the hood? I assume it's going to set the GEM_PATH env var to make the correct version of the gem is at the front of the list. We could probably find out by writing a Ruby script that prints ENV['GEM_PATH'] and then running it with & without bundle exec.

Assuming that's the case, there are really 2 options I'm aware of for setting env vars automatically:

  1. Use a wrapper script (ala binstub) or command (bundle exec) to set the env car before running the script
  2. Have a script that can be manually sourced before running commands that looks up gem versions and exports variables (ala the bin/activate script vruby generates)

Would it help if we made that script smart enough to take the current bundler environment into account?

joefiorini commented 9 years ago

Would it help if we made that script smart enough to take the current bundler environment into account?

A consequence of that would be that you'd have to source the script every time you switch branches. Not very automatic, but it would get you away from binstubs & bundle exec.

joshgoebel commented 9 years ago

You considered Crystal (http://crystal-lang.org)? Compilable to native - very familiar for anyone using Ruby.

joshgoebel commented 9 years ago

And nope, nothing to do with Gem path:

http://bundler.io/v1.3/man/bundle-exec.1.html

I think it just sets up the paths inside ruby (since it's Ruby itself) and then runs the ruby in the executable you mentioned (in the context of the paths that it just setup in the running session). That's how I read between the lines with only a glance just now.

joshgoebel commented 9 years ago

Because it does more than just point to a directory of gems... you might have installed 3 versions of "super" but your Gemfile might say super version 2... so that will be in the Ruby load path, but not super 1 and super 3.

joefiorini commented 9 years ago

I have a couple other ideas around this. I think it's too soon to decide on this just yet. It would be interesting to explore a system written in a single language that can generate a structure similar to vruby/virtualenv for any platform. I get the feeling Haskell's parsec might be a good fit for that. I'm closing this so we continue testing the idea with vruby.