bundle exec bash
The bundler README
makes passing mention of bundle exec bash—when you bundle
everything, you want to avoid typing bundle exec rake all the
time.
Here are 3 tips to help you enjoy the experience:
Sort your .bashrc from your .profile
The first time I ran bundle exec bash, I lost the git branch from my prompt:
~/Code/captain master* bundle exec bash
bash: __git_ps1: command not found
~/Code/captain
Poring through the documentation for the bash startup files, here’s what I pieced together:
-
Terminal.applaunches a “login” shell, which reads~/.profile. -
The shell launched by
(bundle exec) bashis not a login shell, so it reads~/.bashrcinstead. (Moreover, it only inherits the environment variables of its parent shell, none of the functions, aliases, or completions.)
Connecting the dots, you’ll want to:
-
Move all your aliases, functions and completions out of
~/.profileand into~/.bashrc. (example) -
Source your
~/.bashrcat the bottom of your~/.profile:
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
And then you should have __git_ps1 and friends again:
~/Code/captain master* bundle exec bash
~/Code/captain master*
Beware the RUBYOPT
What you can’t see in the prompt above is the next problem I ran into. I should have written something more like this:
~/Code/captain master* bundle exec bash
... THREE SECOND DELAY ...
~/Code/captain master*
Here’s what’s going on:
-
__git_ps1callsgit5 or 6 times. -
I had mixed (the non-rubygems version of)
hubintogitwithalias git=hub. -
bundle execadds-rbundler/setupto yourRUBYOPT.
Boom! I was resolving the dependencies in my Gemfile 5 or 6 times
just to generate a prompt!
The simple workaround is to clear RUBYOPT when calling hub:
alias git='RUBYOPT= hub'
Show the bundle in your prompt
It gets hard to remember if you’ve already run bundle exec bash,
or, if you tend to cd wildly all over the place, which
project you ran it in.
With this function in your ~/.bashrc:
function __bundler_ps1 {
if [ -n "${BUNDLE_GEMFILE-}" ]; then
project_path="${BUNDLE_GEMFILE%/Gemfile}"
project_name="${project_path##**/}"
if [ -n "${1-}" ]; then
printf "$1" "${project_name}"
else
printf " (%s)" "${project_name}"
fi
fi
}
And a PS1 setting in your ~/.profile that calls it:
export PS1='\[\e[36m\]$(__bundler_ps1 "[%s] ")\[\e[0m\]\w\[\e[35m\]$(__git_ps1 " %s")\[\e[0m\] '
You’ll see the name of the active bundle in your prompt:
~/Code/captain master* bundle exec bash
[captain] ~/Code/captain master*
Conclusion
It seems like the main thing I’m learning is that it’s worth spending time
tinkering with your $SHELL.
Along the way, I’ve found it immensely helpful to version my dotfiles. If you haven’t done
that yet, make it your weekend project—you’ll love the freedom it gives
you to experiment! I found Joe
Ferris’ install.sh quite helpful as I got started.