Hacker News new | comments | show | ask | jobs | submit login

Which is exactly why it's a terrible idea. There is no "super" mechanism in Bash. Imagine if the Perl, Python and Node equivalents of rvm overrode cd -- they'd all have to be aware of each other's existence in order to play together nicely.

Overriding cd for dependency injection purposes is like killing a fly with a machine gun. It's completely inappropriate for the task at hand, and it's precisely the kind of problem that $PATH is designed to solve.

Furthermore, rvm breaks the expected behavior of the cd command by prompting you with security theatrics the first time you enter a project with an .rvmrc file: https://gist.github.com/34c251a56e83c61c667e This kind of thing wreaks havoc with third-party programs that attempt to interface with rvm. I've had to deal with far too many bug reports in Pow as a result of this messy behavior.

This is not some theoretical concern. It's just bad design.




(in bash, OSX) if I type

  $ type cd
    cd is a function
    cd () 
    { 
      builtin cd "$@";
      local result=$?;
      __rvm_project_rvmrc;
      __rvm_after_cd;
      return $result
    }
I don't really understand what happens, but the "builtin" looks like some sort of "super", e.g. call original cd, which would allow to chain multiple overrides, no?


No. Builtin does just that. It calls the implementation built into the shell, so that's the original plain cd.

If two utilities provide their cd(), the last loaded one wins. builtin cd is always the plain built in one.

You would need to check whether cd is already overridden, then rename that cd to something else and call that instead of builtin. If it's at all possible to rename functions in bash (I don't know)


> Which is exactly why it's a terrible idea. There is no "super" mechanism in Bash. Imagine if the Perl, Python and Node equivalents of rvm overrode cd -- they'd all have to be aware of each other's existence in order to play together nicely.

That would be a problem until rvm fixed it. Then its users would have to update it. It's not ideal, I know, but rvm is very much an active solution. Because it's used to install rubies, which get updated, its users update it.

That's one great thing about rbenv: it's easier to write, and thus easier to write clones. I'm looking forward to seeing a node.js developer adopting your shim approach. By the way, I'm glad they're plain sh scripts, so I can still use Xavier Shay's technique for making no-dependency ruby scripts fast. The rubygems wrapper scripts run a lot of code and don't provide a convenient option to skip it if it's not needed. By the way it would be cool if, with a plugin of sorts, reshim could remove require 'rubygems'. It could get people running more than one ruby CLI tool at a time (with pipes and/or backquotes) more often by shaving off the approximately half-second rubygems load time.

https://github.com/xaviershay/xtdo

> Overriding cd for dependency injection purposes is like killing a fly with a machine gun. It's completely inappropriate for the task at hand, and it's precisely the kind of problem that $PATH is designed to solve.

I like your shim approach but while it may be obvious to you, I found it quite clever. I think virtualenvwrapper could use it. I don't think it was like killing a fly until you introduced this idea, which most of us hadn't heard of or considered.

> Furthermore, rvm breaks the expected behavior of the cd command by prompting you with security theatrics the first time you enter a project with an .rvmrc file: https://gist.github.com/34c251a56e83c61c667e This kind of thing wreaks havoc with third-party programs that attempt to interface with rvm. I've had to deal with far too many bug reports in Pow as a result of this messy behavior.

You were using it in a different way than most, up until you wrote pow, and found a weak point. The trust database should have a way to inspect it, and it should have been documented. It's frustrating, I know.

> This is not some theoretical concern. It's just bad design.

I don't think the rvm, virtualenv, or virtualenvwrapper developers particularly liked designing (or attempting to design) this part of their system. If they could have skipped out on this feature and still have the benefit, I think they would have. I'm glad you found a path that you enjoyed taking to solve this problem.

By the way I'm a happy pow user and I'm glad you wrote rbenv since it makes pow easier for you to support and maintain. I hope it helps me to use my rvm-installed rubies with pow.


How would you get the same behavior of project base .rvmrc files without hijacking cd?


By using a shim approach, like rbenv.

1. Maintain a directory of shim binaries with the same name as every Ruby binary (ruby, irb, rake, gem, etc).

2. Put the shim directory at the front of your $PATH.

3. When a shim is run (as in typing `rake` from the command line or running a script with a `#!/usr/bin/env ruby` shebang), check for a version file in the current directory or any parent directory, map that to the right path, and re-exec the corresponding binary.


Doesn't this solution not scale? Doesn't this mean a shim must be created for every gem that I install that has a binary? Or is this only required for "core" binaries?


`ls -l /usr/bin | wc -l` reports 1085 entries on my machine. Meanwhile, I have 40 entries in my ~/.rbenv/shims directory. I think the shell can handle it.


I'm sorry, I was not aware of the 'rehash' function, I thought rbenv would have to ship with all the required shims. The rehash functionality is quite clever and cool. Is there an easy way to have that automatically execute after I do any installation of a ruby or gem?


Couldn't you also use $PROMPT_COMMAND? This gets executed right before showing the prompt, so cwd would already have been called and it would be much easier to chain.

Of course you'd run more often than when hooking cd, but just checking for a new .rvmrc isn't so expensive.

The problem would probably be that you wouldn't get called from within scripts (there is no prompt there), but that could also be an advantage because it would ensure that a scripts cd would continue to work "headless".

I'd have to look into this and really see what rvm actually needs the hook for. As such I'm just thinking loudly at the moment.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: