The Journey to Yosemite

hackmacos

Though Yosemite might be regarded as one of the worst OSX release, I do want the upgrade, — ironically, for the latest Microsoft Office 2016 for Mac which only avails to Yosemite and the above.

The upgrade from Mavericks should work just like a magic, according to the official document:

  • Get OS X Yosemite from the Mac App Store.
  • Double-click Install OS X Yosemite to begin installation.

Unfortunately, the journey to the Yosemite is extremely lengthy and painful.

TL;DR:

  • Uninstall the Symantec PGP Disk Encryption, otherwise it will stop Yosemite upgrade after reboot.
  • Remove the homebrew before upgrade, it will lengthen the upgrade procedure significantly, and not all brewed apps are guaranteed to work after the upgrade.
  • vcsh and mr are perfect combination to manage your dotfiles.

Show me the magic

Not show after the machine reboot.

After several attempts, I consulted the IT support and was told that the Symantec PGP Disk Encryption would stop the upgrade process, the disk MUST be decrypted before the Yosemite upgrade. Also, the machine CANNOT be power cycled during the decryption, but it is safe to pause the decryption and put the machine into sleep.

Ten hours later, I double clicked Install OS X Yosemite one more time and waited magic to arrive, and I my first kernel panic in Mac:

Kernel Panic
Kernel Panic

The OSX Recovery is clearly designed for this daunting moment. I held down the Command and R keys at startup, and booted the system into recovery mode, — with only one option: reinstall Mavericks. It is worthy noting that the Mavericks restore requires an internet connection and App Store authentication. 40 minutes later, I was back to the square one.

Luckily, no data loss, so I did one more double click, and finally kicked off the Yosemite upgrade after the reboot. In the retrospect, if I rebooted the machine after the disk decryption, I might reduce the complexity and avoid the Mavericks detour.

The update took another 10 hours, mainly spent on the last “About 1 minute remaining” screen thanks to the homebrew packages.

Fix the broken tap

After the reboot, I found lots of apps stop working:

  • tmux crashed every time a new session started1
  • gulp, node were not found
  • ruby provided by rvm crashed during the start.
  • zsh complained some plugins were not working correctly

All symptoms are pointing to the same root cause, the homebrew is broken. I consider the Yosemite update introduce some change on the basic library which break the dynamic linkage for brewed apps:

The following approach usually works:

brew update
brew doctor

But not this time, so I decided to wipe off the homebrew and start from scratch by following this uninstall instruction; — I really should do it earlier.

The rvm ruby crashed due to the linkage error when I tried to install the homebrew.

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
dyld: Library not loaded: /usr/local/lib/libgmp.10.dylib
  Referenced from: /Users/kunxi/.rvm/rubies/ruby-2.2.1/bin/ruby
  Reason: image not found
[1]    50347 trace trap  ruby

Let’s fix the rvm first:

curl -sSL https://get.rvm.io | bash -s stable --ruby

then the homebrew:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

With homebrew installed, we can get all the basic packages in places:

brew install tmux node ack mr vcsh
sudo npm install -g gulp bower

Update the vim to the latest version:

brew install vim
brew install macvim --override-system-vim
sudo mv /usr/bin/vim /usr/bin/vim.origin

House cleaning

There is no better timing to clean the house when everything is almost broken. Let’s revisit the dotfiles management solution:

The secret sauce of vcsh is to separate the git work directory and the git metadata, i.e .git directory generally. More concretely, the git repository foo managed by vcsh uses $HOME as the working directory, and stores the git meta data at $XDG_CONFIG_HOME/vcsh/repos.d/foo.git, see more details here about the --git-dir and --work-tree magic. Therefore, multiple repositories can share the same working directory, $HOME, — a perfect solution for dotfiles management.

mr, aka myrepos, — multirepos might be a better name in my humble opinion, — complements vcsh with multiple repositories tracking. It can bring multiple repository to the current state, which fits naturally for dotfiles management.

Here is one example, $HOME/.config/mr/config.d/zshrc.vcsh:

[$HOME/.config/vcsh/repo.d/zshrc.git]
checkout = vcsh clone git@github.com:kunxi/zshrc.git

When mr update is invoked, it will try to create a git repository $HOME/.config/vcsh/repo.d/zshrc.git by executing the checkout command, vcsh clone git@github.com:kunxi/zshrc.git. The .vcsh suffix is a mr convention for the repository managed by vcsh, so it is .git suffix in the vcsh repository. We will discuss more examples below.

Migrate to Presto

Presto is a much smaller zsh framework compared to oh-my-zsh, and the advocators claim that presto is generally more responsive than the oh-my-zsh.

Create a new file, $HOME/.config/mr/config.d/prezto.git as:

[$HOME/.zprezto]
checkout = git clone --recursive git@github.com:sorin-ionescu/prezto.git .zprezto

The succeeding mr update will clone the prezto repository to .zprezto. The official document suggests to link the various zsh configuration files in .zprezto/runcoms to the home directory. But I would rather copy them, and track the change in my personal zshrc for customization:

setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  cp "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done

If you haven’t use vcsh to manage the zshrc before:

vcsh init zshrc

then

vcsh zshrc add ~/{.zlogin,.zlogout,.zpreztorc,.zprofile,.zshenv}
vcsh zshrc commit -m "Initial checkin: add prezto runcoms."

Push the repository to github as:

vcsh zshrc remote add origin git@github.com:kunxi/zshrc.git
vcsh zshrc push

Also we can hand off the vcsh repository for mr to manage, add the $HOME/.config/mr/config.d/zshrc.git as:

[$HOME/.config/vcsh/repo.d/zshrc.git]
checkout = vcsh clone git@github.com:kunxi/zshrc.git

ZSH Customization

I decided to instrument the command usage before jumping to a preset configuration. Presto’s history-stat lists the latest most frequently used command recently. If you don’t have preso installed, or you’d rather chase the long tail:

$ (export LC_ALL='C'; cat  ~/.zhistory ~/.zsh_history | cut -d ';' -f 2 | awk '{print $1}' | sort | uniq -c | sort -n -r | head -n 50)

Note: some context about the above command:

  • oh-my-zsh and presto saves the command history in ~/.zsh_history and ~/.zhistory respectively, we will count both of them.
  • The locale is set to C for the whole pipeline to avoid decoding errors for some arguments.

If you are still using bash, here you go:

(export LC_ALL='C'; cat ~/.bash_history | awk '{print $1}' | sort | uniq -c | sort -n -r | head -n 10)

Here is my top 50 most frequently used commands:

letsourcetailnodepstoxmanipythoncutfindrmdirpwdtmuxpyopy.testgruntheadpiptmuxdiffpingboweropen./a.outwhichscpvagrantgrepazurebrewmkdirvimcurlcpsudonpmpythongulphttpmvsshcatrmackvicdllmvimlsgit0500100015002000250030003500400045005000

Surprisingly, git dominates my daily command line usage. One possible explanation is that with the tmuxp and multiple tab support in iTerm2, I rarely need to change the working directory; and the command autocomplete in zsh also helps to reduce the file system traverse. Nevertheless, we could enable the following prezto modules to facilitate the work habit:

  • git
  • utility
  • homebrew
  • python: virtualenv support
  • node: nvm support
  • ruby: rvm support.
  • tmux: not particularly useful if tmux auto-start is not enabled.
  • osx: some nifty Mac OSX specific alias and functions2.
  • ssh: not compatible with OSX.
  • rsync

Also, the zsh prompt plays an important role in the productivity, I choose the pure theme for its sanity.

Pure theme for zsh
Pure theme for zsh

That is all for now, I will talk more about the development environment setup later.


  1. it turns out that there exists an error in the tmux.conf, reattach-to-user-namespace needs to be reinstalled via homebrew.
  2. the portability of the dotfiles across platforms might be an interesting topic to explore in the future.