Introduction
"The most effective debugging tool is still careful thought, coupled with judiciously placed print statements." — Brian Kernighan, Unix for Beginners.
"Don't chase your dreams. Humans are persistence predators. Follow your dreams at a sustainable pace until they get tired and lie down." – @raven.corvids.club (on BlueSky)
Background
What's the first thing that happens when you type bundle install
into the terminal and hit "Enter"?
This is the question which set me off on this entire project. For those unfamiliar with the bundle install
command, it comes from the Bundler library. Bundler provides "a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed", according to its website.
Professionally, I work on a large Rails codebase with many contributors, and bundle install
is one of the most common commands we find ourselves typing. I was frustrated that I didn't know how this command worked under-the-hood. Since I'm a big believer that "The best way to learn something is to explain it to someone else", I decided to blog about what I was learning, as I learned it.
As it turns out, my deep-dive took me on a detour into the code for my Ruby version manager. That version manager, named RBENV, creates shim files for every Ruby command you enter, including bundle
. Therefore, the first file I encountered in my deep-dive was this shim.
In the process of exploring this shim file (and RBENV's code in general), I ended up learning a lot about the UNIX shell and Bash, the language RBENV is written in. At the risk of sounding like I'm backwards-rationalizing, I'd argue this is actually more useful than learning about Bundle, since Bash is much more broadly-used than Bundle.
Along the way, I kept a journal of all my wins, my frustrations, my questions, my a-ha moments, etc. The document you're reading is an edited version of that journal.
Disclaimer
This is NOT an official guide to RBENV's codebase. I am *not* a member of the RBENV core team, nor is this guide endorsed by the core team in any way. It is simply the (sometimes incorrect) educated guesses of a journeyman engineer who wants to attain mastery by teaching what he's learning. Please treat what you read here accordingly.
If you spot any errors or omissions, let me know at impostorsguides [at] gmail.
Table of Contents
- Part 1: The RBENV Shim
- Introduction
- Shebangs
- The 'set' Command
- The 'test' Command
- Verbose Mode
- Setting the Name of the User's Program
- 'if'-blocks
- 'for'-loops
- 'case'-statements
- Case 1: When we don't care about the args
- Case 2: When the argument is a filepath
- Setting the Correct Ruby Version
- Executing The User's Command
- Conclusion
- Part 2: The `rbenv` command (work-in-progress)
- Introduction
- The RBENV test harness
- Setting debug mode via "xtrace"
- Creating our first helper function, 'abort'
- Dynamically loading helper libraries
- Resolving paths
- Setting environment variables
- Importing plugins and sourcing configuration files
- Making hooks available to commands
- Running a specific RBENV command
- rbenv Summary
- Part 3: The `rbenv init` command (work-in-progress)
- Tests for `rbenv-init`
- Completions, Local Vars, and Specifying The Shell
- Printing init instructions
- Initializing directories, setting env vars, sourcing completions, rehashing gems
- Defining the "rbenv" shell function in `fish`
- Tying up loose ends in the shell function
- Why Use (Or Not Use) Shell Integration In RBENV
- Pros And Cons Of The 4 Shells
- init Summary
- Part 4: Other RBENV Commands (work-in-progress)
- Commands- Introduction
- 'rbenv --version'
- rbenv-commands
- rbenv-hooks
- rbenv-completions
- rbenv-exec
- rbenv-global
- rbenv-help
- rbenv-local
- rbenv-prefix
- rbenv-rehash and rbenv-sh-rehash
- rbenv-root
- rbenv-sh-shell
- rbenv-shims
- rbenv-version
- rbenv-version-file
- rbenv-version-file-read
- rbenv-version-file-write
- rbenv-version-name
- rbenv-version-origin
- rbenv-versions
- rbenv-whence
- rbenv-which
- rbenv-echo
- Commands Summary
- Part 5: Infrastructure Files (work-in-progress)