<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>ariejan.net</title><link>http://ariejan.net/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ariejan" /><language>en</language><managingEditor>noemail@noemail.org (Ariejan de Vroom)</managingEditor><lastBuildDate>Mon, 25 Mar 2013 16:00:00 PDT</lastBuildDate><feedburner:info uri="ariejan" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><description></description><feedburner:emailServiceId>ariejan</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/ariejan" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fariejan" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item><title>I'm here for an argument</title><link>http://feedproxy.google.com/~r/ariejan/~3/_pZdcL2ABno/</link><pubDate>Mon, 25 Mar 2013 16:00:00 PDT</pubDate><guid isPermaLink="false">tag:ariejan.net,2013-03-26:/2013/03/26/i-am-here-for-an-argument/</guid><description>&lt;p&gt;When people make a request or proposal I often see them present their request and arguments using the following&amp;nbsp;structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make a&amp;nbsp;request&lt;/li&gt;
  &lt;li&gt;Give a plethora of arguments why that request is a good&amp;nbsp;idea.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;An&amp;nbsp;example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I want to go to the&amp;nbsp;zoo!&lt;/li&gt;
  &lt;li&gt;Because I want to see&amp;nbsp;animal&lt;/li&gt;
  &lt;li&gt;Because I want to spend time with&amp;nbsp;you&lt;/li&gt;
  &lt;li&gt;Because it has been a long&amp;nbsp;time&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here I think, meh, the zoo. And then I read some arguments that may or may not change my opinion on actually going to the zoo or&amp;nbsp;not.&lt;/p&gt;

&lt;p&gt;You start with the &lt;em&gt;what&lt;/em&gt; and then continue on to the &lt;em&gt;why&lt;/em&gt;, but I’ve already lost&amp;nbsp;interest.&lt;/p&gt;

&lt;p&gt;Consider this&amp;nbsp;request:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I want to spend time with you and see&amp;nbsp;animals.&lt;/li&gt;
  &lt;li&gt;It has been a long time since we went to the&amp;nbsp;zoo&lt;/li&gt;
  &lt;li&gt;Let’s go to the&amp;nbsp;zoo!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Here you start with me agreeing on spending time together and it becomes easier for me to accept your request to go to the zoo. I’m not blinded by your&amp;nbsp;request.&lt;/p&gt;

&lt;p&gt;You start with the &lt;em&gt;why&lt;/em&gt; and then continue to the &lt;em&gt;what&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In addition to this article, please watch &lt;a href="http://www.ted.com/talks/simon_sinek_how_great_leaders_inspire_action.html"&gt;Simon Sinek’s &lt;span class="caps"&gt;TED&lt;/span&gt; Talk&lt;/a&gt; [18m05] How great leaders inspire&amp;nbsp;action.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=_pZdcL2ABno:ZpApJXV3XIA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=_pZdcL2ABno:ZpApJXV3XIA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=_pZdcL2ABno:ZpApJXV3XIA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=_pZdcL2ABno:ZpApJXV3XIA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=_pZdcL2ABno:ZpApJXV3XIA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=_pZdcL2ABno:ZpApJXV3XIA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=_pZdcL2ABno:ZpApJXV3XIA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/_pZdcL2ABno" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2013/03/26/i-am-here-for-an-argument/</feedburner:origLink></item><item><title>Automated nanoc deployments</title><link>http://feedproxy.google.com/~r/ariejan/~3/omPOQBco27g/</link><pubDate>Sun, 24 Mar 2013 16:00:00 PDT</pubDate><guid isPermaLink="false">tag:ariejan.net,2013-03-25:/2013/03/25/automated-nanoc-deployments/</guid><description>&lt;p&gt;I’ve migrated &lt;em&gt;ariejan.net&lt;/em&gt; from a custom Ruby on Rails application to a statically generated site with&amp;nbsp;Nanoc.&lt;/p&gt;

&lt;p&gt;Publishing my site now goes like&amp;nbsp;this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write stuff in&amp;nbsp;Markdown&lt;/li&gt;
  &lt;li&gt;Commit and&amp;nbsp;push&lt;/li&gt;
  &lt;li&gt;Watch how jenkins builds and publishes the site with nanoc and&amp;nbsp;rsync.&lt;/li&gt;
&lt;/ol&gt;&lt;h2 id="using-nanoc"&gt;Using&amp;nbsp;nanoc&lt;/h2&gt;

&lt;p&gt;Nanoc is a very powerful static site generator. You can use ruby to create helpers, filters and what not. Fancy using Sass, Compass and Haml? No&amp;nbsp;problem!&lt;/p&gt;

&lt;p&gt;Simply write pages in Haml or Markdown and Nanoc will generate a complete site, including sitemap, robots.txt and &lt;span class="caps"&gt;RSS&lt;/span&gt;&amp;nbsp;feed.&lt;/p&gt;

&lt;p&gt;Once you’ve set everything up to your liking, simply run &lt;code&gt;nanoc compile&lt;/code&gt; and your site is&amp;nbsp;ready.&lt;/p&gt;

&lt;p&gt;Nanoc also has some nice features to deploy your website through rsync, which will upload (or remove) files on a remote server as&amp;nbsp;necessary.&lt;/p&gt;

&lt;h2 id="automate-the-crap-out-of-it"&gt;Automate the crap out of&amp;nbsp;it!&lt;/h2&gt;

&lt;p&gt;I’m a programmer. I like to automate repetitive tasks. So I&amp;nbsp;did.&lt;/p&gt;

&lt;p&gt;I’ve setup Jenkins with the &lt;span class="caps"&gt;RVM&lt;/span&gt; plugin and that’s all I need to have Jenkins generate and deploy my Nanoc&amp;nbsp;site.&lt;/p&gt;

&lt;p&gt;Here’s the build script I currently&amp;nbsp;use:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1
2
3
4
5&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NANOC_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production
bundle install
nanoc compile
nanoc deploy -t public
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the compilation fails for some reason, the deployment is&amp;nbsp;cancelled.&lt;/p&gt;

&lt;h2 id="enter-gitlab"&gt;Enter&amp;nbsp;gitlab&lt;/h2&gt;

&lt;p&gt;Now I use Gitlab to host tons of private repositories, including the one for &lt;em&gt;ariejan.net&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I’ve setup a web hook that will trigger the Jenkins job when new commits are made or&amp;nbsp;pushed.&lt;/p&gt;

&lt;p&gt;This allows me to quickly edit a file, commit it and Gitlab en Jenkins will make sure the change is compiled and published to &lt;em&gt;ariejan.net&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="where-to-go-from-here"&gt;Where to go from&amp;nbsp;here&lt;/h2&gt;

&lt;p&gt;For now, this setup suffices for me. I keep all my posts in version control, and backupped to &lt;span class="caps"&gt;S3&lt;/span&gt; (by backing up my gitlab repositories). Adding a new story to git is sufficient for it to be published automatically on &lt;em&gt;ariejan.net&lt;/em&gt; and in the event something goes wrong with compilation, Jenkins will notify me of the build&amp;nbsp;failure.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=omPOQBco27g:cfuDzcJ5408:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=omPOQBco27g:cfuDzcJ5408:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=omPOQBco27g:cfuDzcJ5408:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=omPOQBco27g:cfuDzcJ5408:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=omPOQBco27g:cfuDzcJ5408:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=omPOQBco27g:cfuDzcJ5408:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=omPOQBco27g:cfuDzcJ5408:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/omPOQBco27g" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2013/03/25/automated-nanoc-deployments/</feedburner:origLink></item><item><title>Review commits in your feature branch</title><link>http://feedproxy.google.com/~r/ariejan/~3/S7AVSosjma4/</link><pubDate>Thu, 07 Mar 2013 15:00:00 PST</pubDate><guid isPermaLink="false">tag:ariejan.net,2013-03-08:/2013/03/08/review-commits-in-your-feature-branch/</guid><description>&lt;p&gt;Github pull requests are awesome, but you can’t use them all the time, mostly when working on code not hosted at&amp;nbsp;github.&lt;/p&gt;

&lt;p&gt;The following snippet makes it easy to see the commits in your current (head) branch that are not yet in the base&amp;nbsp;branch.&lt;/p&gt;

&lt;p&gt;To see what commits are made in your current feature branch, but which have not been merged into develop&amp;nbsp;yet:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1
2
3&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;$ gpr develop
* 5246248 &amp;lt;ariejan@ariejan.net&amp;gt; (HEAD, origin/feature-branch, feature-branch) Implements the awesome feature (50 minutes ago)
* 4f55b7c &amp;lt;ariejan@ariejan.net&amp;gt; Write specs for awesome feature (2 hours ago)
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h2 id="snippets"&gt;Snippets&lt;/h2&gt;

&lt;p&gt;To achieve this, add the following alias to&amp;nbsp;&lt;code&gt;~/.gitconfig&lt;/code&gt;:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1
2&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
  &lt;span class="na"&gt;lg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;log --graph --pretty=format:'%Cred%h%Creset %Cblue&amp;lt;%ae&amp;gt;%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And the following alias to your &lt;code&gt;~/.bashrc&lt;/code&gt; or&amp;nbsp;&lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gpr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git --no-pager lg HEAD --not $1"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h2 id="bonus-tip"&gt;Bonus&amp;nbsp;tip&lt;/h2&gt;

&lt;p&gt;After reviewing the commits in your feature branch with &lt;code&gt;gpr&lt;/code&gt;, use &lt;a href="http://defunkt.io/hub/"&gt;&lt;code&gt;hub&lt;/code&gt;&lt;/a&gt; to attach your code to a github&amp;nbsp;issue:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;hub pull-request -i 42 -h ariejan:feature-branch -b you:develop
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=S7AVSosjma4:tQ-12WinEEw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=S7AVSosjma4:tQ-12WinEEw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=S7AVSosjma4:tQ-12WinEEw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=S7AVSosjma4:tQ-12WinEEw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=S7AVSosjma4:tQ-12WinEEw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=S7AVSosjma4:tQ-12WinEEw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=S7AVSosjma4:tQ-12WinEEw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/S7AVSosjma4" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2013/03/08/review-commits-in-your-feature-branch/</feedburner:origLink></item><item><title>Instagram, Governments and Cypherpunks</title><link>http://feedproxy.google.com/~r/ariejan/~3/GRrTbv3T4SY/</link><pubDate>Mon, 17 Dec 2012 15:00:00 PST</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-12-18:/2012/12/18/instagram-governments-and-cypherpunks/</guid><description>&lt;p&gt;The whole internet collectively fell over Instagram earlier this week when they released their new &lt;em&gt;Terms of Service&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Some or all of the Service may be supported by advertising revenue. To help us deliver interesting paid or sponsored content or promotions, you agree that a business or other entity may pay us to display your username, likeness, photos (along with any associated metadata), and/or actions you take, in connection with paid or sponsored content or promotions, without any compensation to&amp;nbsp;you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today &lt;a href="http://blog.instagram.com/post/38252135408/thank-you-and-were-listening"&gt;Instagram officially responded&lt;/a&gt; to all the screaming and shouting, trying to control the&amp;nbsp;damage.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;From the start, Instagram was created to become a&amp;nbsp;business.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, that was unexpected. It’s the same with Facebook, Twitter, Gmail, Hotmail, etc. All these services are here for you to use for free -&amp;nbsp;awesome!&lt;/p&gt;

&lt;p&gt;But nobody ever got rich from giving stuff away for free, and these are businesses we’re talking&amp;nbsp;about.&lt;/p&gt;

&lt;p&gt;Let’s see how this works over at&amp;nbsp;Facebook.&lt;/p&gt;

&lt;h2 id="exhibit-a-facebook"&gt;Exhibit A:&amp;nbsp;Facebook&lt;/h2&gt;

&lt;p&gt;Facebook is a good example of how you are the product being sold. We all know Facebook tries to show you ads that you are likely interested in. Based on what you put in your profile advertisers can target specific&amp;nbsp;audiences.&lt;/p&gt;

&lt;p&gt;That might sound all well and good to you, but did you also know that your friends might see a &lt;em&gt;sponsored&lt;/em&gt; post in their newsfeed? And that that &lt;em&gt;sponsored&lt;/em&gt; post appears as if it’s one posted by &lt;em&gt;you&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;img src="https://s3-eu-west-1.amazonaws.com/ariejannet/images/related-post.png" alt="Facebook sponsored post"&gt;&lt;/p&gt;

&lt;p&gt;Here you see a post by a friend of mine who apparently likes some mobile company’s ad. They didn’t like this add. I asked&amp;nbsp;them.&lt;/p&gt;

&lt;p&gt;So basically Facebook and an advertiser are using you, your name and your profile picture to promote an advertisement to one of your&amp;nbsp;friends.&lt;/p&gt;

&lt;h2 id="exhibit-b-google"&gt;Exhibit B:&amp;nbsp;Google&lt;/h2&gt;

&lt;p&gt;Another example, more in line with Facebook, is Google. All those free tools: Search, Gmail, Google+, Analytics, Web Master Tools, maps. They are all geared towards either exposing ads to you, or gathering data on you to expose more focussed&amp;nbsp;ads.&lt;/p&gt;

&lt;p&gt;The plus side here, I would say, is that Google actually delivers usable services, like search, mail, calendars and such. But still, look at the boatloads of money Google is making selling ads based on your private details and online&amp;nbsp;behaviour.&lt;/p&gt;

&lt;h2 id="exhibit-c-twitter"&gt;Exhibit C:&amp;nbsp;Twitter&lt;/h2&gt;

&lt;p&gt;Twitter is a company that has struggled for a long time to find a way to monetize itself. Hopes were high that they would find a new an innovative way, but they have&amp;nbsp;not.&lt;/p&gt;

&lt;p&gt;It remains to be seen what’s going to happen exactly with twitter, but we can all assume that our tweets are being analyzed and that Twitter will do anything to sell you to their&amp;nbsp;advertisers.&lt;/p&gt;

&lt;h2 id="exhibit-d-instagram"&gt;Exhibit D:&amp;nbsp;Instagram&lt;/h2&gt;

&lt;p&gt;To come back to Instagram, they’re in the same boat as Twitter and&amp;nbsp;Facebook.&lt;/p&gt;

&lt;p&gt;They have been growing their user base for quite some time now and now comes the time to move in and cash on all those&amp;nbsp;users.&lt;/p&gt;

&lt;p&gt;The new terms of service should not come as a&amp;nbsp;surprise.&lt;/p&gt;

&lt;p&gt;Instagram wants to use your data to match you up with advertisers and it even wants to show ads endorsed by you, just like Facebook already&amp;nbsp;does.&lt;/p&gt;

&lt;h2 id="so-whats-happening-out-there"&gt;So what’s happening out&amp;nbsp;there?&lt;/h2&gt;

&lt;p&gt;Social Media are nice, they connect people and can start revolutions. But that is not why those media exist. They are marketing and data mining platforms on a massive&amp;nbsp;scale.&lt;/p&gt;

&lt;p&gt;Have you ever wondered why social media companies get multi million dollar investments? Because with a huge, world-wide user base, there is a huge advertising&amp;nbsp;potential.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you are not buying a product or service, but are receiving one for free, then you are the product or service begin&amp;nbsp;sold.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I think that companies like Facebook and Instagram are wading in a gray area of privacy. Their practices may be perfectly legal, but they &lt;em&gt;are&lt;/em&gt; ethically&amp;nbsp;questionable.&lt;/p&gt;

&lt;h2 id="on-government-spying-and-eavesdropping"&gt;On government spying and&amp;nbsp;eavesdropping&lt;/h2&gt;

&lt;p&gt;You might sometimes worry about governments eavesdropping and keeping tabs on innocent citizens – and you&amp;nbsp;should.&lt;/p&gt;

&lt;p&gt;If you look at the sheer amount of data social media gather on you, imagine what kind of data a government agency with the proper tools and hardware can&amp;nbsp;do.&lt;/p&gt;

&lt;p&gt;But the issue is not really that companies and governments are gathering data - you are feeding it to them with every status update and photo you upload to the internet. With every email you&amp;nbsp;sent.&lt;/p&gt;

&lt;p&gt;So, what’s to be&amp;nbsp;done?&lt;/p&gt;

&lt;h2 id="cypherpunks-to-the-rescue"&gt;Cypherpunks to the&amp;nbsp;rescue?&lt;/h2&gt;

&lt;p&gt;Now, I won’t claim to know a whole lot about cypherpunks and the crypto wars, but these people have fought (and still are) fighting for our digital rights and&amp;nbsp;freedom.&lt;/p&gt;

&lt;p&gt;We are collectively giving away our personal data to companies and governments and most of the time we don’t even know it. But then some image sharing company changes its terms that will allow them to display adds alongside your name and we freak&amp;nbsp;out.&lt;/p&gt;

&lt;p&gt;Here’s quite from the Cypherpunks&amp;nbsp;manifesto:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Privacy is necessary for an open society in the electronic age. … We cannot expect governments, corporations, or other large, faceless organizations to grant us privacy … We must defend our own privacy if we expect to have any. … Cypherpunks write code. We know that someone has to write software to defend privacy, and … we’re going to write&amp;nbsp;it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To be clear, I’m not a cypherpunk by any means. Here’s a snippet from Wired magazine,&amp;nbsp;1993:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The people in this room [cypherpunks] hope for a world where an individual’s informational footprints – everything from an opinion on abortion to the medical record of an actual abortion – can be traced only if the individual involved chooses to reveal&amp;nbsp;them;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this is where the problem lies. Yesterday Will Wheaton, of Star Trek fame, &lt;a href="https://plus.google.com/108176814619778619437/posts/3o79SJWv4kG"&gt;wrote about&lt;/a&gt; this as&amp;nbsp;well.&lt;/p&gt;

&lt;p&gt;Will has a great point that we’ve come to a point where it’s okay that somebody else shares your personal details with a third party on the internet – without your knowledge, without your consent. And there is nothing you can do about&amp;nbsp;it.&lt;/p&gt;

&lt;p&gt;I’m not sure about you, but this sure frightens&amp;nbsp;me.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=GRrTbv3T4SY:0sMsVqa_EJA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=GRrTbv3T4SY:0sMsVqa_EJA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=GRrTbv3T4SY:0sMsVqa_EJA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=GRrTbv3T4SY:0sMsVqa_EJA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=GRrTbv3T4SY:0sMsVqa_EJA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=GRrTbv3T4SY:0sMsVqa_EJA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=GRrTbv3T4SY:0sMsVqa_EJA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/GRrTbv3T4SY" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/12/18/instagram-governments-and-cypherpunks/</feedburner:origLink></item><item><title>Binary debugging with git bisect</title><link>http://feedproxy.google.com/~r/ariejan/~3/85akOZjIEIo/</link><pubDate>Wed, 28 Nov 2012 15:00:00 PST</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-11-29:/2012/11/29/binary-debugging-with-git-bisect/</guid><description>&lt;p&gt;Part of resolving a bug is finding where and when that bug was introduced into your code. Not so much for blaming a specific person, but more for an understanding of how and maybe why the bug was introduced; and more over which versions of your app are&amp;nbsp;affected.&lt;/p&gt;

&lt;p&gt;Most of the time the bug was recently introduced and your &lt;span class="caps"&gt;CI&lt;/span&gt; notified you that stuff has been&amp;nbsp;broken.&lt;/p&gt;

&lt;p&gt;In order to find out when, how and by whom the build was broken, you’ll have to dig into your git history and run your specs to see if they pass or&amp;nbsp;not.&lt;/p&gt;

&lt;p&gt;Running your specs for every commit in your history manually is very time consuming and boring. Luckily there are better ways, using plain old&amp;nbsp;git.&lt;/p&gt;

&lt;h2 id="binary-search"&gt;Binary&amp;nbsp;search&lt;/h2&gt;

&lt;p&gt;Before I dive into git, it’s important you understand how binary search works. If you already know this stuff, skip right to the next&amp;nbsp;section.&lt;/p&gt;

&lt;p&gt;You have a sorted array. This means there is some order to the elements you have. Presume you have an array of&amp;nbsp;ints:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;89&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now, we want to find the position (&lt;code&gt;n&lt;/code&gt;) of &lt;code&gt;7&lt;/code&gt; in this array using binary search so that&amp;nbsp;&lt;code&gt;a[n] == 7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Binary search uses a divide and conquer strategy. You split the array in the middle. We have 10 elements, so a logical place would be to split the array at position &lt;code&gt;n = 5&lt;/code&gt;, which has the value&amp;nbsp;&lt;code&gt;42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Comparing &lt;code&gt;7 &amp;lt;=&amp;gt; 42&lt;/code&gt; tells us that, because we have an ordered array, the value &lt;code&gt;7&lt;/code&gt; should be in the first half of the&amp;nbsp;array.&lt;/p&gt;

&lt;p&gt;We can ignore the right half of the array for searching, and repeat this step for the left part,&amp;nbsp;specifically:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So, let’s split this part up again. We get &lt;code&gt;4&lt;/code&gt;. This is less than &lt;code&gt;7&lt;/code&gt;, so if we continue looking we should take the right&amp;nbsp;part.&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Okay, again, we continue our search. We know have to split the array one way or the other, and we end up picking &lt;code&gt;n = 4&lt;/code&gt;. We hit &lt;code&gt;33&lt;/code&gt;. Surely the value of &lt;code&gt;7&lt;/code&gt; must be on the left part of&amp;nbsp;this.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that although I don’t show the whole array, I’m still using the index positions for the entire &lt;code&gt;a&lt;/code&gt;&amp;nbsp;array.&lt;/em&gt;&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now, there’s not much to pick for us. This is 7. Right here at &lt;code&gt;n = 3&lt;/code&gt;.&amp;nbsp;Done!&lt;/p&gt;

&lt;p&gt;Notice that the last step does not involve checking the value of the last element. We only have 1 element left, so we’re&amp;nbsp;finished.&lt;/p&gt;

&lt;p&gt;If we had been looking for a value of 18, we would have also found &lt;code&gt;n = 3&lt;/code&gt;. This means that we can search for non-existing values, which then return the index right before where that number should be inserted. This works because the array was ordered, so we can safely make such assumptions. Nice,&amp;nbsp;huh?&lt;/p&gt;

&lt;h2 id="how-does-binary-search-relate-to-finding-bugs"&gt;How does binary search relate to finding&amp;nbsp;bugs?&lt;/h2&gt;

&lt;p&gt;Well, in the example above we were looking for an integer value. The test we use to evaluate is&amp;nbsp;simple:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When we want to find the commit that broke our build we need a more clever way of comparing&amp;nbsp;values.&lt;/p&gt;

&lt;p&gt;This is where your test suite comes in. You have a failing spec now, so basically we’re looking for the point in git history where that spec failed for the first&amp;nbsp;time.&lt;/p&gt;

&lt;h2 id="git-bisect"&gt;Git&amp;nbsp;bisect&lt;/h2&gt;

&lt;p&gt;Because it’s not feasible to do a linear search over your entire commit history, we’ll have to start by marking a &lt;em&gt;good&lt;/em&gt; and a &lt;em&gt;bad&lt;/em&gt;&amp;nbsp;commit.&lt;/p&gt;

&lt;p&gt;First we’ll have to find a location in your git history where you know the app did not exhibit this&amp;nbsp;bug.&lt;/p&gt;

&lt;p&gt;More than likely, this place is your last stable release. If you used &lt;code&gt;git tag&lt;/code&gt; to tag your release, you should be able to find out quickly if that release contains the&amp;nbsp;bug.&lt;/p&gt;

&lt;pre class="plaincode"&gt;git checkout v1.2.1
rspec spec/features/fancy_spec.rb
=&amp;gt; 0 failures
&lt;/pre&gt;

&lt;p&gt;Good. We now our latest commit was broken, so let’s get started with that binary&amp;nbsp;search!&lt;/p&gt;

&lt;p&gt;You don’t have to keep track of the git history and binary search position all by yourself: git does this for you. All you have to do is compare each commit that is presented to you with an expected result. E.g. does the &lt;code&gt;fancy_spec.rb&lt;/code&gt; spec pass or&amp;nbsp;not?&lt;/p&gt;

&lt;h2 id="bisecting-steps"&gt;Bisecting&amp;nbsp;steps&lt;/h2&gt;

&lt;p&gt;First, let git know you want to do a binary&amp;nbsp;search.&lt;/p&gt;

&lt;pre class="plaincode"&gt;git bisect start
&lt;/pre&gt;

&lt;p&gt;Next, let git know which commit is good, and which one is&amp;nbsp;bad.&lt;/p&gt;

&lt;pre class="plaincode"&gt;git good v1.2.1
git bad e8ab31
&lt;/pre&gt;

&lt;p&gt;Git will respond with something like&amp;nbsp;this:&lt;/p&gt;

&lt;pre class="plaincode"&gt;Bisecting: 19 revisions left to test after this (roughly 4 steps)
[0e70ee6aefe428fa897ec7e48273c3fe4d0bf7fb] Did some funky stuff in `config/application.rb`.
&lt;/pre&gt;

&lt;p&gt;Git has determined that commit &lt;code&gt;0e70ee&lt;/code&gt; is right in between &lt;code&gt;v1.2.1&lt;/code&gt; and &lt;code&gt;ebab31&lt;/code&gt;. Check if this revision is broken and report back to&amp;nbsp;git.&lt;/p&gt;

&lt;pre class="plaincode"&gt;rspec spec/features/fancy_spec.rb
&amp;gt; 1 failure
git bisect bad
&lt;/pre&gt;

&lt;p&gt;And git will&amp;nbsp;respond:&lt;/p&gt;

&lt;pre class="plaincode"&gt;Bisecting: 9 revisions left to test after this (roughly 3 steps)
&lt;/pre&gt;

&lt;p&gt;You can continue this until git tells you the commit that first broke this&amp;nbsp;spec.&lt;/p&gt;

&lt;p&gt;When you’re done bisecting (or if you just feel like doing something else), just tell&amp;nbsp;git:&lt;/p&gt;

&lt;pre class="plaincode"&gt;git bisect reset
&lt;/pre&gt;

&lt;h2 id="usage-in-the-field"&gt;Usage in the&amp;nbsp;field&lt;/h2&gt;

&lt;p&gt;Git bisect is a very powerful tool to find specific points in your&amp;nbsp;code.&lt;/p&gt;

&lt;p&gt;In this example we were looking for a commit that broke a specific test. You can look for all kinds of&amp;nbsp;things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When did the layout on that page&amp;nbsp;break?&lt;/li&gt;
  &lt;li&gt;At what point did we upgrade that gem to a buggy&amp;nbsp;release?&lt;/li&gt;
  &lt;li&gt;Who added this ugly piece of&amp;nbsp;code?!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Doing a binary search over your git history is a fast and efficient way of finding these kind of things&amp;nbsp;out.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=85akOZjIEIo:ftyjRqTBSaY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=85akOZjIEIo:ftyjRqTBSaY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=85akOZjIEIo:ftyjRqTBSaY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=85akOZjIEIo:ftyjRqTBSaY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=85akOZjIEIo:ftyjRqTBSaY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=85akOZjIEIo:ftyjRqTBSaY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=85akOZjIEIo:ftyjRqTBSaY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/85akOZjIEIo" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/11/29/binary-debugging-with-git-bisect/</feedburner:origLink></item><item><title>CustoMac</title><link>http://feedproxy.google.com/~r/ariejan/~3/MVoTjMtGw5U/</link><pubDate>Wed, 21 Nov 2012 15:00:00 PST</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-11-22:/2012/11/22/customac/</guid><description>&lt;p&gt;Ever since Apple decided to put Intel processors in their Macs there have been attempts by enthusiasts to run Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X on commodity hardware – with mixed&amp;nbsp;results.&lt;/p&gt;

&lt;p&gt;The key to installing Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X on a non-Mac computer is using the right hardware. If your hardware is a close to Apple kit as possible, you have the best chance to&amp;nbsp;succeed.&lt;/p&gt;

&lt;p&gt;The so-called &lt;em&gt;Hackintosh&lt;/em&gt; community has come a long way the past few years in making it easy for “normal people” to install Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X on their &lt;em&gt;&lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Since I was tired of using Debian Linux on my Desktop, dual booting to Windows to play the occasional game of &lt;em&gt;World of Warcraft&lt;/em&gt;, I decided to give installing Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X a try. But there was a&amp;nbsp;problem.&lt;/p&gt;

&lt;h2 id="the-hardware"&gt;The&amp;nbsp;hardware&lt;/h2&gt;

&lt;p&gt;My current &lt;span class="caps"&gt;PC&lt;/span&gt; is powered by an &lt;span class="caps"&gt;AMD&lt;/span&gt; processor (&lt;span class="caps"&gt;AMD&lt;/span&gt; Phenom &lt;span class="caps"&gt;II&lt;/span&gt; &lt;span class="caps"&gt;X6&lt;/span&gt; &lt;span class="caps"&gt;1055T&lt;/span&gt;, to be precise). Simply put, installing Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X on an &lt;span class="caps"&gt;AMD&lt;/span&gt; cpu is not going to&amp;nbsp;work.&lt;/p&gt;

&lt;p&gt;So, the first thing I did was go over to the &lt;a href="http://wiki.osx86project.org/wiki/index.php/HCL_10.8.2"&gt;OSx86 Project Hardware Compatibility List&lt;/a&gt; and see what hardware is most compatible with Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X &lt;span class="caps"&gt;1.8.2&lt;/span&gt; (the most recent version of &lt;span class="caps"&gt;OS&lt;/span&gt; X at this&amp;nbsp;time).&lt;/p&gt;

&lt;p&gt;I already knew I’d need a shiny new Intel &lt;span class="caps"&gt;CPU&lt;/span&gt;, and thus also a new&amp;nbsp;motherboard.&lt;/p&gt;

&lt;h2 id="choosing-a-cpu"&gt;Choosing a&amp;nbsp;&lt;span class="caps"&gt;CPU&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;Choosing a &lt;span class="caps"&gt;CPU&lt;/span&gt; for your CustoMac is not very difficult, because you are limited to Intel. Since the release of the new MacBooks Apple officially supports the &lt;a href="http://en.wikipedia.org/wiki/Ivy_Bridge_%28microarchitecture%29"&gt;Ivy Bridge&lt;/a&gt; architecture, which means about a 50% lower power consumption and a 5-15% speed increase (&lt;a href="http://en.wikipedia.org/wiki/Ivy_Bridge_%28microarchitecture%29"&gt;link&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The main candidates&amp;nbsp;were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intel i5&amp;nbsp;3570&lt;/li&gt;
  &lt;li&gt;Intel i5&amp;nbsp;&lt;span class="caps"&gt;3570K&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;Intel i7&amp;nbsp;&lt;span class="caps"&gt;3770K&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I won’t go into to too much detail here, but I chose the &lt;em&gt;Intel i5 3570&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The i7 offers &lt;a href="http://en.wikipedia.org/wiki/Hyper-threading"&gt;Hyper Threading&lt;/a&gt; at a price bump of about € 100,-. For me, this was not worth the&amp;nbsp;money.&lt;/p&gt;

&lt;p&gt;Then there’s the choice between the &lt;em&gt;3570&lt;/em&gt; or the &lt;em&gt;&lt;span class="caps"&gt;3570K&lt;/span&gt;&lt;/em&gt;. The ‘K’ version has less features, but is &lt;em&gt;unlocked&lt;/em&gt;, allow it to be easily over-clocked to higher&amp;nbsp;speeds.&lt;/p&gt;

&lt;p&gt;The price difference between the &lt;em&gt;3570&lt;/em&gt; and the &lt;em&gt;3570&lt;/em&gt; are minimal, but I’m not planning to over-clock my &lt;span class="caps"&gt;CPU&lt;/span&gt;, so I went for the slightly cheaper &lt;em&gt;Intel i5 3570&lt;/em&gt;&amp;nbsp;processor.&lt;/p&gt;

&lt;h2 id="choosing-a-motherboard"&gt;Choosing a&amp;nbsp;motherboard&lt;/h2&gt;

&lt;p&gt;Next came a more difficult decision. The motherboard. Again, the  &lt;a href="http://wiki.osx86project.org/wiki/index.php/HCL_10.8.2"&gt;Hardware Compatibility List&lt;/a&gt; was a great help here. In the end I chose the &lt;em&gt;Gigabyte &lt;span class="caps"&gt;Z77&lt;/span&gt;-&lt;span class="caps"&gt;DS3H&lt;/span&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The pro’s of this board are that it’s well supported by Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X and the OSx86 community. This board is special because it features Gigabyte’s &lt;span class="caps"&gt;3D&lt;/span&gt; &lt;span class="caps"&gt;UEFI&lt;/span&gt; Bios. This bios would make it easy to install Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X &lt;em&gt;untouched&lt;/em&gt; on your&amp;nbsp;machine.&lt;/p&gt;

&lt;p&gt;I didn’t end up using this &lt;span class="caps"&gt;UEFI&lt;/span&gt; feature, but nonetheless, support for this board is&amp;nbsp;incredible.&lt;/p&gt;

&lt;h2 id="the-full-hardware-list"&gt;The full hardware&amp;nbsp;list&lt;/h2&gt;

&lt;p&gt;So, recycling other parts of my current &lt;em&gt;&lt;span class="caps"&gt;PC&lt;/span&gt;&lt;/em&gt; I build the following CustoMac&amp;nbsp;configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gigabyte &lt;span class="caps"&gt;Z77&lt;/span&gt;-&lt;span class="caps"&gt;DS3H&lt;/span&gt; Motherboard (&lt;a href="http://www.amazon.com/gp/product/B007R21JWC/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B007R21JWC&amp;amp;linkCode=as2&amp;amp;tag=ariejannet-20"&gt;But at Amazon&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Intel i5 3570 &lt;span class="caps"&gt;CPU&lt;/span&gt; @3.4Ghz (&lt;a href="http://www.amazon.com/gp/product/B0087EVHTE/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B0087EVHTE&amp;amp;linkCode=as2&amp;amp;tag=ariejannet-20"&gt;Buy at Amazon&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;span class="caps"&gt;16GB&lt;/span&gt; &lt;span class="caps"&gt;RAM&lt;/span&gt; at&amp;nbsp;1333Mhz&lt;/li&gt;
  &lt;li&gt;1x 120 &lt;span class="caps"&gt;GB&lt;/span&gt; &lt;span class="caps"&gt;OCZ&lt;/span&gt; Agility 3&amp;nbsp;&lt;span class="caps"&gt;SSD&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;1x &lt;span class="caps"&gt;1TB&lt;/span&gt; Western Digital&amp;nbsp;&lt;span class="caps"&gt;HD&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;1x &lt;span class="caps"&gt;2TB&lt;/span&gt; Western Digital&amp;nbsp;&lt;span class="caps"&gt;HD&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span class="caps"&gt;XFX&lt;/span&gt; &lt;span class="caps"&gt;ATI&lt;/span&gt; Radeon &lt;span class="caps"&gt;HD&lt;/span&gt; 6870 &lt;span class="caps"&gt;1GB&lt;/span&gt; (&lt;a href="http://www.amazon.com/gp/product/B0047ZH7GE/ref=as_li_ss_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B0047ZH7GE&amp;amp;linkCode=as2&amp;amp;tag=ariejannet-20"&gt;Buy at Amazon&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;em&gt;Note 1: The above Amazon links are affiliate&amp;nbsp;links.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note 2: I could have upgraded my memory to 1600Mhz units, which would be faster. But I have no use for the old memory, so I chose to re-use it for&amp;nbsp;now.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id="the-preparation"&gt;The&amp;nbsp;preparation&lt;/h2&gt;

&lt;p&gt;Before you get started, you should prepare an installation &lt;span class="caps"&gt;USB&lt;/span&gt; drive on another Mac. You’ll need at least &lt;span class="caps"&gt;8GB&lt;/span&gt; of space on the&amp;nbsp;drive.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buy Mountain Lion from the App Store on you Mac and download the installer. If you already purchased Mountain Lion, re-download&amp;nbsp;it.&lt;/li&gt;
  &lt;li&gt;Download &lt;a href="http://www.tonymacx86.com/downloads"&gt;UniBeast&lt;/a&gt; for Mountain Lion and follow step 1 and 2 from &lt;a href="http://tonymacx86.blogspot.nl/2011/10/unibeast-install-mac-os-x-lion-using.html"&gt;this guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;At this point you have a bootable &lt;span class="caps"&gt;USB&lt;/span&gt; drive with the Mountain Lion install on&amp;nbsp;it.&lt;/p&gt;

&lt;p&gt;To prepare the actual installation, remove any devices you don’t need, like extra hard drivers, &lt;span class="caps"&gt;DVD&lt;/span&gt;/BluRay drives, etc. In my case I also pulled out the &lt;span class="caps"&gt;ATI&lt;/span&gt; 6870 and used the onboard Intel &lt;span class="caps"&gt;HD&lt;/span&gt; Graphics during&amp;nbsp;installation.&lt;/p&gt;

&lt;p&gt;Plug your &lt;span class="caps"&gt;USB&lt;/span&gt; drive into a &lt;span class="caps"&gt;USB&lt;/span&gt; &lt;span class="caps"&gt;2.0&lt;/span&gt; (black, not blue) port on the motherboard. Make sure to use one of the ports on the back of your computer, those are directly attached to the motherboard and have the greatest chance of&amp;nbsp;succes.&lt;/p&gt;

&lt;p&gt;Now, boot up the computer and enter the &lt;span class="caps"&gt;BIOS.&lt;/span&gt; There are two important changes you need to&amp;nbsp;make.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;span class="caps"&gt;SATA&lt;/span&gt; to &lt;code&gt;AHCI&lt;/code&gt;&amp;nbsp;mode.&lt;/li&gt;
  &lt;li&gt;Disable&amp;nbsp;&lt;code&gt;VT-d&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Then select the &lt;span class="caps"&gt;USB&lt;/span&gt; drive as the bootable device and&amp;nbsp;boot.&lt;/p&gt;

&lt;h2 id="booting-the-installer"&gt;Booting the&amp;nbsp;installer&lt;/h2&gt;

&lt;p&gt;You’ll see the UniBeast boot screen which show a ‘&lt;span class="caps"&gt;USB&lt;/span&gt;’ option (and possibly other, depending on what’s on your disks). Choose ‘&lt;span class="caps"&gt;USB&lt;/span&gt;’ - but don’t press &lt;code&gt;ENTER&lt;/code&gt; just yet. Instead, type &lt;code&gt;-x&lt;/code&gt;, which will show up on the screen. Then, press&amp;nbsp;&lt;code&gt;ENTER&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After a few minutes you should have the Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X Installer in front of you. Go ahead, install this&amp;nbsp;baby.&lt;/p&gt;

&lt;h2 id="notes-on-fusion-drive"&gt;Notes on Fusion&amp;nbsp;drive&lt;/h2&gt;

&lt;p&gt;It’s possible to create a CustoMac Fusion Drive using an &lt;span class="caps"&gt;SSD&lt;/span&gt; and regular&amp;nbsp;harddisk.&lt;/p&gt;

&lt;p&gt;When you’re in the installer, choose ‘Terminal’ to open a terminal window and follow the steps in &lt;a href="http://jollyjinx.tumblr.com/post/34638496292/fusion-drive-on-older-macs-yes-since-apple-has"&gt;this fusion drive guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was able to create and install Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X on a Fusion Drive without problems. The only knack was that the custom bootloader you need is not Fusion Drive aware, which makes it difficult to&amp;nbsp;use.&lt;/p&gt;

&lt;p&gt;In the end I decided to not use a Fusion drive setup, and just install everything on the&amp;nbsp;&lt;span class="caps"&gt;SSD.&lt;/span&gt;&lt;/p&gt;

&lt;h2 id="completing-the-installation"&gt;Completing the&amp;nbsp;installation&lt;/h2&gt;

&lt;p&gt;Now comes the tricky part. The installation is done and you’re CustoMac wants to reboot. Let it, but leave the &lt;span class="caps"&gt;USB&lt;/span&gt; drive&amp;nbsp;connected.&lt;/p&gt;

&lt;p&gt;Your machine will boot up with the same boot menu as before, but instead of ‘&lt;span class="caps"&gt;USB&lt;/span&gt;’ you should now be able to select ‘Macintosh&amp;nbsp;&lt;span class="caps"&gt;HD&lt;/span&gt;’.&lt;/p&gt;

&lt;p&gt;Select that, enter &lt;code&gt;-x&lt;/code&gt; followed by&amp;nbsp;&lt;code&gt;ENTER&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You’ll now be taken through the final steps of installation, like setting up iCloud and creating a user&amp;nbsp;account.&lt;/p&gt;

&lt;p&gt;When finished, you should be on your new Mac&amp;nbsp;desktop.&lt;/p&gt;

&lt;h2 id="installing-custom-kexts"&gt;Installing custom&amp;nbsp;kexts&lt;/h2&gt;

&lt;p&gt;Now, your CustoMac can only boot with the &lt;span class="caps"&gt;USB&lt;/span&gt; drive. Let’s change that by installing a bootloader and some kernel&amp;nbsp;extensions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download &lt;a href="http://www.tonymacx86.com/downloads"&gt;MultiBeast&lt;/a&gt; for Mountain&amp;nbsp;Lion.&lt;/li&gt;
  &lt;li&gt;Run the installer and select the following&amp;nbsp;options:
** User&lt;span class="caps"&gt;DSDT&lt;/span&gt; or &lt;span class="caps"&gt;DSDT&lt;/span&gt;-Free&amp;nbsp;Installation
** Miscellaneous =&amp;gt;&amp;nbsp;Fake&lt;span class="caps"&gt;SMC&lt;/span&gt;
** Audio =&amp;gt; Realtek ALC8xx =&amp;gt; Without &lt;span class="caps"&gt;DSDT&lt;/span&gt; =&amp;gt; Latest version for&amp;nbsp;&lt;span class="caps"&gt;ALC8887&lt;/span&gt;/888b.
** Network =&amp;gt; maolj’s&amp;nbsp;AtherosL1cEthernet
** Disk =&amp;gt; &lt;span class="caps"&gt;TRIM&lt;/span&gt; fix for&amp;nbsp;&lt;span class="caps"&gt;1.8.1&lt;/span&gt;+
** Bootloaders =&amp;gt;&amp;nbsp;Chimera&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;That’s all. Install that stuff. Now, you should be able to reboot your CustoMac and boot it without the &lt;span class="caps"&gt;USB&lt;/span&gt;&amp;nbsp;drive.&lt;/p&gt;

&lt;p&gt;If things don’t work out (like a black or white screen, kernel panics, whatever), just plugin your &lt;span class="caps"&gt;USB&lt;/span&gt; drive again, boot from it and select your ‘Macintosh&amp;nbsp;&lt;span class="caps"&gt;HD&lt;/span&gt;’.&lt;/p&gt;

&lt;h2 id="graphics"&gt;Graphics&lt;/h2&gt;

&lt;p&gt;At this point, you should have a working CustoMac with sound and network working. The only thing missing is a proper graphics&amp;nbsp;card.&lt;/p&gt;

&lt;p&gt;You’ll need to make some tweaks to the chameleon plist file. Then shutdown your computer and install the graphics&amp;nbsp;card.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this works for my &lt;span class="caps"&gt;XFX&lt;/span&gt; &lt;span class="caps"&gt;ATI&lt;/span&gt; Radeon &lt;span class="caps"&gt;HD&lt;/span&gt; 6870 card. There may be subtle differences for different version and brands. Just use the Google to find hints, boot with the &lt;span class="caps"&gt;USB&lt;/span&gt; drive to get to your system and make updates as&amp;nbsp;needed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;/Extra/org.chameleon.Boot.plist&lt;/code&gt; make sure you have the following&amp;nbsp;entries:&lt;/p&gt;

&lt;pre class="plaincode"&gt;&amp;lt;key&amp;gt;AtiConfig&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;Duckweed&amp;lt;/string&amp;gt;
&amp;lt;key&amp;gt;AtiPorts&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;5&amp;lt;/string&amp;gt;
&amp;lt;key&amp;gt;Graphics Mode&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;1920x1080x32&amp;lt;/string&amp;gt;
&amp;lt;key&amp;gt;GraphicsEnabler&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;Yes&amp;lt;/string&amp;gt;
&amp;lt;key&amp;gt;PciRoot&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;1&amp;lt;/string&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Depending on which slot you used for your graphics card, you may have to set &lt;code&gt;PciRoot&lt;/code&gt; to&amp;nbsp;&lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I also had to add &lt;code&gt;npci=0x2000&lt;/code&gt; to &lt;code&gt;Kernel Flags&lt;/code&gt;, but you may or may not need&amp;nbsp;it.&lt;/p&gt;

&lt;pre class="plaincode"&gt;&amp;lt;key&amp;gt;Kernel Flags&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;npci=0x2000 darkwake=0&amp;lt;/string&amp;gt;
&lt;/pre&gt;

&lt;h2 id="boot-up"&gt;Boot&amp;nbsp;up!&lt;/h2&gt;

&lt;p&gt;Now, reboot one last time and everything should go&amp;nbsp;smoothly.&lt;/p&gt;

&lt;p&gt;If your system comes up without any troubles, start attaching those others disks and drives you had disconnected during the installation. There shouldn’t be any issues&amp;nbsp;here.&lt;/p&gt;

&lt;h2 id="youre-done"&gt;You’re&amp;nbsp;done!&lt;/h2&gt;

&lt;p&gt;Congratulations. You now have a&amp;nbsp;CustoMac!&lt;/p&gt;

&lt;p&gt;Keep in mind that you should not blindly install any update you see. Installing an update my change the bootloader or change kernel extensions that break your&amp;nbsp;system.&lt;/p&gt;

&lt;p&gt;A good tip is to create a full disk image of your &lt;span class="caps"&gt;SSD&lt;/span&gt; using a tool like &lt;a href="http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html"&gt;Super Duper&lt;/a&gt;. In case of shit hitting the fan after an update, you can easily restore your disk to working&amp;nbsp;order.&lt;/p&gt;

&lt;p&gt;In my case, I’ve attached an old &lt;span class="caps"&gt;500GB&lt;/span&gt; drive to store this disk image. It works&amp;nbsp;great.&lt;/p&gt;

&lt;h2 id="shiny-and-fast"&gt;Shiny and&amp;nbsp;fast!&lt;/h2&gt;

&lt;p&gt;Just as a side-note, my CustoMac is blazingly fast. It’s the combination of the fast &lt;em&gt;Ivy Bridge&lt;/em&gt; architecture, the i5 processor, and the&amp;nbsp;&lt;span class="caps"&gt;SSD.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;I’ve measured boot-up time from pressing the power button to the Mac &lt;span class="caps"&gt;OS&lt;/span&gt; X login screen at about 11&amp;nbsp;seconds.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=MVoTjMtGw5U:5VPjG7DStn4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=MVoTjMtGw5U:5VPjG7DStn4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=MVoTjMtGw5U:5VPjG7DStn4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=MVoTjMtGw5U:5VPjG7DStn4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=MVoTjMtGw5U:5VPjG7DStn4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=MVoTjMtGw5U:5VPjG7DStn4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=MVoTjMtGw5U:5VPjG7DStn4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/MVoTjMtGw5U" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/11/22/customac/</feedburner:origLink></item><item><title>A Call to all CI Service Providers</title><link>http://feedproxy.google.com/~r/ariejan/~3/itxJr0-BWJ0/</link><pubDate>Sun, 04 Nov 2012 15:00:00 PST</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-11-05:/2012/11/05/a-call-to-all-ci-service-providers/</guid><description>&lt;p&gt;As a professional developer I test my code. Every check-in I do is tested either on &lt;a href="http://kabisa.nl"&gt;Kabisa&lt;/a&gt;’s &lt;a href="http://jenkins-ci.org"&gt;Jenkins&lt;/a&gt; server or on &lt;a href="http://travis-ci.com"&gt;Travis &lt;span class="caps"&gt;CI&lt;/span&gt; Pro&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For open source projects there’s &lt;a href="http://travis-ci.org"&gt;Travis &lt;span class="caps"&gt;CI&lt;/span&gt;&lt;/a&gt;. It’s free and a great way to get to know&amp;nbsp;Travis.&lt;/p&gt;

&lt;p&gt;Now, as an individual I have some side projects, most notably my own site, &lt;a href="http://ariejan.net"&gt;Ariejan.net&lt;/a&gt;. I value well written and well tested code as much for my own stuff as for my professional work. However, I don’t have a Jenkins &lt;span class="caps"&gt;CI&lt;/span&gt; server in my&amp;nbsp;basement.&lt;/p&gt;

&lt;p&gt;Looking around the internets there are a few &lt;span class="caps"&gt;CI&lt;/span&gt; services that can test my Ariejan.net Rails application, among them &lt;a href="https://circleci.com"&gt;Cirlce &lt;span class="caps"&gt;CI&lt;/span&gt;&lt;/a&gt;, &lt;a href="http://www.atlassian.com/software/bamboo/"&gt;Atlassian Bamboo&lt;/a&gt; and &lt;a href="https://semaphoreapp.com"&gt;Semaphore&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, the thing here is that to test the few projects I have (about four) it will cost me more to have the hosted in a &lt;span class="caps"&gt;CI&lt;/span&gt; services than actually running these&amp;nbsp;apps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Travis - $129/mo for 2 concurrent&amp;nbsp;builds.&lt;/li&gt;
  &lt;li&gt;Circle &lt;span class="caps"&gt;CI&lt;/span&gt; - $49/mo for 10 private&amp;nbsp;projects.&lt;/li&gt;
  &lt;li&gt;Semaphore - 	$39/mo for 5 private&amp;nbsp;projects.&lt;/li&gt;
  &lt;li&gt;Bamboo - $20/mo for 10&amp;nbsp;jobs.¹&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;em&gt;¹ Bamboo advertises $10/mo, but a $10/mo Jira subscription is also&amp;nbsp;required.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As an individual, these prices are pretty steep for the few commits I make during the&amp;nbsp;weekend.&lt;/p&gt;

&lt;h3 id="looking-at-github-and-heroku"&gt;Looking at Github and&amp;nbsp;Heroku&lt;/h3&gt;

&lt;p&gt;Let’s take a look at github and heroku here. At heroku I pay nothing to host a site. Performance is limited, but it more often than not is sufficient for a side-project. Adding a worker or extra dyno costs about $38/mo. Still less than half of the &lt;span class="caps"&gt;CI&lt;/span&gt; services I&amp;nbsp;mentioned.&lt;/p&gt;

&lt;p&gt;Having private repos with Github is also quite cheap. You’ll get 5 for $7/mo. Which, converted, is about €1 per repo a&amp;nbsp;month.&lt;/p&gt;

&lt;p&gt;Now, as an individual developer, I’m more than happy to use these services for these relatively low&amp;nbsp;fees.&lt;/p&gt;

&lt;h3 id="where-are-the-cheap-individual-ci-services"&gt;Where are the cheap, individual &lt;span class="caps"&gt;CI&lt;/span&gt;&amp;nbsp;services?&lt;/h3&gt;

&lt;p&gt;As an individual developer, this is what I&amp;nbsp;need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlimited, or at least 5-10 jobs/private&amp;nbsp;projects.&lt;/li&gt;
  &lt;li&gt;Low monthly cost: $5 -&amp;nbsp;$10.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;What I don’t need&amp;nbsp;is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concurrency and&amp;nbsp;paralellisation&lt;/li&gt;
  &lt;li&gt;Immediate&amp;nbsp;execution&lt;/li&gt;
  &lt;li&gt;24/7&amp;nbsp;Support&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I can do with a single worker doing one build at a time. I don’t write enterprise &lt;span class="caps"&gt;CRM&lt;/span&gt; software in my weekends, you&amp;nbsp;know.&lt;/p&gt;

&lt;p&gt;Also, I don’t expect my build to execute immediately. I don’t mind if there’s a job queue and I have to wait a bit longer to get back&amp;nbsp;results.&lt;/p&gt;

&lt;h3 id="business-opportunity"&gt;Business&amp;nbsp;opportunity?&lt;/h3&gt;

&lt;p&gt;&lt;span class="caps"&gt;IMHO&lt;/span&gt; there’s a business opportunity here. Github and Heroku are great examples of how giving something away for free (or cheap) to individual developers creates a market for their&amp;nbsp;product.&lt;/p&gt;

&lt;p&gt;I understand that &lt;span class="caps"&gt;CI&lt;/span&gt; takes a considerable amount of system resources and time, but having a good experience as an individual is more than likely to attrack people to your platform when they need a more profession&amp;nbsp;plan.&lt;/p&gt;

&lt;p&gt;Who’s stepping up to the&amp;nbsp;plate?&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=itxJr0-BWJ0:_Qxh2IoNT8c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=itxJr0-BWJ0:_Qxh2IoNT8c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=itxJr0-BWJ0:_Qxh2IoNT8c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=itxJr0-BWJ0:_Qxh2IoNT8c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=itxJr0-BWJ0:_Qxh2IoNT8c:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=itxJr0-BWJ0:_Qxh2IoNT8c:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=itxJr0-BWJ0:_Qxh2IoNT8c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/itxJr0-BWJ0" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/11/05/a-call-to-all-ci-service-providers/</feedburner:origLink></item><item><title>Decorating Sorcery's current_user with Draper</title><link>http://feedproxy.google.com/~r/ariejan/~3/n1zCtgtO7vs/</link><pubDate>Thu, 01 Nov 2012 16:00:00 PDT</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-11-02:/2012/11/02/decorating_sorcery_current_user_with_draper/</guid><description>&lt;p&gt;I already &lt;a href="http://ariejan.net/2012/04/14/decorating-devise-s-current_user-with-draper"&gt;wrote&lt;/a&gt; about how to apply your decorator to the &lt;code&gt;current_user&lt;/code&gt; when you’re using &lt;a href="https://github.com/plataformatec/devise"&gt;Devise&lt;/a&gt;. However, the trick is a bit different when applied to &lt;a href="https://github.com/NoamB/sorcery"&gt;Sorcery&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of being &lt;code&gt;nil&lt;/code&gt; when no user is signed in, Sorcery uses an explicit &lt;code&gt;false&lt;/code&gt; value, no &lt;code&gt;nil&lt;/code&gt;. In your &lt;code&gt;ApplicationController&lt;/code&gt; at &lt;code&gt;app/controllers/application_controller.rb&lt;/code&gt; add&amp;nbsp;this:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1
2
3&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;current_user&lt;/span&gt;
  &lt;span class="no"&gt;UserDecorator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decorate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I’m using the most recent version of &lt;a href="https://github.com/drapergem/draper"&gt;Draper&lt;/a&gt; by the&amp;nbsp;way.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1zCtgtO7vs:31hxZOC4s78:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=n1zCtgtO7vs:31hxZOC4s78:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1zCtgtO7vs:31hxZOC4s78:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=n1zCtgtO7vs:31hxZOC4s78:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1zCtgtO7vs:31hxZOC4s78:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=n1zCtgtO7vs:31hxZOC4s78:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1zCtgtO7vs:31hxZOC4s78:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/n1zCtgtO7vs" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/11/02/decorating_sorcery_current_user_with_draper/</feedburner:origLink></item><item><title>A static file server in Go</title><link>http://feedproxy.google.com/~r/ariejan/~3/n1sUhomLj1A/</link><pubDate>Wed, 03 Oct 2012 15:00:00 PDT</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-10-04:/2012/10/04/a-static-file-server-in-go/</guid><description>&lt;p&gt;If you don’t know Go, you should really look into it. Today I was trying to figure out how to write a simple (and fast) static file server in&amp;nbsp;Go.&lt;/p&gt;

&lt;p&gt;As it turns out, this is very easy to do. Go contains (in the &lt;code&gt;net/http&lt;/code&gt; package) a nice &lt;code&gt;FileServer&lt;/code&gt; type that can server files from the directory you point it&amp;nbsp;to.&lt;/p&gt;

&lt;p&gt;Here’s a sweet and short&amp;nbsp;example:&lt;/p&gt;

&lt;div class="code"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;
&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;
&lt;td class="code"&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":4242"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FileServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"public"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error running web server for static assets: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By itself this is not very useful, but you can easily integrate this into any other http server you create, maybe for handling dynamic requests or doing web&amp;nbsp;sockets.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1sUhomLj1A:M-qpGZRzOUw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=n1sUhomLj1A:M-qpGZRzOUw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1sUhomLj1A:M-qpGZRzOUw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=n1sUhomLj1A:M-qpGZRzOUw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1sUhomLj1A:M-qpGZRzOUw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=n1sUhomLj1A:M-qpGZRzOUw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=n1sUhomLj1A:M-qpGZRzOUw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/n1sUhomLj1A" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/10/04/a-static-file-server-in-go/</feedburner:origLink></item><item><title>Migrate git repositories</title><link>http://feedproxy.google.com/~r/ariejan/~3/aa3hoZRApnU/</link><pubDate>Sun, 30 Sep 2012 15:00:00 PDT</pubDate><guid isPermaLink="false">tag:ariejan.net,2012-10-01:/2012/10/01/migrate-git-repositories/</guid><description>&lt;p&gt;Sometimes you have to move your git repository to another host. In this case I want to move a privately hosted git repository to a brand spanking new github&amp;nbsp;repository.&lt;/p&gt;

&lt;p&gt;These are four easy steps to get that&amp;nbsp;done:&lt;/p&gt;

&lt;pre class="plaincode"&gt;$ git clone --bare git@yourserver.com:project.git
$ cd project.git
$ git push --mirror git@github.com:ariejan/project.git
$ cd .. &amp;amp;&amp;amp; rm -rf project.git
&lt;/pre&gt;

&lt;p&gt;That’s it. Don’t forget to update the &lt;code&gt;remote&lt;/code&gt; of your working copy&amp;nbsp;accordingly:&lt;/p&gt;

&lt;pre class="plaincode"&gt;$ git remote set-url origin git@github.com:ariejan/project.git
&lt;/pre&gt;

&lt;p&gt;Of course, this works with any git server or service, not just Github, although Github is awesome and you should use&amp;nbsp;it.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=aa3hoZRApnU:Zm6XFYR4JwY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=aa3hoZRApnU:Zm6XFYR4JwY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=aa3hoZRApnU:Zm6XFYR4JwY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=aa3hoZRApnU:Zm6XFYR4JwY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=aa3hoZRApnU:Zm6XFYR4JwY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?i=aa3hoZRApnU:Zm6XFYR4JwY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ariejan?a=aa3hoZRApnU:Zm6XFYR4JwY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ariejan?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ariejan/~4/aa3hoZRApnU" height="1" width="1"/&gt;</description><feedburner:origLink>http://ariejan.net/2012/10/01/migrate-git-repositories/</feedburner:origLink></item></channel></rss>
