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.app
launches a “login” shell, which reads~/.profile
. -
The shell launched by
(bundle exec) bash
is not a login shell, so it reads~/.bashrc
instead. (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
~/.profile
and into~/.bashrc
. (example) -
Source your
~/.bashrc
at 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_ps1
callsgit
5 or 6 times. -
I had mixed (the non-rubygems version of)
hub
intogit
withalias git=hub
. -
bundle exec
adds-rbundler/setup
to 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.