Chris Frederick

Beta Testing Octopress 2.1

I've been meaning to update this blog to Octopress 2.1 for some time now (mainly to use its linklog feature), but I kept procrastinating because I was intimidated by the prospect of diving back into Git and Rake commands to do so. When I finally decided to get my hands dirty the other day, I ran into problems—as I had feared—and ended up spending a few hours debugging. I'm writing this blog post to document the process.

I'd like to emphasize that I am entirely aware that I am using beta software (caveat emptor) and that, consequently, I do not intend for this to reflect negatively on Octopress in any way. I love Octopress because it allows me to write a nice, professional-looking blog using nothing but simple, elegant Markdown. In fact, I want to document my experience with the 2.1 branch to make it easier for other people to use it, too.

Okay, are you with me now? Let's get started.

Rake Tasks Have Changed

After upgrading to the 2.1 branch of Octopress, I tried running rake update_source and rake update_style (according to the instructions given by the documentation for the 2.1 branch) and was somewhat surprised to find that these tasks don't work any more. Curious, I used rake -T to get a list of all the available rake tasks. As it turns out, there are a lot of them.

Octopress 2.1 Rake Tasks
rake clean # Clean out caches: .pygments-cache, .gist-cache, .sass-cache, and Compass-generated files.
rake clobber # Remove generated files ( directory).
rake deploy # Default deploy task
rake gen_deploy # Generate website and deploy
rake generate # Generate jekyll site
rake generate_only[filename] # Generate only the specified post (much faster)
rake install[theme] # Initial setup for Octopress: copies the default theme into the path of Jekyll's generator.
rake install_javascripts[theme] # Install javascript assets for a theme
rake install_stylesheets[theme] # Install stylesheets for a theme
rake integrate # Move all stashed posts back into the posts directory, ready for site generation.
rake isolate[filename] # Move all other posts than the one currently being worked on to a temporary stash location (stash) so regenerating the site happens much more quickly.
rake list_drafts # List all unpublished/draft posts
rake new_page[filename] # Create a new page in /(filename)/index.
rake new_post[title] # Begin a new post in /
rake preview # preview the site in a web browser.
rake push # deploy public directory to github pages
rake rsync # Deploy website via rsync
rake set_root_dir[dir] # Update configurations to support publishing to root or sub directory
rake setup_github_pages[repo] # Set up _deploy folder and deploy branch for GitHub Pages deployment
rake test # Run tests
rake update[theme] # Update theme source and style
rake update_javascripts[theme] # Move javascripts to .old/javascripts, install javascripts theme updates.
rake update_stylesheets[theme] # Move stylesheets to stylesheets.old, install stylesheets theme updates, replace stylesheets/custom with stylesheets.old/custom
rake update_template[theme] # Move source to source.old, install source theme updates, replace source/_includes/navigation.html with source.old's navigation
rake watch # Watch the site and regenerate when it changes

The following tasks are new:

New Octopress 2.1 Rake Tasks
rake clobber # Remove generated files ( directory).
rake install_javascripts[theme] # Install javascript assets for a theme
rake install_stylesheets[theme] # Install stylesheets for a theme
rake update_javascripts[theme] # Move javascripts to .old/javascripts, install javascripts theme updates.
rake update_stylesheets[theme] # Move stylesheets to stylesheets.old, install stylesheets theme updates, replace stylesheets/custom with stylesheets.old/custom
rake update_template[theme] # Move source to source.old, install source theme updates, replace source/_includes/navigation.html with source.old's navigation

The following tasks have been removed:

Deprecated Octopress 2.0 Rake Tasks
rake list # list tasks
rake minify_and_combine # Minifies the specified javascripts
rake update_source[theme] # Move source to source.old, install source theme updates, replace source/_includes/navigation.html with source.old's navigation
rake update_style[theme] # Move sass to sass.old, install sass theme updates, replace sass/custom with sass.old/custom

Of particular interest to me were the changes to the update_* tasks. Specificaly, update_source and update_style have been replaced with update_javascripts, update_stylesheets, and update_template. However, the Rakefile seems to imply that you can simply use rake update to run all of these update tasks at once, so I did.

Updates Are Broken

Unfortunately, I encountered the following error when I ran rake update.

Error Updating Octopress
Removed existing .old directory
rm -r .old
mkdir .old
cp -r /. .old
rake aborted!
cannot handle socket
/path/to/octopress/Rakefile:309:in `block in <top (required)>'
/path/to/octopress/Rakefile:264:in `block in <top (required)>'
~/.rvm/gems/ruby-1.9.3-p392/bin/ruby_noexec_wrapper:14:in `eval'
~/.rvm/gems/ruby-1.9.3-p392/bin/ruby_noexec_wrapper:14:in `<main>'
Tasks: TOP => update_template
(See full trace by running task with --trace)

I have no idea what was causing this error and I certainly don't know enough about Octopress's internals to make much of an educated guess. Thankfully, I don't necessarily have to: all I really need to do is isolate the commit that caused this problem. I can use the entire 2.1 branch up to that point.

How do I find the offending commit?

Git Bisect to the Rescue

I remembered that this sort of situation is exactly what git bisect is for. Do a binary search through the commit tree, starting with the latest bad commit and ending with the last known good commit. I had created my 2.1 branch off of master, which I knew to be good, so I starting git bisect with the following commands.

Start git bisect
$ git bisect start
$ git bisect bad
$ git bisect good master

This produced the following output.

Step 1 of git bisect
Bisecting: 175 revisions left to test after this (roughly 8 steps)
[be443098d683a38893c7458ca00f5d14a5de144a] Merge pull request #878 from Eric-Guo/eric_fix

Because I wanted to test Octopress's update process, I needed to make absolutely sure that I had generated the Octopress theme (source directories) correctly. I also wanted to make sure that all of my bundles were up to date. To accomplish this, I used the following (probably horribly inefficient) procedure.

  1. Update gems.

    bundle update
    
  2. “Uninstall” the default Octopress theme by removing the source and (if they exist) sass directories.

    rm -r sass sass.old source source.old
    
  3. Re-install the default Octopress theme.

    rake install
    
  4. Try to update Octopress.

    rake update
    
  5. Discard all changes to Gemfile.lock.

    git checkout -- Gemfile.lock
    
  6. Run git bisect good if step 4 was successful or git bisect bad if it failed. Repeat steps 1–6 until there are no more commits to check.

  7. Clean up the source directories (rm -r source source.old) and then run git bisect reset to stop bisecting and restore HEAD to its original location.

When step 4 succeeded, it produced output similar to the following.

Successful Octopress Update
mkdir source.old
cp -r source/. source.old
## Copied source into source.old/
cp -r --remove-destination .themes/classic/source/. source
cp -r --remove-destination source.old/_includes/custom/. source/_includes/custom/
## Updated source ##
mv sass sass.old
## Moved styles into sass.old/
cp -r .themes/classic/sass/ sass
cp -r sass.old/custom/. sass/custom
## Updated Sass ##
rm -r .sass-cache

When step 4 failed, it produced output similar to the following.

Failed Octopress Update
mkdir source.old
cp -r source/. source.old
## Copied source into source.old/
cp -r --remove-destination .themes/classic/source/. source
cp -r --remove-destination source.old/_includes/custom/. source/_includes/custom/
mv -f source/index.html
cp source.old/index.html source
## Updated source ##
mkdir .old
rake aborted!
File exists - .old
/path/to/octopress/Rakefile:271:in `block in <top (required)>'
/path/to/octopress/Rakefile:260:in `block in <top (required)>'
~/.rvm/gems/ruby-1.9.3-p392/bin/ruby_noexec_wrapper:14:in `eval'
~/.rvm/gems/ruby-1.9.3-p392/bin/ruby_noexec_wrapper:14:in `<main>'
Tasks: TOP => update_stylesheets
(See full trace by running task with --trace)

And finally, here is the result of my little excursion:

Results from git bisect
7bdab0e65c86d8bd9fe3b46a4bf1ca92b1e1a54e is the first bad commit
commit 7bdab0e65c86d8bd9fe3b46a4bf1ca92b1e1a54e
Author: Brandon Mathis <brandon@imathis.com>
Date: Sun Feb 10 02:47:53 2013 -0600
Added javascript asset management and improved Rakefiles and configuration for themes and plugins.
- Added Guard for file watching
- Configs can be automatically reloaded
- Static asset changes do not trigger Jekyll build
- CommonJS modular js support proved by stich-rb
- Javascript is concatenated and uglified
- Environment variables toggle uglify and fingerprinting
- New Jekyll plugin config_tag
- New Jekyll plugin javascript_assets_tag
- Added theme specific configurations
- Custome Jekyll Guard to the rescue
- Install, Generate, Watch, and Preview work with Guard now.
- Now configs are no longer tracked by Octopress, only theme defauts are.
- Console messages can be colorized.
- misc config reorganization and improvements
:040000 040000 3d2ca5d42be900e081050cd31344780ffbbb0b20 bef0756debd5ac71f40b5696a8ed87af77f8268f M .themes
:100644 100644 ed67ec9d37a79e98ed0d3b10daf7bf88ef54ffc1 a4c8628d5388e60783d64800842e794074b773e9 M Gemfile
:100644 100644 366bcc9b9f50a94de8b652f9a1721d63dce7a083 9a7816d5e36027850df9f268bdf0b103574c4057 M Gemfile.lock
:000000 100644 0000000000000000000000000000000000000000 50e4dd9007a6ed9223312f43951ceb9c8e264b76 A Guardfile
:100644 100644 ead162a40086ec9afa4d903ade378545b8bcd695 1bac57ede8226f1331867bc6b9bdf1b3c15ab03a M Rakefile
:040000 000000 5bc14cccc0e1433f673dbf7348d417030d17b94b 0000000000000000000000000000000000000000 D _config
:100644 100644 72cbc0a04e91820163faae78df5caa03fc39d347 8850a0498347f8b4deaae0422a4dc4fe4f28607b M config.rb
:040000 040000 4b22768afd286d8e359075dbcc5fba632ea9564b c9f7e99034f425bf3de51cabec1bb7925bfbcbfb M lib
:040000 040000 2d7995a9500dffd5ef9421a67b1a16f3794f0f8b 91ce26b900afd8916d30a9471b5e09892813fde3 M plugins

I don't know precisely what happened in this commit to break the update process, but it is suspect because it adds several features and changes several files all at once.

Branch Off the Last Known Good Commit

Once I found the offending commit (7bdab0e65), I was able to create a new branch off of its parent (4972fb6c62) and continue blogging. I noticed that some settings have been moved, but that's a topic for another post.