<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pr.ogra.ms</title>
	<atom:link href="http://pr.ogra.ms/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://pr.ogra.ms/blog</link>
	<description>functional codaholism</description>
	<lastBuildDate>Tue, 15 Nov 2011 17:05:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Chroma Key Adventures Part 2: This Is How We Do It</title>
		<link>http://pr.ogra.ms/blog/?p=37</link>
		<comments>http://pr.ogra.ms/blog/?p=37#comments</comments>
		<pubDate>Wed, 12 Oct 2011 00:32:18 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=37</guid>
		<description><![CDATA[Now that I&#8217;ve convinced you all that hue matching is the way to go with chroma key, let me tell you what&#8217;s wrong with the approach I championed in Chroma Key Adventures Part 1. Actually better yet, let me show you:                       My green jacket is a very different green than the background, but it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>Now that I&#8217;ve convinced you all that hue matching is the way to go with chroma key, let me tell you what&#8217;s wrong with the approach I championed in <a title="Chroma Key Adventures Part 1: ImageMagick" href="http://pr.ogra.ms/blog/?p=36">Chroma Key Adventures Part 1</a>.</p>
<p>Actually better yet, let me show you:<br />
<center><a title="Green Jacket Original by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6234813185/"><img src="http://farm7.static.flickr.com/6102/6234813185_4839824dfc_m.jpg" alt="Green Jacket Original" width="240" height="160" /></a>                     <a title="Green Jacket Chroma Key in HSL Space by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6234812131/"><img src="http://farm7.static.flickr.com/6102/6234812131_2cc2874f5a_m.jpg" alt="Green Jacket Chroma Key in HSL Space" width="240" height="160" /></a></center><br />
My green jacket is a very different green than the background, but it&#8217;s getting completely obliterated by ImageMagick.</p>
<p>Our hue matching system clearly has some issues. The main problem is that it&#8217;s all-or-nothing; a pixel is either masked or not. There&#8217;s no gradation. It&#8217;s not a surprise that it confuses the two greens. The whole reason we used <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV">HSL</a> instead of <a href="http://en.wikipedia.org/wiki/RGB_color_model" title="RGB">RGB</a> was because we can find similar colors easily with the hue component! But why can&#8217;t greens be gradually more opaque the further they are from the key color?</p>
<p>Wouldn&#8217;t it be great if there was a way to do chroma key where colors close to the key color but not quite had a transparency value somewhere in between on and off? There is a way, it&#8217;s called <a title="Alpha Compositing" href="http://en.wikipedia.org/wiki/Alpha_compositing">alpha compositing.</a></p>
<h1>Sorry, ImageMagick</h1>
<p>I was researching other chroma key programs and ran across <a title="Chroma Key Plugin for Paint.NET" href="http://forums.getpaint.net/index.php?/topic/12991-chroma-key-green/">this plugin</a> for <a title="Paint.NET" href="http://www.getpaint.net/">Paint.NET</a>. I tried it on some images that I knew were a problem and was amazed. It worked way better than my ImageMagick method, even for the pixels that were not quite the right shade of green.</p>
<p>As much as I love the .NET open source community though, I didn&#8217;t really want to try to automate Paint.NET actions on the fly inside of the <a title="Photobot 3000" href="http://photobot3000.com">Photobot 3000</a>. I also figured that I might need to tweak things in the algorithm to get it just right, so I was leaning heavily towards trying to implement chroma key myself. The creator of the Paint.NET plugin conveniently included a link to the <a title="Chroma Key Algorithm" href="http://www.makebelieve.gr/vl/Publications/SAICSIT99.pdf">paper</a> that they used to create the plugin. The paper turned out to be pretty digestible, so I decided to writing the algorithm myself in C#.</p>
<h1>The Algorithm</h1>
<p>The algorithm starts with looping over the pixels in the image in RGB color space. For each pixel, it checks to see if the green component (we&#8217;re going to use green but they use blue in the paper) is greater than the blue and red components. If not, it leaves the pixel how it is. If so, it decides an alpha value (how transparent to make the pixel) based on how much more green the pixel is than it is red or blue.</p>
<p>For pixels where the green color is only slightly dominant, the alpha stays at 255 (completely opaque.) Then at some configurable threshold, the alphas start counting down until a second threshold where the alpha becomes zero. Every pixel that has a more green than red or blue value higher than the second threshold gets its alpha value set to 0 (completely transparent.)</p>
<p><center><br />
<a href="http://www.flickr.com/photos/agorilla/6234957217/" title="AlphaMap by AGorilla, on Flickr"><img src="http://farm7.static.flickr.com/6096/6234957217_63a0bb80c6.jpg" width="479" height="307" alt="AlphaMap"></a></center><br />
And that&#8217;s basically it. The paper makes it seem hard, but it&#8217;s really simple. And really fast, especially if we create a lookup table for the values in that graph. The paper doesn&#8217;t provide any actual values for the two thresholds, so we will have to play with them to get just the right alpha map.</p>
<h1>The Code</h1>
<p>First, let&#8217;s create the alpha map:</p>
<pre class="prettyprint">
private void initalphaMap()
{
    List&lt;int&gt; alphaMapArray = new List&lt;int&gt;(510);

    //int fullyTransparentEndIndex = 15;
    //int semiTransparentEndIndex = 75;

    int fullyTransparentEndIndex = 15;
    int semiTransparentEndIndex = 100;

    for (int i = 0; i &lt; 510; i++)
    {
        if (i &lt; fullyTransparentEndIndex)
            alphaMapArray.Add(255);
        else if (i &gt;= fullyTransparentEndIndex
                 &#038;&#038; i &lt; semiTransparentEndIndex)
        {
            double lengthOfSemis = semiTransparentEndIndex
                                   - fullyTransparentEndIndex;

            double indexValue = (double)(i - fullyTransparentEndIndex);

            double multiplier = 1 - (indexValue / (double)lengthOfSemis);

            int alphaValue = (int)(multiplier * 255.0);

            alphaMapArray.Add(alphaValue);
        }
        else
            alphaMapArray.Add(0);
    }
    alphaMap = alphaMapArray.ToArray();
}
</pre>
<p>Next, we need to loop through the pixels of our image. There are ways of looping through the image data which are safe and managed by .NET, but on the advice of <a title="Using LockBits" href="http://www.bobpowell.net/lockingbits.htm">this post</a>, I decided to throw caution to the wind and access the memory directly inside of an <strong>unsafe</strong> block. Here&#8217;s the code I&#8217;m using to loop through all of the bits:</p>
<pre class="prettyprint">
private Bitmap operateOnEachPixelOfImage(Bitmap original
                                         , CopyPixelOperation operation)
{
    Rectangle rect = new Rectangle(Point.Empty, original.Size);

    Bitmap output = original.Clone(rect
         , System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    var modifications = output.LockBits(rect
         , System.Drawing.Imaging.ImageLockMode.ReadWrite
         , System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    unsafe
    {
        int pixelSize = 4;

        for (int y = 0; y &lt; modifications.Height; y++)
        {

            byte* row = (byte*)modifications.Scan0
                        + (y * modifications.Stride);

            for (int x = 0; x &lt; modifications.Width; x++)
            {
                byte[] pixel = {row[(x*pixelSize)]
                                , row[(x*pixelSize)+1]
                                , row[(x*pixelSize)+2]
                                , row[(x*pixelSize)+3]};

                byte[] newPixel = operation(pixel);

                row[(x * pixelSize)] = newPixel[0];
                row[(x * pixelSize)+1] = newPixel[1];
                row[(x * pixelSize)+2] = newPixel[2];
                row[(x * pixelSize)+3] = newPixel[3];

            }

        }

    }
    output.UnlockBits(modifications);
    return output;
}</pre>
<p>You may have noticed that I&#8217;m not changing the pixels at all so far. I wanted to be able to reuse the bit-looping code with other operations for which I&#8217;d need to work with each individual pixel. I&#8217;m allowing the caller of this method to inject their own pixel manipulation operation into the loop through a delegate. This makes it trivial to create things like an alpha booster, or a method that makes a photo darker or lighter, and it helped in creating a hue-shifting method that I&#8217;m using for an enhanced version of the chroma key algorithm (which is a topic for another post.)</p>
<p>The actual method that creates our mask is implemented like this:</p>
<pre class="prettyprint">public Bitmap chromaKey(Bitmap original)
{

    return operateOnEachPixelOfImage(original,
            delegate(byte[] pixel)
            {
                int redValue = pixel[2];
                int greenValue = pixel[1];
                int blueValue = pixel[0];

                if (greenValue &gt; redValue &amp;&amp; greenValue &gt; blueValue)
                    pixel[3] = (byte)alphaMap[(greenValue * 2)
                                - redValue - blueValue];
                else
                    pixel[3] = 255;

                return pixel;
            });
}</pre>
<p>This method outputs a Bitmap that has a transparency where we want the background to be inserted. Once you have this, it&#8217;s simply a matter of overlaying the Laser image, which you can do using the built-in Graphics object.</p>
<h1>Results</h1>
<p>The results are hard to argue with. The new method still picks up some other greens but when it does, they&#8217;re only partially transparent. Here are the results, the old ImageMagick hue matching method is on the left, and the new algorithm is on the right.</p>
<p><center><br />
<a title="Green Jacket Chroma Key in HSL Space by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6234812131/"><img src="http://farm7.static.flickr.com/6102/6234812131_2cc2874f5a_m.jpg" alt="Green Jacket Chroma Key in HSL Space" width="240" height="160" /></a> <a title="Green Jacket Chroma Key Alpha Blending by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6235368694/">                     </a><a title="Green Jacket Chroma Key Alpha Blending by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6235368694/"><img src="http://farm7.static.flickr.com/6153/6235368694_2134f3b47e_m.jpg" alt="Green Jacket Chroma Key Alpha Blending" width="240" height="160" /></a></center><br />
As you can see, it works much better. More of the background is getting through, so it&#8217;s brighter, and it&#8217;s not making the jacket completely transparent. If you look closely at my right arm in the new photo, you&#8217;ll see a blue laser faintly dissolving into my jacket. That&#8217;s good! You&#8217;ll never see that at first glance. It&#8217;s unlikely we&#8217;ll ever have a chroma key method that&#8217;s as good at differentiating colors as the human eye, but we can trick the human eye into seeing what we want it to see.</p>
<p>Not only does this method work better, it&#8217;s also much faster and more configurable. If we happen to change the color of the background, it will be really easy to change the code to work with the different color. Also, we can keep honing the alpha map to produce the desired results, and maybe add new features that allow us to perfect this process.</p>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=37</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Chroma Key Adventures Part 1: ImageMagick</title>
		<link>http://pr.ogra.ms/blog/?p=36</link>
		<comments>http://pr.ogra.ms/blog/?p=36#comments</comments>
		<pubDate>Mon, 10 Oct 2011 22:39:29 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=36</guid>
		<description><![CDATA[In my last post, I mentioned the Photobot 3000, a portable photobooth-without-the-booth project I&#8217;ve been working on. After renting it out for a few events, we decided to investigate the possibility of doing in-software chroma key to add fun backgrounds to the photos before they get displayed on the projector. We were already using the [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post, I mentioned the <a title="Photobot 3000" href="http://photobot3000.com/">Photobot 3000</a>, a portable photobooth-without-the-booth project I&#8217;ve been working on. After renting it out for a few events, we decided to investigate the possibility of doing in-software <a title="Chroma Key" href="http://en.wikipedia.org/wiki/Chroma_key">chroma key</a> to add fun backgrounds to the photos before they get displayed on the projector.</p>
<p>We were already using the amazing and versatile <a title="ImageMagick" href="http://www.imagemagick.org/script/index.php">ImageMagick</a> to add a custom logo for each event to the images, so it made sense to see if ImageMagick could do something like chroma key. I was hoping it&#8217;d be as simple as calling ImageMagick with the right arguments, but it turned out to be a bit of a rabbit hole.</p>
<p>Before I started looking into this, I had a skewed idea about how chroma key works. I thought that you just set your key color and software removes every pixel with that color, with some fudge factor so that if a pixel is close enough to be under a certain threshold, it will be removed as well. That mental model is only partially true, and it&#8217;s only one way of implementing chroma key. The point that my brain was glossing over is the definition of the word &#8220;close enough.&#8221; Since I&#8217;d only ever seen images with color information represented as either <a title="RGB Color Model" href="http://en.wikipedia.org/wiki/RGB_color_model">RGB</a> or <a title="CMYK Color Model" href="http://en.wikipedia.org/wiki/Cmyk">CMYK</a>, I assumed that &#8220;close enough&#8221; meant nearby in RGB color space.</p>
<p>In RGB color space however, similar colors aren&#8217;t really next to each other. The lightest green is #00FF00, but the darkest green of the same shade is #000000. In fact, the darkest green is so dark that you can&#8217;t even tell that it&#8217;s green. It&#8217;s just black like every other black. The darkest red is the exact same color as the darkest green in RGB. Because of this, just replacing colors that are close in RGB is not enough.</p>
<p><center><br />
<a title="Bright Green by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6232258768/"><img style="border: 1px solid black;" src="http://farm7.static.flickr.com/6044/6232258768_6184df8e67_m.jpg" alt="Bright Green" width="138" height="240" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a title="Dark Green by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6231740089/"><img style="border: 1px solid black;" src="http://farm7.static.flickr.com/6045/6231740089_06499b5978_m.jpg" alt="Dark Green" width="138" height="240" /></a></center></p>
<h1>Prove it</h1>
<p>To demonstrate this, we&#8217;re going to do some ImageMagick acrobatics. Basically what we have to do is create a mask image based on closeness to our key color in RGB space, then overlay our background image, but mask out the areas that are not close to our key color.</p>
<p>Step 1 is creating the mask image. If we start with a JPG or other compressed image, we need to convert it to a bitmap so that the compare command will work. Similar images in a compressed format may have differences that have nothing to do with the image itself, but are the result of compression artifacts.</p>
<p>The first part of creating the mask is changing every instance of a pixel with a color close to our key color to white and saving the results.</p>
<p>Next, we compare the original image to the mask and then re-save it as the completed mask.</p>
<pre class="prettyprint">convert IMG_7938.JPG IMG_7938.BMP
convert IMG_7938.BMP \
   -fuzz 20% -fill white -opaque \#467c46 IMG_7938_Mask.BMP
compare IMG_7938.BMP IMG_7938_Mask.BMP \
   -compose SRC IMG_7938_Mask.BMP</pre>
<p>Now that we have the mask, we do some smoothing to try and remove some of the noise</p>
<pre class="prettyprint">convert IMG_7938_Mask.BMP \
   -morphology smooth square IMG_7938_Mask.BMP</pre>
<p>Then we sandwich the background, the mask, and the original JPG together</p>
<pre class="prettyprint">composite IMG_7938.JPG Lasers.gif IMG_7938_Mask.BMP \
   IMG_7938_Chromakeyed.JPG</pre>
<p>and get the resulting images:</p>
<p><center><br />
<a title="Original by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6232091152/"><img src="http://farm7.static.flickr.com/6058/6232091152_d9bf05826c_m.jpg" alt="Original" width="240" height="160" /></a><br />
The Original Photo<br />
<br />
<a title="IMG_7938_Mask by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6231685231/"><img src="http://farm7.static.flickr.com/6166/6231685231_a8f910a7dc_m.jpg" alt="Masked in RGB Space" width="240" height="160" /></a><br />
The Mask<br />
<br />
<a title="Chromakey in RGB Space by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6231573153/"><img src="http://farm7.static.flickr.com/6166/6231573153_f7522ea3fc_m.jpg" alt="Chromakey in RGB Space" width="240" height="160" /></a><br />
The Composited Result<br />
<br /></center><br />
This sucks. It can&#8217;t tell the difference between differently colored shadows because it&#8217;s in RGB. We need to account for the difference between things like the green-black in the folds of the background and the red-black in the folds of my shirt. This is where <a title="Hue" href="http://en.wikipedia.org/wiki/Hue">hue</a> comes in.</p>
<h1>Hue</h1>
<p>If we look at that color map a little more closely, we will find the answer to our problem:<br />
<center><br />
<a href="http://www.flickr.com/photos/agorilla/6232297542/" title="Dark Green Hue by AGorilla, on Flickr"><img style="border: 1px solid black;" src="http://farm7.static.flickr.com/6117/6232297542_7eaf8e8213_m.jpg" width="138" height="240" alt="Dark Green Hue"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://www.flickr.com/photos/agorilla/6232297484/" title="Bright Green Hue by AGorilla, on Flickr"><img style="border: 1px solid black;" src="http://farm7.static.flickr.com/6159/6232297484_ddd40c2fb5_m.jpg" width="138" height="240" alt="Bright Green Hue"></a><br />
</center><br />
That&#8217;s right, the brightest green and the darkest green have the same exact hues! That&#8217;s because hue refers to distinct colors, <a href="http://en.wikipedia.org/wiki/Hue" title="Hue">&#8220;&#8230;without tint or shade (added white or black pigment, respectively).&#8221;</a> </p>
<p>Well OK color scientist, but how can we use this? Well, if we just change the colorspace we&#8217;re working with to something that has hue as a component, such as <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV">HSL or HSV</a>, we can identify pixels of our image that have the same hue (or are close within a threshold) regardless of how luminous or saturated they are.</p>
<p>Luckily, we can do this pretty easily with ImageMagick. The <a href="http://www.imagemagick.org/Usage/photos/#chroma_key" title="Chroma Key with ImageMagick">ImageMagick documentation on chroma key</a> gives us a hint as to how to proceed. We can use the <strong>-separate</strong> option on <strong>convert</strong> to separate the image into it&#8217;s distinct hues.</p>
<pre class = "prettyprint">
convert IMG_7938.JPG \
   -colorspace HSL -channel Hue -separate IMG_7938_Hues.JPG
</pre>
<p>If we combine that with what we already have, we get</p>
<pre class="prettyprint">
convert IMG_7938.JPG \
   -colorspace HSL -channel Hue -separate IMG_7938_Hues.JPG

convert IMG_7938_Hues.JPG IMG_7938_Hues.BMP

convert IMG_7938_Hues.BMP \
   -fuzz 20% -fill white -opaque \#606060 IMG_7938_Mask.BMP
compare IMG_7938_Hues.BMP IMG_7938_Mask.BMP \
   -compose SRC IMG_7938_Mask.BMP
convert IMG_7938_Mask.BMP \
   -morphology smooth square IMG_7938_Mask.BMP

composite IMG_7938.JPG Lasers.gif IMG_7938_Mask.BMP \
   IMG_7938_Chromakeyed.JPG
</pre>
<p><strong>#606060</strong> is the specific grey that our background&#8217;s hue turns out to be in the separated file:<br />
<center><br />
<a title="Original by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6232091152/"><img src="http://farm7.static.flickr.com/6058/6232091152_d9bf05826c_m.jpg" alt="Original" width="240" height="160" /></a><br />
The Original Photo<br />
<br />
<a href="http://www.flickr.com/photos/agorilla/6232403160/" title="Original Hue Separated by AGorilla, on Flickr"><img src="http://farm7.static.flickr.com/6043/6232403160_d909375979_m.jpg" width="240" height="160" alt="Original Hue Separated"></a><br />
Hue Separated Image (notice that the background is #606060)<br />
<br />
<a href="http://www.flickr.com/photos/agorilla/6232404430/" title="HSL Mask by AGorilla, on Flickr"><img src="http://farm7.static.flickr.com/6173/6232404430_943cd07f56_m.jpg" width="240" height="160" alt="Hue Mask"></a><br />
HSL Mask<br />
<br />
<a href="http://www.flickr.com/photos/agorilla/6231885101/" title="Chromakey in HSL Space by AGorilla, on Flickr"><img src="http://farm7.static.flickr.com/6091/6231885101_4f7195d515_m.jpg" width="240" height="160" alt="Chromakey in HSL Space"></a><br />
HSL Chroma Key<br />
<br />
</center><br />
This is much better. There are still some problems though, which I will go over in my next post. I think this is the best result we can reasonably get short of writing our own chroma key functionality and operating on the pixels individually. That turns out to not be that scary though&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=36</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Roll your own Tasteful Twitter Ticker</title>
		<link>http://pr.ogra.ms/blog/?p=33</link>
		<comments>http://pr.ogra.ms/blog/?p=33#comments</comments>
		<pubDate>Mon, 10 Oct 2011 18:00:02 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=33</guid>
		<description><![CDATA[Twitter&#8217;s search widget is really nice. So nice that I use it unmodified on the right side of the front page of pr.ogra.ms. You&#8217;re supposed to put it on the sidebar of your blog and it will show a list of a specified number of past tweets vertically. You can have it display any user&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/about/resources/widgets/widget_search" title="Twitter's Search Widget">Twitter&#8217;s search widget</a> is really nice. So nice that I use it unmodified on the right side of the front page of <a href="http://pr.ogra.ms" title="pr.ogra.ms">pr.ogra.ms</a>. You&#8217;re supposed to put it on the sidebar of your blog and it will show a list of a specified number of past tweets vertically. You can have it display any user&#8217;s tweets or specify search terms. It has a limited number of other options which are enough for most applications. Sometimes you need something a little different though.</p>
<p>I&#8217;ve been working on a <a href="http://photobot3000.com/" title="Photobot 3000">project</a> for which a long list of past tweets might not be the best for visibility, layout or usability. The <a href="http://photobot3000.com" title="Photobot 3000">Photobot 3000</a> is a portable photo booth without the booth. It&#8217;s a small box that you set up facing a wall with chairs and a green screen. Party guests sit in the chairs and hit the <a href="http://www.youtube.com/watch?v=4DUmoJNQK2o&#038;feature=youtu.be&#038;t=50s" title="The Jolly Candy-Like Button">big red button</a> on the front of the box. A series of lights counts down and the box takes their picture. All of the pictures are then projected onto a screen for everyone to see.</p>
<p>The projected image is a browser running a web page in full screen mode. For certain events, we also want to show tweets adjacent to the photos using a custom <a href="http://twitter.pbworks.com/w/page/1779812/Hashtags" title="Hashtags">hashtag</a>. We&#8217;ve been using Twitter&#8217;s widget and it&#8217;s been working great, but there are a few things that could make it better.</p>
<p>First, the text is very small, making it hard to read from far away. If we&#8217;re at a venue that doesn&#8217;t have a proper screen and are instead projecting the images on a non-homogenous wall, the tweets are even harder to read. If people can&#8217;t read the tweets, they&#8217;ll be less likely to use the hashtag themselves and the Twitter widget will just become one big waste of space.</p>
<p>Second, having the list of tweets displayed vertically to the right of the photos limits how large we can display the photos. We need to make sure that the Twitter widget adds to the experience and doesn&#8217;t detract from the important portion of the display: the images.</p>
<p>Third, there are some filters that we&#8217;d like to put on the tweets to be displayed that the default Twitter widget doesn&#8217;t support. For example, we&#8217;d like to only show tweets from the same day as the event.</p>
<p>So I decided to start playing around with getting data from Twitter and try to see if I could create my own Twitter widget that only shows one tweet at a time and position it right below each photo.</p>
<p>Before we continue, let me just say that I&#8217;ve been skittish about using ticker-type displays ever since the introduction of the second most hated HTML tag: <a href="http://en.wikipedia.org/wiki/Marquee_element" title="Marquee Tag">&lt;marquee&gt;</a> (second to <a href="http://en.wikipedia.org/wiki/Blink_element" title="Blink Tag">&lt;blink&gt;</a>). But I think I&#8217;ve made a reasonable case for a Twitter ticker widget as long as I keep it tasteful.<br />
<marquee>I promise it&#8217;ll be better than this!</marquee></p>
<h1>Twitter&#8217;s really easy</h1>
<p>It turns out that Twitter is really easy to work with if you&#8217;re just reading public tweets. They expose an interface to get <a href="https://dev.twitter.com/docs/api/1/get/search" title="Twitter Search API">search results in JSON format</a> without having to log-in. If you add in the ease of working with JSON data which <a href="http://jquery.com/" title="jQuery">jQuery</a> provides (which you should because jQuery is awesome,) the code to get Twitter search results becomes pretty trivial:</p>
<pre class="prettyprint">
function getTweets()
{
	var hashTag = "%23flyers";
	var maxTweets = 99;

	var JSONQuery = "http://search.twitter.com/search.json?q="
		+ hashTag + "&#038;callback=?&#038;rpp=" + maxTweets;

 	$.getJSON(JSONQuery, getTweetCallback);

}
function getTweetCallback(ob)
{
	tweets = ob;
}
</pre>
<p>This code&#8217;s pretty straightforward. I&#8217;m asynchronously calling the Twitter search with an arbitrary hashtag (%23 is the <a href="http://en.wiktionary.org/wiki/octothorpe" title="#">octothorpe</a> character.) When the request is complete, the getTweetCallback method is invoked. The rpp option stands for Results Per Page. The maximum is 100 which is fine for my uses, but if you need more than that, you&#8217;ll have to call the JSON search multiple times with the paging query options and aggregate the results.</p>
<h1>Ok, but what do we do with it?</h1>
<p>So we&#8217;ve got all of the tweets, now what do we do? the variable <strong>ob</strong> now contains a member called results which is an array of tweets. Each element has a bunch of data about each tweet, but the members that we&#8217;re going to use are <strong>profile_image_url</strong>, <strong>from_user</strong>, and <strong>text</strong>. So for example, to access the text of the latest tweet, you would do:</p>
<pre class="prettyprint">
ob.results[0].text
</pre>
<p>It&#8217;s not enough to just show the latest tweet though. We want to cycle through the list, showing each tweet for a few seconds. For this, we&#8217;re going to use the Javscript&#8217;s <a href="http://www.w3schools.com/jsref/met_win_settimeout.asp" title="setTimeout">setTimeout</a> function. <strong>setTimeout</strong> sets a one-time timer and after the prescribed duration invokes the specified callback method.</p>
<pre class = "prettyprint">
timer = setTimeout(showNext, interval);
</pre>
<p>The final piece of the puzzle is making it look pretty. Another reason that jQeury is a joy to use is <a href="http://jqueryui.com/" title="jQuery UI">jQuery UI</a>. jQuery UI adds a method called <a href="http://jqueryui.com/demos/toggle/" title="toggle">.toggle</a> that shows or hides an HTML element with a few different options for visual effects. The effects look great and are really easy to invoke.</p>
<pre class="prettyprint">
var toggleType = "blind"
$( "#TwitterTicker" ).toggle(toggleType, options, "slow");
</pre>
<p>Pulling it all together, we have the following Javascript:</p>
<pre class="prettyprint">
function getTweets()
{
	refreshNum = 0;

	if(timer)
		clearTimeout(timer);

	var JSONQuery = "http://search.twitter.com/search.json?q="
		+ hashTag + "&#038;callback=?&#038;rpp=" + maxTweets;

 	$.getJSON(JSONQuery, getTweetCallback);

}
function getTweetCallback(ob)
{
	tweets = ob;
	showNext();
}
function showNext()
{
	if(tweets.results.length &gt; refreshNum+1)
 	{
 		var toggleType = "blind";
 		var options = {}

 		//Calling toggle from jQuery UI to
 		//make the previous tweet invisible.
		$( "#TwitterTicker" ).toggle(toggleType, options, "slow",
		function(){

 			//Using the tweet data
 			var text =
			   "&lt;img style='vertical-align:middle' src='"
			   + tweets.results[refreshNum].profile_image_url
			   + "'/&gt; &lt;a href='twitter.com'&gt;"
			   + tweets.results[refreshNum].from_user
			   + "&lt;/a&gt; "
			   + tweets.results[refreshNum].text;

			$( "#TwitterTicker" ).html(text);

 			if(refreshNum &gt;= maxTweets)
 				getTweets();
 			else
 				refreshNum = refreshNum + 1;

 		});

		 //Calling toggle from jQuery UI to
 		 //make the new tweet visible
		 $( "#TwitterTicker" ).toggle(toggleType, options, "slow");

		 //Setting the timeout timer
		 timer = setTimeout(showNext, interval);
	 }
	 else
	 	getTweets();
}
</pre>
<p>The only slightly tricky part here is that I&#8217;m setting the text of the div element <strong>TwitterTicker</strong> in the callback for the <strong>toggle</strong> method that hides the div. This is so that the text of the tweet doesn&#8217;t change until the div is completely hidden. Here&#8217;s what it looks like:<br />
<script type="text/javascript" src="wp-content/jquery-1.6.2.min.js"></script><script type="text/javascript" src="wp-content/jquery-ui-1.8.16.custom.min.js"></script><script type="text/javascript" src="wp-content/TwitterTicker.js"></script></p>
<div style="background-color:#000;height:145px">
		<center></p>
<h1>
<div id="TwitterTicker" style="color:#fff;background-color:#000;width:100%"></div>
</h1>
<p>		</center>
</div>
<h1>One more thing</h1>
<p>One more thing. <strong>setTimeout</strong> has this weird behavior on many browsers where if you switch tabs or the tab otherwise loses focus, when you return the browser <a href="http://stackoverflow.com/questions/5766263/run-settimeout-only-when-tab-is-active" title="setTimeout Catch Up">tries to &#8220;catch up&#8221;</a>. If you leave this code as-is, you may see a bunch of tweets flashing by quickly if you leave the tab and then come back. That&#8217;s pretty undesirable behavior here, so I added this code to the end of the Javascript file:</p>
<pre class="prettyprint">
 $(document).blur(function(e) {
 	clearTimeout(timer);
 });
 $(document).focus(function(e) {
  	if(timer)
 	 	setTimeout(showNext, interval);
 });
</pre>
<p>This code disables the timer when the tab loses focus and restarts it when it gains focus again. The timer will start over at zero seconds when the focus comes back, but it&#8217;s better than playing catch up!</p>
<p>You can download the Javascript source <a href="http://pr.ogra.ms/blog/wp-content/TwitterTicker.js" title="TwitterTicker.js">here</a> and an example html file <a href="http://pr.ogra.ms/blog/wp-content/TwitterTicker.html" title="TwitterTicker.html">here</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=33</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Turning it up to 12</title>
		<link>http://pr.ogra.ms/blog/?p=23</link>
		<comments>http://pr.ogra.ms/blog/?p=23#comments</comments>
		<pubDate>Tue, 09 Aug 2011 16:59:23 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=23</guid>
		<description><![CDATA[I bought a nice Samsung flat screen from Best Buy during a Black Friday sale and have been mostly happy with it. The built-in speakers are terrible though. Don&#8217;t get me wrong, I&#8217;m no audiophile. I went on a bus tour of Toledo two years ago and still use the free headphones they gave us. [...]]]></description>
			<content:encoded><![CDATA[<p>I bought a nice Samsung flat screen from Best Buy during a Black Friday sale and have been mostly happy with it. The built-in speakers are terrible though. Don&#8217;t get me wrong, I&#8217;m no audiophile. I went on a bus tour of <a title="Toledo, Spain" href="http://en.wikipedia.org/wiki/Toledo,_Spain">Toledo</a> two years ago and still use the free headphones they gave us. The sound on my TV was worse though.<br />
<a href="http://www.flickr.com/photos/agorilla/6144159699/" title="DSC_0004 by AGorilla, on Flickr"><img  class="aligncenter"src="http://farm7.static.flickr.com/6162/6144159699_0ea5636c9d.jpg" width="500" height="333" alt="DSC_0004"></a><br />
I lived with it for a while, but eventually decided that I needed to give myself an auditory experience that matched the visual experience of watching my new TV. I had heard good things about the <a title="Bose Companion 3 Series II" href="http://www.target.com/p/Bose-174-Companion-174-3-Series-II-Multimedia-Speaker-System-Black-40279/-/A-10388666">Bose Companion 3 Series II multimedia speaker system</a>, so I grabbed it on sale from Target.</p>
<p>I knew the speaker system was meant for a computer, but didn&#8217;t think it made any difference. My TV has an audio-out jack, the speakers have an audio-in jack, what could go wrong? I got the speakers home and connected them to the TV. The sound was amazing. My ears ached retroactively from the abuse they had been subjected to from the built-in speakers. Plugging in the new speakers turned Snooki into a virtuoso, Walter White into Louis Armstrong, and the Bridalplasty contestants into sirens.</p>
<p>There was a problem though. When you hook up external speakers to my TV, the TV assumes that the speakers will now control the volume and locks you out of its volume control.<br />
<a   href="http://www.flickr.com/photos/agorilla/6144110127/" title="IMG_7381 by AGorilla, on Flickr"><img class="aligncenter" src="http://farm7.static.flickr.com/6087/6144110127_5b0d0491b9.jpg" width="500" height="333" alt="IMG_7381"></a><br />
That would be fine if the speakers could recognize the volume up and volume down buttons on the TV remote, but this particular set of speakers is geared toward computers and has no IR input whatsoever. In place of an IR reciever it has a big standalone knob, which as an input device is pretty awesome, but you can&#8217;t use it remotely.</p>
<p><a href="http://www.flickr.com/photos/agorilla/6100391389/" title="Turning it up to 12 by AGorilla, on Flickr"><img   class="aligncenter" src="http://farm7.static.flickr.com/6202/6100391389_04afee8d6f.jpg" width="297" height="218" alt="Turning it up to 12"></a></p>
<p>So for months, I would set the volume to a middle level and only change it in dire situations. It&#8217;s only a foot away from the sofa, but it might as well be inside of <a title="Yucca Mountain nuclear waste repository" href="http://en.wikipedia.org/wiki/Yucca_Mountain_nuclear_waste_repository">Yucca Mountain</a>.</p>
<p>This was all just a minor inconvenience, but I would think about the problem a lot. I wasn&#8217;t really trying to solve the issue, I was just using it as a brain teaser. I would try to come up with the most Goldbergian contraption I could. The funniest one was something that intercepts the volume signals from the normal TV remote and then turns a gear that turns the big knob in a direction that corresponds to which volume button you pressed. The conversion of mechanical signal (button press) to IR signal to mechanical signal (gear turning) to electrical signal (from the knob to the speakers) to audio signal (change in volume) seemed hilariously complicated.<br />
<a title="Plan by AGorilla, on Flickr" href="http://www.flickr.com/photos/agorilla/6130606599/"><br />
<img class="aligncenter" src="http://farm7.static.flickr.com/6190/6130606599_b7691cecea.jpg" alt="Plan" width="500" height="275" /></a></p>
<p>It would have stayed just a funny idea if I hadn&#8217;t started playing around with an <a title="Arduino" href="http://www.arduino.cc/">Arduino</a>. Arduinos are tiny programmable microcontrollers that work really well with any sort of electronic component. They use the <a title="Processing.org" href="http://processing.org/">Processing</a> language which is super simple and fun to code in. Making this crazy contraption was the perfect project to get me started with the Arduino. I ran down to the local Radio Shack and bought the two main components of the system: an <a title="IR Reciever Module" href="http://www.radioshack.com/product/index.jsp?productId=2049727">IR reciever module</a> and a <a title="Servo" href="http://www.google.com/products/catalog?q=servo&amp;hl=en&amp;safe=off&amp;prmd=ivnsr&amp;bav=on.2,or.r_gc.r_pw.r_cp.&amp;biw=2400&amp;bih=1086&amp;um=1&amp;ie=UTF-8&amp;tbm=shop&amp;cid=3989395267520219846&amp;sa=X&amp;ei=I3RqTvroMYrF0AHU9KXmBA&amp;ved=0CJoBEPMCMAM">Servo</a> (servo being a fancy word for turny thing) and got started.</p>
<h1>Getting the IR module to respond to my remote</h1>
<p>Getting the IR module to work was not as hard as I thought it would be. I basically used an <a href="http://www.rtfa.net/2008/12/31/arduino-infra-red-ir-remote-control" title="Arduino Infrared IR Remote Control">amazing blog post</a> as the outline for my code. I added some <a href="http://www.arduino.cc/en/Serial/Print" title="Serial.print">Serial.print</a> statements into the pulse_to_bits method so that I could see the codes that the receiver was getting from my particular remote. I ran the code with the Arduino IDE&#8217;s built-in Serial Monitor and was able to find the codes for both the Volume Up button and the Volume Down button on my Samsung remote.<br />
<a href="http://www.flickr.com/photos/agorilla/6131633264/" title="Serial Monitor by AGorilla, on Flickr"><img class="aligncenter" src="http://farm7.static.flickr.com/6201/6131633264_7a40795111.jpg" width="500" height="290" alt="Serial Monitor"></a><br />
The real bit sequence is actually much longer, but the length I collected seems to be enough to be basically unique. At least in my living room.</p>
<h1>Getting the servo to turn the right amount in the right direction</h1>
<p>Getting the servo turning took a little bit more work. Arduino has a Servo library called <a href="http://www.arduino.cc/playground/ComponentLib/Servo" title="Arduino Software Servo">SoftwareServo</a> and there&#8217;s another Arduino <a href="http://code.google.com/p/arduino/source/browse/trunk/libraries/Servo/Servo.h?r=1088" title="Servo.h on Google Code">Servo library</a> on Google Code, but neither of them worked with the servos I had lying around. So not knowing anything about servos, I did some extensive research and more than a little trial and error to come up with the following code.</p>
<pre class="”prettyprint">
void rotateServo(int servoPin, boolean clockwise, int duration)
{
  int pulse = clockwise?1200:1800;
  unsigned long endTime = millis() + duration;

  int i = 1;
  while(endTime &gt; millis())
  {
    digitalWrite(servoPin,HIGH);
    delayMicroseconds(pulse);
    digitalWrite(servoPin,LOW);
    delay(20);
    i++;
  }
}
</pre>
<p>If you send the servo I was working with a stream of ones pulsed at 1200 milliseconds, it will turn clockwise. If you send the same digits but with an 1800ms pulse, it will turn counterclockwise. I sincerely hope someone else looking for this information finds this page, it will save them a ton of time.</p>
<h1>Tying it all together</h1>
<p>Once I had the IR receiver and the servo figured out, I made this circuit.<br />
<a  href="http://www.flickr.com/photos/agorilla/6144660880/" title="IMG_7394 by AGorilla, on Flickr"><img class="aligncenter" src="http://farm7.static.flickr.com/6161/6144660880_3374d059ef.jpg" width="500" height="409" alt="IMG_7394"></a><br />
Here is a video of it in action.<br />
<iframe class="aligncenter" width="560" height="345" src="http://www.youtube.com/embed/N3HQmLPNyKY" frameborder="0" allowfullscreen></iframe><br />
And this is the processing code that I uploaded to the Arduino.</p>
<pre class="prettyprint">
#include &lt;Servo.h&gt;;
// 0.1 by pmalmsten
// 0.2 by farkinga
//This code is mostly verbatim from this blog post
//http://goo.gl/R3Zm8 with the primary modifications
//being the addition of a servo and the magic bit strings
//that represent the volume-up and volume-down buttons
//on my Samsung TV remote.

#define IR_BIT_LENGTH 32
#define BIT_1 1000          //Binary 1 threshold (Microseconds)
#define BIT_0 400           //Binary 0 threshold (Microseconds)
#define BIT_START 2000      //Start bit threshold (Microseconds)
#define DEBUG 1             //Serial connection must be started
                            //to debug

#define IR_PIN 0            //Sensor pin 1 wired through a
                            //220 ohm resistor

#define LED_PIN 9           //"Ready to Recieve" flag, not
                            //needed but nice
#define POWER_PIN 11       // the red LED that indicates
                           //if the power button is pressed.

#define SERVO_PIN 9

#define SERVO_INCREMENT 50

int runtime_debug = 0;
int output_key = 1;
int power_button = 0;

int servoPos = 0;

//IR Codes for my remote
int samsungVolumeUp[] = {1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1};
int samsungVolumeDown[] = {1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,1,0,1,1,1,1};

Servo volumeKnob;

void setup() {
  pinMode(IR_PIN, INPUT);

  volumeKnob.attach(SERVO_PIN);
  volumeKnob.write(servoPos);
  delay(100);
  volumeKnob.detach();

  Serial.begin(9600);
}

void loop() {

  int bitStream[IR_BIT_LENGTH];

  get_ir_key(bitStream);		    //Fetch the key
  do_response(bitStream);

  delay(200);
}

void do_response(int key[])
{
  if(intArraysAreEqual(key, samsungVolumeUp))
  {
    Serial.println("Smasung Volume UP!");
    rotateServo(SERVO_PIN, true, SERVO_INCREMENT);

  }
  else if(intArraysAreEqual(key, samsungVolumeDown))
  {
    Serial.println("Samsung Volume DOWN!");
    rotateServo(SERVO_PIN, false, SERVO_INCREMENT);

  }
  else
    Serial.println("Unrecognized Key.");

}

void read_pulse(int data[], int num_bits)
{
  for (int i = 0; i &lt; num_bits; i++)
  {
    data[i] = pulseIn(IR_PIN, HIGH);
  }
}

void pulse_to_bits(int pulse[], int bits[], int num_bits)
{

  if (DEBUG || runtime_debug) { Serial.println("-----"); }

  for(int i = 0; i &lt; num_bits ; i++)
  {
    //if (DEBUG || runtime_debug) { Serial.println(pulse[i]); }

    if(pulse[i] &gt; BIT_1) //is it a 1?
    {
      bits[i] = 1;
    }
    else if(pulse[i] &gt; BIT_0) //is it a 0?
    {
      bits[i] = 0;
    } 

    else //data is invalid...
    {
      Serial.println("Error");
    }
    Serial.print(bits[i]);
  }
  Serial.println();

}

void get_ir_key(int bits[])
{
  int pulse[IR_BIT_LENGTH];

  do {} //Wait for a start bit
  while(pulseIn(IR_PIN, LOW) &lt; BIT_START);

  read_pulse(pulse, IR_BIT_LENGTH);

  pulse_to_bits(pulse, bits, IR_BIT_LENGTH);

}
void printBits(int bits[])
{
  for(int i = 0; i &lt; IR_BIT_LENGTH; i++)
    Serial.print(bits[i]);
  Serial.println();
}
boolean intArraysAreEqual(int Array1[], int Array2[])
{ 

  for(int i = 0; i &lt; IR_BIT_LENGTH; i++)
  {
    if(Array1[i] != Array2[i])
      return false;
  }

  return true;
}
void rotateServo(int servoPin, boolean clockwise, int duration)
{
  int pulse = clockwise?1200:1800;
  unsigned long endTime = millis() + duration;

  int i = 1;
  while(endTime &gt; millis())
  {
    digitalWrite(servoPin,HIGH);
    delayMicroseconds(pulse);
    digitalWrite(servoPin,LOW);
    delay(20);
    i++;
  }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=23</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8220;Easter Egg&#8221; in Xcode</title>
		<link>http://pr.ogra.ms/blog/?p=31</link>
		<comments>http://pr.ogra.ms/blog/?p=31#comments</comments>
		<pubDate>Sat, 05 Mar 2011 00:44:58 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=31</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/kvop3fj5L_E" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=31</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Make that MySql Backup Put Up or Shut Up</title>
		<link>http://pr.ogra.ms/blog/?p=27</link>
		<comments>http://pr.ogra.ms/blog/?p=27#comments</comments>
		<pubDate>Wed, 02 Feb 2011 22:07:57 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=27</guid>
		<description><![CDATA[Ok, so we&#8217;ve set up a little system to backup a remote MySQL database to another machine periodically. If the host ever loses our data, we just hit the restore button and we&#8217;re back in business, right? I mean, we can see by looking in the backup folder that our little robot process is dilligently [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, so we&#8217;ve set up a little <a href="http://pr.ogra.ms/blog/?p=18">system</a> to backup a remote MySQL database to another machine periodically. If the host ever loses our data, we just hit the restore button and we&#8217;re back in business, right? I mean, we can see by looking in the backup folder that our little robot process is dilligently creating a new file every day and that none of the files are empty. It must be working correctly, right? Wrong! If programming and science fiction have one imperative in common, it&#8217;s NEVER TRUST A ROBOT.</p>
<div class="wp-caption aligncenter" style="width: 345px"><img title="Johnny Five" src="http://farm6.static.flickr.com/5091/5410869079_0f19edabe5.jpg" alt="" width="335" height="500" /><p class="wp-caption-text">Don&#39;t worry, broseph! I got this on lock.</p></div>
<p>And Joel Spolsky <a href="http://www.joelonsoftware.com/items/2009/12/14.html">agrees</a>. Our backup strategy needs to be verified or it&#8217;s worthless. If you&#8217;re not testing your backups, you&#8217;re begging the data gods to hit you with the double whammy: losing your primary data and then realizing your backups have never worked (or maybe you have that one backup from last spring when you were setting up the process.) Think of how terrible your future self will feel when he or she realizes that they were backing up the wrong database every day. How will the Family Guy fanfic community react to the content vacuum created by the loss of your blog?</p>
<p>They&#8217;ll move on. Some other Peter will start a blog and become more successful than you ever were. He&#8217;ll be lauded by the community and you&#8217;ll be shunned. You won&#8217;t be invited to Stewie-con next year, and people will think you&#8217;re crazy when you try to point out that the plot of the new guy&#8217;s opus, &#8220;Cirque de Family&#8221; is suspiciously similar to your masterpiece, &#8220;Brian&#8217;s Carni-fail.&#8221;</p>
<p>Neither of us want that to happen, so we have a choice. We can put all our trust into some broseph-spewing robot, or we can test our backups by faking an emergency and trying to restore to a new database. It&#8217;ll be like a fire drill, except we don&#8217;t have to stand outside our apartment building at 3 am in the middle of February (I know that&#8217;s a great opportunity to chat-up your cute neighbor, but you wouldn&#8217;t need the &#8220;perfect opportunity&#8221; if you just grew a pair and said hi in elevator.)</p>
<h3>The Emergency</h3>
<p>Just for narrative interest, lets invent an emergency. We want something that covers all aspects of the backup process. Since the main point of backing up to a local drive was so that <a href="http://www.apple.com/findouthow/mac/#timemachinebasics">Time Machine</a> would pick it up, we should include a failure of the hard drive to which the backups are being written.</p>
<p>Picture this: you&#8217;re on an airplane returning from a vacation in Italy (fun time, bad drivers). A terrorist sitting behind you shoulder-surfs your MySQL password and overwrites your database with threats against American freedom using his CLEAR 4G card. Then he stands up and starts threatening the pilot with bombs that he smuggled in his shoes AND underwear. He&#8217;s standing right in front of you with his back turned, so you quietly shut your laptop and wait for just the right moment. At the crescendo of his anti-imperialist soliloquy, you whack him with your MacBook so hard the drive crashes, knocking him unconcious. Your database is corrupted, your hard drive is destroyed, but you&#8217;re a hero.</p>
<p>Weeks later, after the parade down Broadway in your honor and the loads of free hardware Apple has thrown at you, you decide it&#8217;s time to restore all of your data from your external Time Machine drive.</p>
<h3>Get the MySql Backup File from Time Machine</h3>
<p>Open a Finder window and navigate to the folder where your WordPress backups are stored. Click the Time Machine toolbar icon and click<strong> Enter Time Machine</strong>. Scroll through history to a time that has the most recent backup. Right-click the file and choose Restore.</p>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Time Machine" src="http://farm6.static.flickr.com/5012/5411744016_0fa62f02d1.jpg" alt="" width="500" height="352" /><p class="wp-caption-text">I put it here somewhere...</p></div>
<p>Time Machine then prompts you for a location to put the restored file. I chose to create a new folder called <strong>Restore</strong>, just so I don&#8217;t get my restored backups and my actual backups mixed up.</p>
<h3>Create a Restore Environment</h3>
<p>We obviously don&#8217;t want this restore to overwrite your existing Family Guy fanfic blog (Fanficly Guy). After all, what if the backup is incomplete or corrupted? We&#8217;d end up destroying the data we&#8217;re trying to protect. We&#8217;ve got to create a separate restore environment.</p>
<blockquote><p>Note: This section is going to cover creating a restore environment for WordPress on DreamHost. If you&#8217;re looking for how to restore from a MySqlDataDump in general, skip to <a href="#mysqldatadumpcommand">Finally do the restore!</a></p></blockquote>
<p>To recreate a similar environment, we&#8217;re going to make new Worpress and MySQL instances. That way we can restore the data to a new clean database. Plus, once we&#8217;re done restoring, we can check that it worked by hitting the new WordPress instance in our browser. If everything works correctly, we should see an exact clone of our original blog.</p>
<p>Just to keep the two environments separated, we&#8217;re also going to create a new subdomain. To add the new subdomain, go to Dreamhost&#8217;s web panel, and click <strong>Domains &gt; Manage Domains &gt; Add New Domain/Sub-Domain</strong>. Name it whatever you want; I named mine <strong>restore</strong>.pr.ogra.ms. Leave all of the other options at their defaults and click <strong>Fully host this domain</strong>.</p>
<p>Now to install a new WordPress instance, click <strong>Goodies &gt; One-Click Installs &gt; WordPress</strong>. Click <strong>Custom Installation</strong> so that it gives you the option of creating a new MySql database. Make sure that <strong>Automatically Create Database</strong> is highlighted in the <strong>Select Database</strong> dropdown and click <strong>Install it for me now!</strong></p>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Host of my dreams" src="http://farm6.static.flickr.com/5094/5428351543_d160785613.jpg" alt="" width="500" height="199" /><p class="wp-caption-text">They make it too easy.</p></div>
<h3>Verify the MySql Connection</h3>
<p>You should be redirected to a confirmation page that tells you the name of the new MySql database. In my case, it&#8217;s <strong>restore_pr_ogra_ms</strong>.</p>
<p style="text-align: left;">
<div class="wp-caption aligncenter" style="width: 650px"><img title="success" src="http://farm6.static.flickr.com/5058/5429021982_a1ed7cd0ec_z.jpg" alt="" width="640" height="112" /></dt>
</dl>
</div>
<p style="text-align: left;">We need to make sure we can access the new database from our local machine, but what username and password do we use? If we click <strong>Goodies &gt; MySql Databases</strong>, we can see the new database in the list. It also tells us the name of a new user that the installation created for us. We still need the password though!</p>
<p style="text-align: left;">
<div class="mceTemp mceIEcenter">
<dl class="wp-caption aligncenter" style="width: 650px;">
<dt class="wp-caption-dt"><img title="mystery user" src="http://farm6.static.flickr.com/5212/5429042126_05d851e6c8_z.jpg" alt="" width="640" height="97" /><p class="wp-caption-text">Locked out of our own database.</p></div>
<p style="text-align: left;">Don&#8217;t worry, the web panel can do <em>anything</em>. Click on the user with access (in my case, <strong>restoreprograms</strong>). It will show the autogenerated password in the <strong>New Password</strong> section (after <strong>Currently:</strong>&#8230;). You should probably not change the autogenerated password because WordPress has connection information hard-coded in the <strong>wp-config.php</strong> file. If you change it here, you&#8217;ll have to change it there. We will be making changes to that file, but keeping the autogenerated password just makes troubleshooting easier.</p>
<p style="text-align: left;">While we&#8217;re in this part of the web panel, we need to add your IP address into the <strong>Allowable Hosts</strong> box. Otherwise, we will not be able to connect to this database from your local machine. Copy the IP address of your current computer (it&#8217;s displayed on the page under <strong>Your current computer is:</strong>) and paste it into the <strong>Allowable Hosts</strong> box. Save your settings.</p>
<p style="text-align: left;">Now we&#8217;re ready to test connectivity from our local machine. Open up a terminal window and run the MySqlDataDump command that we&#8217;ve been using to create these backups, but change the address and login credentials to point to your restore database. You could also connect via MySql and run some SELECT statements, but MySqlDataDump is a quick, simple and unambiguous way to check the connection.</p>
<pre>/usr/local/mysql/bin/mysqldump
	-h restore.pr.ogra.ms
	--user=restoreprograms
	--password=AReallyStrongPassword restore_pr_ogra_ms
</pre>
<p>If you get a scrolling window of gibberish SQL code, congratulations! Your MySql restore environment is ready.</p>
<h3>Verify the Restore WordPress Instance</h3>
<p>Since we&#8217;re verifying everything, we might as well navigate to the new WordPress installation in a browser. Set up the Admin user and check to make sure the default blog entries show up. Logging in as Admin for the first time creates some database tables and sets up some configuration variables, so it&#8217;s important to do this step. Don&#8217;t worry about any of the settings too much, we&#8217;re going to replace all of the new tables with our restored data. Just make sure that you give the Admin user a password and login at least once. If you can see the new blog with the default posts when you navigate to your restore WordPress instance, you&#8217;re all set.</p>
<h3><a name="mysqldatadumpcommand">Finally do the restore!</a></h3>
<p>This part is <em>almost</em> really simple, but there&#8217;s one trick. First, open a terminal window and navigate to the folder to which you restored your Time Machine backup. Now execute the following command:</p>
<pre>/usr/local/mysql/bin/mysql
	-h mysql.restore.pr.ogra.ms
	--user=restoreprograms
	--password=AutoGeneratedPassword restore_pr_ogra_ms
	&lt; 02022011-pr.ogra.ms.MySqlBackup.sql
</pre>
<p>make sure to substitute the credentials of your restore database (<strong>restore_pr_ogra_ms</strong> is the database within my restore MySql instance). Also substitute the name of your extracted backup file for <strong>02022011-pr.ogra.ms.MySqlBackup.sql</strong>.</p>
<p>The backup file is a SQL script that CREATEs all of the WordPress tables and INSERTS all of your data (posts, comments, styles, etc). The above command just pipes the backup file to MySql, which knows to run the script against your restore database. So after this command is run, all of your backed-up data should be in the restore database.</p>
<p>Here&#8217;s the tricky part though: Every WordPress site has a unique prefix that it uses to name its tables. When we logged in to our new WordPress instance as Admin the first time, it generated all of the tables with this unique prefix. The same thing happened the first time you logged in to your real blog. When we ran the backup script, it recreated the tables from our real WordPress blog, prefix and all. This means that now we have two sets of tables in our restore database. That&#8217;s fine, we just need to tell the WordPress config file to use the prefix from our primary site instead of the new blank site and we should be golden.</p>
<p>Go back to the DreamHost web panel and click<strong> Goodies &gt; MySql Databases</strong>. Find your restore database&#8217;s hostname (it should be of the form <strong>mysql.&lt;new subdomain that we made for the restore&gt;</strong>) and click <strong>phpMyAdmin</strong>.</p>
<div class="wp-caption aligncenter" style="width: 650px"><img src="http://farm6.static.flickr.com/5060/5431084833_d0936d2d92_z.jpg" alt="" width="640" height="73" /><p class="wp-caption-text">phpYourAdmin</p></div>
<p>This brings up phpMyAdmin, a nice little web interface for MySql. We&#8217;re going to use this interface to figure out the prefix of our restored tables. To get a listing of all the tables in the WordPress database, click on your database name in the left sidebar (under the phpMyAdmin logo.)</p>
<div class="wp-caption aligncenter" style="width: 406px"><img title="prefixes" src="http://farm5.static.flickr.com/4130/5431120365_a490c7be2f.jpg" alt="" width="396" height="451" /><p class="wp-caption-text">Pre Fixe</p></div>
<p>When the list loads, we can see that there are two sets of tables with the same names but different prefixes. One set is the default tables that were installed when we logged in to our new WordPress instance as Admin, and the other is our restored blog data. Which is which though?</p>
<p>To figure that out, we are going to look at the configuration file that tells WordPress which prefix to look for. The, we&#8217;re going to change the file to point to the real tables. If you have SSH configured for <a title="SSH Passwordless Login" href="http://wiki.dreamhost.com/SSH#Passwordless_Login">passwordless login</a>, run this command to login:</p>
<pre>ssh TheBestHuman@pr.ogra.ms
</pre>
<p>Substituting your username for TheBestHuman and your primary domain name (not the new restore subdomain) for pr.ogra.ms. Now cd into the directory of your restore WordPress instance.</p>
<pre>cd restore.pr.ogra.ms/blog
</pre>
<p>Open the <strong>wp-config.php</strong> file in your favorite editor. Find the line that says</p>
<pre>$table_prefix  = 'wp_5qvylv_';
</pre>
<p>This tells us that <strong>&#8216;wp_5qvylv_&#8217;</strong> is the prefix of the new default installation of WordPress. We want to point it to our restored tables, so simply change this value to the prefix of the <em>other</em> set of tables.</p>
<pre>$table_prefix  = 'wp_wg0xrn_';
</pre>
<p>Finally, navigate to your restore instance (restore.pr.ogra.ms/blog) and BOOM, we have an exact copy of our blog!</p>
<h3>This is Important, Just Do It</h3>
<p>If you follow these instructions, it should take less than half an hour to verify a WordPress backup. If you weigh that half-hour against the hours and days you&#8217;ve spent crafting your online identity with an interesting and useful blog, it becomes laughable not to do a test restore at least once a month. If you never do a test restore, you have no idea whether or not your backups are working. Why spend time setting up and running a backup process every day if you&#8217;re not going to test it? As far as I&#8217;m concerned, an untested backup is the same as no backup.</p>
<p>Don&#8217;t just trust your robots; you never know when they&#8217;re going to turn evil and kill your data.</p>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=27</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Surviving the Unit Testing Wasteland of Objective-C and OCUnit</title>
		<link>http://pr.ogra.ms/blog/?p=21</link>
		<comments>http://pr.ogra.ms/blog/?p=21#comments</comments>
		<pubDate>Thu, 27 Jan 2011 02:53:09 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=21</guid>
		<description><![CDATA[Sooner or later you&#8217;re going to want to unit test your Cocoa apps. You&#8217;ll put it off as long as possible, but you&#8217;ll start to feel dirty without them. Your app will start to feel like peanut butter without jelly, or hot cocoa without marshmallows. You&#8217;ll put up with anything to get your code unit [...]]]></description>
			<content:encoded><![CDATA[<p>Sooner or later you&#8217;re going to want to unit test your Cocoa apps. You&#8217;ll put it off as long as possible, but you&#8217;ll start to feel dirty without them. Your app will start to feel like peanut butter without jelly, or hot cocoa without marshmallows. You&#8217;ll put up with anything to get your code unit tested. No setup cost will be too great.</p>
<p>That may sound a little codependent, and unit testing in objective-c is a lot like an emotionally abusive relationship. There are a bunch of <a href="http://stackoverflow.com/questions/33207/what-is-the-best-way-to-unit-test-objective-c-code">options</a> out there, but OCUnit just feels comfortable and besides, it&#8217;s been with you since the beginning (because it came bundled with Xcode). OCUnit can&#8217;t stay terrible forever, it&#8217;s got to change right? right? What&#8217;s so bad about OCUnit anyway?</p>
<h3>What&#8217;s Wrong with OCUnit?</h3>
<p>Well for starters, all OCUnit tests happen <em>at build time</em>, not as separate run-time tasks. This small distinction makes it very difficult to debug unit tests. You can set things up so that when you choose <strong>Build and Debug</strong> in Xcode, it runs the tests once at build time and then a second time as your app starts running. On the second run-through, breakpoints will get hit, but the debugger doesn&#8217;t really work. It&#8217;s a mess that&#8217;s annoying to deal with, so you&#8217;re probably going to start falling back to NSLogging everything and just running the tests through <strong>Build</strong>.</p>
<p>Another problem is that there&#8217;s no separate GUI that shows all of your tests as green or red for pass or fail. If a test fails, the build fails. To find out which one failed, you have to drill down to the specific test in the build results window. It&#8217;s hard to do<a href="http://jamesshore.com/Blog/Red-Green-Refactor.html"> Red, Green, Refactor </a>without red or green. There are third-party GUIs such as <a href="https://launchpad.net/ocrunner">OCRunner</a> that are doing their best to usher OCUnit into the mid-aughts by providing a nice GUI. I haven&#8217;t been able to get them working yet though (maybe a future post).</p>
<p>Finally, OCUnit requires specific naming conventions for test classes and methods. I admit that this is more of a style choice than a genuine shortcoming. In some other unit test packages such as <a href="http://www.nunit.org/">NUnit</a> for .NET, classes and methods are identified as test cases in metadata (NUnit uses <a href="http://www.nunit.org/index.php?p=testFixture&amp;r=2.2.10">attributes</a>.) With OCUnit however, all test class names must end with &#8220;TestCase&#8221; and each test method must begin with &#8220;test&#8221; in order for them to be recognized by OCUnit. This may seem like just the choice of <a href="http://en.wikipedia.org/wiki/Convention_over_configuration">convention over configuration</a>, but it&#8217;s really convention <em>as</em> configuration. Instead of making things easier and more intuitive, it hides information about the behavior of a class or method in its name.</p>
<h3>What&#8217;s Right With OCUnit?</h3>
<p>Ok, now you&#8217;re about to leave a comment &#8220;If you think OCUnit sucks so much, don&#8217;t use it!&#8221;, but that&#8217;s not true. I don&#8217;t think OCUnit is that bad. It gets the job done and could grow into the testing framework that we all want it to be. It does have some things going for it too.</p>
<p>When you&#8217;re choosing tools, a real concern is that development on a particular tool will stagnate and you&#8217;ll be left in the cold with outdated tools that you can&#8217;t migrate from. OCUnit is bundled with Xcode, so development is probably going to continue for the foreseeable future. Who knows, maybe Apple already has developers dedicated to improving it. Or writing a unit testing framework that&#8217;s compatible with it.</p>
<p>Also, despite my ranting, once you get OCUnit running and know its quirks, it&#8217;s pretty easy to use. Its shortcomings only really cost you time when setting it up and learning how to use it. Most of the problems I&#8217;ve mentioned above don&#8217;t have recurring costs.</p>
<p>Conveniently, you can minimize that initial cost of setting up and learning OCUnit by reading the rest of this post. It will not only help you survive the wasteland, but thrive with Unit Testing in the Objective-C world.</p>
<h3>Add a new testing target</h3>
<p>The first thing we need to do is add a new <strong>Unit Test Bundle</strong> target to an existing project that we want to unit test. Right click on the <strong>Targets</strong> section of the project file list and click <strong>Add&gt;New Target</strong>.</p>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Add New Target" src="http://farm6.static.flickr.com/5176/5391086438_29fc9d2740.jpg" alt="" width="500" height="163" /><p class="wp-caption-text">Target Aqcuired.</p></div>
<p>Choose <strong>Unit Test Bundle</strong> and click <strong>Next</strong>.</p>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Unit Test Bundle" src="http://farm6.static.flickr.com/5179/5390479519_289dd24969.jpg" alt="" width="500" height="452" /><p class="wp-caption-text">Bundle Up!</p></div>
<p>Usually people name it <strong>HotPotatoTests</strong> where HotPotato is the name of their project. I don&#8217;t think the naming affects anything though, so feel free name it a cuss word if you like and click <strong>Finish</strong>.</p>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Cuss Words" src="http://farm6.static.flickr.com/5212/5390479555_bc55e8d2a3.jpg" alt="" width="500" height="452" /><p class="wp-caption-text">I recommend naming it something safe for work if you&#39;re at work.</p></div>
<h3>Add a new group for your test files</h3>
<p>We&#8217;re probably going to end up writing at least one test class per functionality class, so the project&#8217;s going to start to get messy. Let&#8217;s just nip that clutter in the bud right now and create a group called <strong>Test</strong> into which we will put all of our test case files. Right click your project&#8217;s name in the <strong>Groups &amp; Files </strong>pane, and go to <strong>Add&gt;New Group</strong>. You should probably not name this a cuss word, you&#8217;re just going to confuse yourself.</p>
<h3>Add a new Test Case file</h3>
<p>Now it&#8217;s time to add a new testing class. Right click your newly created <strong>Test</strong> group and go to <strong>Add&gt;New File&#8230;</strong> Choose<strong> Objective-C Test Case Class</strong> from the <strong>Cocoa Class</strong> section and hit <strong>Next</strong>.</p>
<p>This next part is <strong>VERY IMPORTANT</strong>. It is the first of two things that are absolutely vital to saving yourself frustration. Every test case class in OCUnit <strong>must</strong> end with the suffix <strong>TestCase</strong>. A nice convention is to name it HotPotatoTestCase where HotPotato is the name of the class under test. That way it&#8217;s stupid easy to find the tests for that class. Don&#8217;t forget to add <strong>TestCase</strong> to the end though. Promise me you won&#8217;t forget. I&#8217;m serious, pinky swear in the comments.</p>
<p>Once we have a test case class, the first thing we should do is write a failing test and run it to make sure it fails. Add the following code to the .m file of the test case class:</p>
<pre class="”prettyprint">-(void) testThatTestingIsWorking
{
	STFail(@"YOU WILL ALWAYS BE A FAILURE");
}</pre>
<p>This is the second <strong>VERY IMPORTANT</strong> part. It is again crucial to your sanity that you remember to do the following exactly: You must name all test methods so that they begin with the word <strong>test</strong>. Don&#8217;t forget! Oh please don&#8217;t forget.</p>
<h3><strong>Run your failing test</strong></h3>
<p>Now click that little unlabeled drop down in the upper left corner of the main Xcode window and switch the <strong>Active Target </strong>to your test target.</p>
<p>The next part is optional, but you probably want it. Expand the <strong>Targets</strong> section of your project. Now click and drag your executable target onto your test target. This will make your executable a dependency of your test target. Now, every time you attempt to build the test target, it will build the executable first. This ensures that the code under test always reflects the current code and not just whatever is lying around from the last time you built your executable.</p>
<p>Now comes the fun part, running the test! Just go to <strong>Build&gt;Build</strong> and your test should run. The first time I did this, I was like &#8220;oh shit there are build errors, I&#8217;m doing this tutorial wrong.&#8221; Don&#8217;t worry, you&#8217;re not doing it wrong. Well you may be doing it wrong, but you should be expecting build errors here because a test failure counts as a build error. We need to dig a little to see exactly what the build error is though.</p>
<h3>Finding the Failure</h3>
<p>First bring up the <strong>Build Results</strong> window by doing <strong>command+shift+b</strong>. At this point, we could simply do a full expansion on the line where you see the errors by clicking the little <img class="alignnone" src="http://farm6.static.flickr.com/5179/5391130792_0dff4d2a26_t.jpg" alt="" width="24" height="18" /> button. But that gets you a big long log file that sucks to parse with your eyes. We can get a <em>slightly</em> more readable list of results by expanding <strong>Run custom shell script &#8216;Run Script&#8217; &gt; Run unit tests for architecture &gt; Run test suite &lt;octest path&gt;</strong>. Here you will see a list of test case classes with an exclamation point if they&#8217;ve failed. You can further expand that to see the actual test methods that failed, and then drill down to the actual failure.</p>
<div class="wp-caption alignnone" style="width: 627px"><img title="FAILURE" src="http://farm6.static.flickr.com/5015/5391086408_6034da4327_o.jpg" alt="" width="617" height="130" /><p class="wp-caption-text">Ok, I guess it is red.</p></div>
<p>It&#8217;s annoying, but you&#8217;ll get used to it. Because you have to.</p>
<h3>Test your actual code from your actual project</h3>
<p>Most of the tutorials I&#8217;ve encountered stop here without telling you how to reference the code in your executable from your test case classes. It&#8217;s not intuitive but it&#8217;s just something you have to learn to do. I don&#8217;t know why they usually exclude this part, maybe the authors didn&#8217;t actually try to unit test anything significant. We live in the real world though, so we need to actually reference our actual code.</p>
<p>The first thing we&#8217;ll do is go to the <strong>Groups &amp; Files </strong>pane and drag the code files (just the .m files) under test into the <strong>Compile Sources</strong> folder inside your test target. This is the magic that tells Xcode that you&#8217;re going to need access to the code from these files when you build the test target. So, if you&#8217;re testing a class called StringBasedTime, you grab StringBasedTime.m and drop them into the folder under <strong>Targets&gt;HotPotatoTests&gt;Compile Sources</strong> (where HotPotatoTests is the name of your test target.)</p>
<p style="text-align: center;">
<div class="wp-caption aligncenter" style="width: 275px"><img class=" " title="Dragging" src="http://farm6.static.flickr.com/5136/5390479473_8ff6f9ae79_o.jpg" alt="" width="265" height="500" /><p class="wp-caption-text">Cuss words everywhere!</p></div>
<p>Then in the test case file that you&#8217;re using to test this code (StringBasedTimeTest.m,) you simply add a directive to import the header file:</p>
<pre class="”prettyprint">#import "StringBasedTime.h"
</pre>
<p>And that&#8217;s it, you can reference your executable class in your test code!</p>
<h3>Example Unit Test</h3>
<p>Here&#8217;s a simple unit test that I wrote in real life for a real reason. I&#8217;m using it to test the initializer of a class I&#8217;m building called StringBasedTime. StringBasedTime takes an argument in it&#8217;s initalizer that is a string representation of a time interval. The string representation is based on the output of <a title="QTStringFromTime" href="http://developer.apple.com/library/mac/#technotes/tn2005/tn2138.html">QTStringFromTime</a>, which is a method in QTKit, Cocoa&#8217;s QuickTime framework. It converts a QTime to an NSString in the format <strong>dd:hh:mm:ss.ff/ts</strong>. For example, @&#8221;0:00:00:00.00/00&#8243; is the very beginning of a QuickTime movie. The test we&#8217;re looking at just makes sure that if someone initializes a new StringBasedTime with <strong>@&#8221;0:00:00:00.00/00&#8243;</strong>, each of the properties gets populated with zero. If one doesn&#8217;t, I want the failure output to tell the tester which property is non-zero. Here&#8217;s the code from the test case&#8217;s .m file:</p>
<pre class="”prettyprint">#import "StringBasedTimeTestCase.h"
#import "StringBasedTime.h"

@implementation StringBasedTimeTestCase

-(void) testInitWithStringZeroTime
{
	NSString *ZeroTimeString = @"0:00:00:00.00/00";
	StringBasedTime *ZeroTime =
		[[StringBasedTime alloc] initWithString:ZeroTimeString];

	NSString* FailText = @"";

	if([ZeroTime days] != 0)
		FailText = [FailText stringByAppendingFormat:
					@"%d days when 0 expected."
					, [ZeroTime days]];

	if([ZeroTime hours] != 0)
		FailText = [FailText stringByAppendingFormat:
					@"%d hours when 0 expected."
					, [ZeroTime hours]];

	if([ZeroTime minutes] != 0)
		FailText = [FailText stringByAppendingFormat:
					@"%d minutes when 0 expected."
					, [ZeroTime minutes]];

	if([ZeroTime seconds] != 0)
		FailText = [FailText stringByAppendingFormat:
					@"%d seconds when 0 expected."
					, [ZeroTime seconds]];

	if([ZeroTime timescale] != 0)
		FailText = [FailText stringByAppendingFormat:
					@"%d timescale when 0 expected."
					, [ZeroTime timescale]];

	STAssertEquals(@"", FailText, FailText);

}
@end
</pre>
<h3>Debugging</h3>
<p>Remember, NSLog is your friend when debugging. I know <a href="http://stackoverflow.com/questions/189562/what-is-the-proper-name-for-doing-debugging-by-adding-print-statements">printf debugging</a> sucks, but sometimes it&#8217;s your best option. It might be possible to get the debugger working with OCUnit, but I haven&#8217;t been able to crack that code. If you figure it out, please feel free to leave a comment!</p>
<h3>Further Reading</h3>
<p>I figured out how to do all of this from a few good tutorials on OCUnit (and a few bad ones!):</p>
<ul>
<li><a href="http://stackoverflow.com/questions/33207/what-is-the-best-way-to-unit-test-objective-c-code">What is the best way to unit test Objective-C code?</a></li>
<li><a href="http://chanson.livejournal.com/119097.html">Chris Hanson&#8217;s series on Unit Testing in Xcode</a> &#8211; Very comprehensive series of blog posts on OCUnit</li>
<li><a href="http://mobileorchard.com/ocunit-integrated-unit-testing-in-xcode/">OCUnit: Integrated Unit Testing in Xcode</a></li>
<li><a href="http://developer.apple.com/tools/unittest.html">Test Driving Your Code With OCUnit</a></li>
<li><a href="http://developer.apple.com/library/ios/#documentation/Xcode/Conceptual/iphone_development/135-Unit_Testing_Applications/unit_testing_applications.html">iOS Development Guide: Unit Testing Applications</a> &#8211; This is where Apple <a href="http://stackoverflow.com/questions/2002330/implementing-unit-testing-with-the-iphone-sdk">lies</a> and tells you that when a test fails, Xcode will highlight the line on which it failed.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=21</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ridin&#8217; Dirty With your MySQL Database Backups</title>
		<link>http://pr.ogra.ms/blog/?p=18</link>
		<comments>http://pr.ogra.ms/blog/?p=18#comments</comments>
		<pubDate>Tue, 18 Jan 2011 19:10:29 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=18</guid>
		<description><![CDATA[I switched credit cards a while back and forgot to change the autopay settings for my Dreamhost account so they turned off my hosting. During the recovery process, I lost a few (terrible and uninteresting) blog entries. Even though it was my fault, it&#8217;s left me twice shy about leaving my data integrity in someone [...]]]></description>
			<content:encoded><![CDATA[<p>I switched credit cards a while back and forgot to change the autopay settings for my <a href="http://www.dreamhost.com/">Dreamhost</a> account so they turned off my hosting. During the recovery process, I lost a few (terrible and uninteresting) blog entries. Even though it was my fault, it&#8217;s left me twice shy about leaving my data integrity in someone else&#8217;s hands. For most of my data, I&#8217;m running Mac OS X on my laptop and use <a title="Time Machine Basics" href="http://www.apple.com/findouthow/mac/#timemachinebasics">Time Machine</a> to back up to an external drive. I needed to find a way to get my WordPress database onto the Time Machine train. I know this blog is starting out a little Dreamhost heavy, but this should apply to anyone wanting to backup a remote MySql database.</p>
<h3>MySQLDataDump</h3>
<p>MySQL comes bundled with an awesome utility called MySQLDataDump. You throw it a database, user name and password, and it outputs a SQL script that creates all the tables and inserts all the data. First, you have to install MySQL locally though.  Finding the right download for MySQL is a little like finding the installer for Java was back in the day. They try to hide it to make you accidentally pay money for it or something. I&#8217;ve gone ahead and sussed out the <a href="http://www.mysql.com/downloads/mysql/">link</a> for you though.  After you install MySQL locally, it&#8217;s really easy to get a dump of your database from Terminal (This should all be on one line, but I didn&#8217;t want to make you have to scroll to the right forever so I broke it up a little):</p>
<pre>/usr/local/mysql/bin/mysqldump
	-h WordPressDatabase.pr.ogra.ms
	--user=TheBestHuman
	--password=AReallyStrongPassword WordPressDatabaseName
</pre>
<p>Once the terminal window stops scrolling, we can talk about piping this output to a nice text file and zipping it up, but first a Dreamhost digression:  In order to access a MySQL database remotely, you need to add the host to the Allowable Hosts list on their web panel. Don&#8217;t believe me? Check out <a title="Connect to Your MySQL Database from Third-Party Programs" href="http://wiki.dreamhost.com/MySQL#Connect_to_Your_MySQL_Database_from_Third-Party_Programs">the wiki</a>. I&#8217;m not sure what I&#8217;m going to do when my IP address changes, but for now, I just went to <strong>Goodies&gt;MySQL Databases </strong>on the web panel, then clicked on the user that I wanted to have remote access, then added my current IP address to the list of Allowable Hosts.</p>
<h3>Put The Output of MySQLDataDump Into a File</h3>
<p>I knew I would probably want to schedule this backup with a cron job later, so I wanted to put a date stamp in the filename that we pipe the output of MySQLDataDump to. Fortunately, <a href="http://en.wikipedia.org/wiki/Date_%28Unix%29">Unix&#8217;s date</a> does exactly what we need it to (again, this was put onto multiple lines for readability, the real command should be just a single line).</p>
<pre>/usr/local/mysql/bin/mysqldump
	-h  WordPressDatabase.pr.ogra.ms
	--user=TheBestHuman
	--password=AReallyStrongPassword WordPressDatabaseName
&gt;
	~/Documents/Projects/pr.ogra.ms/Wordpress Database Backup/
	$(date +%m%d%Y)-pr.ogra.ms.MySqlBackup.sql.zip
</pre>
<p>That&#8217;s nice&#8230; real nice. All this crap is going to start filling up the drive though, so let&#8217;s zip it up</p>
<pre>/usr/local/mysql/bin/mysqldump
	-h WordPressDatabase.pr.ogra.ms
	--user=TheBestHuman
	--password=AReallyStrongPassword WordPressDatabaseName
	| gzip &gt;
	~/Documents/Projects/pr.ogra.ms/Wordpress Database Backup/
	$(date +%m%d%Y)-pr.ogra.ms.MySqlBackup.sql.zip
</pre>
<p>Make sure you name the output file .sql.zip so that when you unzip, it has the .sql extension. Who knows, we might run this script in Windows some day.</p>
<h3>Schedule it wih Crontab</h3>
<p>I had never used crontab before this, though I knew it existed. It&#8217;s a little idiosyncratic, but easy to pick up. You can always use a third-party task scheduler like <a href="http://www.peterborgapps.com/lingon/">Lingon</a>, but I find cron jobs to be way simpler to use.</p>
<p>In order to schedule a task, you need to add a line to crontab&#8217;s configuration text file. The line format is split into two sections, the first is five numbers separated by spaces indicating the minute, hour, day of the month, month, and day of the week that you want the job to run. You can substitute an asterisk (*) for any of these numbers to tell cron to execute the job every hour, minute, etc. The second section (after another space) is the actual command you want to execute. Here&#8217;s a nice little diagram that I stole from <a title="Pilfered diagram!" href="http://adminschoice.com/crontab-quick-reference">this site</a>:</p>
<pre>*     *     *   *    *        command to be executed
-     -     -   -    -
|     |     |   |    |
|     |     |   |    +----- day of week (0 - 6) (Sunday=0)
|     |     |   +------- month (1 - 12)
|     |     +--------- day of        month (1 - 31)
|     +----------- hour (0 - 23)
+------------- min (0 - 59)
</pre>
<p>How do you get to this config file though? just type</p>
<pre>crontab -e
</pre>
<p>and you get a nice VI window with the file opened. If you&#8217;re confused or just don&#8217;t want to think right now, here is the line I inserted to tell crontab to execute the data dump every day at noon:</p>
<pre>0 12 * * * /usr/local/mysql/bin/mysqldump
	-h   WordPressDatabase.pr.ogra.ms
	--user=TheBestHuman
	--password=AReallyStrongPassword
	WordpressDatabaseName
	| gzip &gt;
	~/Documents/Projects/pr.ogra.ms/Wordpress Database Backup/
	$(date +%m%d%Y)-pr.ogra.ms.MySqlBackup.sql.zip
</pre>
<p>This should all be on one line though, here it is for copying:</p>
<pre>0 12 * * * /usr/local/mysql/bin/mysqldump -h   WordPressDatabase.pr.ogra.ms --user=TheBestHuman --password=AReallyStrongPassword WordPressDatabaseName | gzip &gt; ~/Documents/Projects/pr.ogra.ms/Wordpress Database Backup/ $(date +%m%d%Y)-pr.ogra.ms.MySqlBackup.sql.zip
</pre>
<p>Just paste that line into the crontab config file and your MySQL(YourSQL?) database is on the Time Machine Train!</p>
<div class="wp-caption aligncenter" style="width: 490px"><img class=" " title="Doc Brown" src="http://farm6.static.flickr.com/5290/5330513093_401a2cab0d_o.jpg" alt="" width="480" height="270" /><p class="wp-caption-text">&quot;Your data&#39;s safe with me, Marty!&quot;</p></div>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=18</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Mercurial Running on DreamHost Part II: Cloning an Existing Local Repo to the Server and Making it the Parent</title>
		<link>http://pr.ogra.ms/blog/?p=19</link>
		<comments>http://pr.ogra.ms/blog/?p=19#comments</comments>
		<pubDate>Tue, 11 Jan 2011 18:35:14 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=19</guid>
		<description><![CDATA[Last time, we talked about getting Mercurial running on Dreamhost, which should be enough to allow you to start creating repos on the server (using hg init while ssh&#8217;d in) and cloning them locally. But what if you already have repos with a rich history on your local machine and want to clone them to [...]]]></description>
			<content:encoded><![CDATA[<p>Last time, we talked about <a title="Getting Mercurial Running on Dreamhost" href="http://pr.ogra.ms/blog/?p=17">getting Mercurial running on Dreamhost</a>, which should be enough to allow you to start creating repos on the server (using <strong>hg init</strong> while ssh&#8217;d in) and cloning them locally. But what if you already have repos with a rich history on your local machine and want to clone them to the server? I promise it&#8217;s easy, but I&#8217;d like to make a quick digression because something&#8217;s been bugging me.</p>
<p>I&#8217;ve always wondered why Mercurial&#8217;s executable was called hg. I thought that maybe it was a holdover from an ancestor project- the way Firefox&#8217;s executable was called mozilla for a while. It turns out that I was selling Mercurial&#8217;s developers short and that they do, in fact, have their shit together:</p>
<p style="text-align: center;">
<div class="wp-caption aligncenter" style="width: 137px"><img class="    " title="Mercury" src="http://farm6.static.flickr.com/5083/5343976427_b9274e082e_m.jpg" alt="" width="127" height="127" /><p class="wp-caption-text">Chemistry Nerds!</p></div>
<p style="text-align: left;">It was named after the elemental symbol for mercury, Hg. The Mercurial Logo even looks like a glop of Mercury.</p>
<div class="wp-caption aligncenter" style="width: 194px"><img title="http://farm6.static.flickr.com/5169/5344584640_a910811ed9_o.png" src="http://farm6.static.flickr.com/5169/5344584640_a910811ed9_o.png" alt="" width="184" height="61" /><p class="wp-caption-text">Liquid at Room Temperature</p></div>
<p style="text-align: left;">The symbol <a title="Mercury" href="http://en.wikipedia.org/wiki/Mercury_%28element%29">Hg</a> is short for <em>hydrargyrum</em> which comes from the Latinized Greek prefix hyrda- meaning <em>watery</em> <em>or</em> <em>runny </em>and the word argyros meaning <em>silver</em>. So it means runny silver. I can imagine the Greeks making prank phone calls: &#8220;Is your silver runny? Then you better go catch it!&#8221; and getting people all mad and Latinized over it. Anyway, back to</p>
<h3 style="text-align: left;">3. Clone my existing local repositories to the server and then make that server the parent</h3>
<p>Should be easy, right? It is. Ned Batchelder&#8217;s <a title="How Do I Move a Private Mercurial Repository to a Central Server?" href="http://stackoverflow.com/questions/3105427/how-do-i-move-a-private-mercurial-repository-to-a-central-server/3105582#3105582">answer</a> to this Stack Overflow question nails it. First, ssh into your Dreamhost account, then create a new repository on the server to house the repo that&#8217;s already on your local machine. Make sure that it&#8217;s in the repo parent directory (specified in hgweb.config) so that hgweb.cgi will pick it up.</p>
<pre>cd ~/hg/repos

mkdir HotPotato

cd HotPotato

hg init
</pre>
<p>Now logout of your ssh session and use Terminal to navigate to the local directory of the repository you want to clone to the server. Use the<strong> hg push</strong> command to get the local repo up to your newly created server repo.</p>
<pre>hg push ssh://TheBestHuman@pr.ogra.ms/hg/repos/HotPotato
</pre>
<p>Make sure you put the <strong>ssh://</strong> prefix on the URI or you&#8217;ll get a <em>repository not found </em>error message. Now you should be able to go to hgweb.cgi and see your new (old) repo.</p>
<div class="wp-caption aligncenter" style="width: 547px"><img class=" " title="Hot Potato" src="http://farm6.static.flickr.com/5207/5344676940_69017f0f0c_z.jpg" alt="" width="537" height="126" /><p class="wp-caption-text">Your &quot;New&quot; Repo!</p></div>
<p>Your repo is available on the server, but we need to make it so that when you <strong>hg push</strong> from your local repo, it remembers what server to push to. This will make it so you don&#8217;t have to specify the server repo&#8217;s URI every time you want to push your changes up.</p>
<pre>vi .hg/hgrc
</pre>
<p>with vi open, add the following lines to the hgrc file.</p>
<pre>[paths]
default = ssh://TheBestHuman@pr.ogra.ms/hg/repos/HotPotato
</pre>
<p>Any changes you commit locally from now on will get pushed to the server if you run <strong>hg push</strong>!</p>
<p>But wait, if you ssh back in to the server and <strong>ls</strong> in the new repo&#8217;s directory, you won&#8217;t see any files!</p>
<div class="wp-caption aligncenter" style="width: 214px"><img title="WTF" src="http://farm6.static.flickr.com/5246/5344713990_691cda1afd_o.png" alt="" width="204" height="86" /><p class="wp-caption-text">Dub Tee Eff</p></div>
<p>What was all that console output if it wasn&#8217;t uploading the repo to the server? And how come when you navigate to hgweb.cgi, there&#8217;s a bunch of history about files that don&#8217;t seem to exist? Well, it has to do with some Mercurial fundamentals. The repo&#8217;s root directory (~/hg/repos/HotPotato) contains the working copy of the repo. Mercurial, however, only cares about committed code. Since we <strong>hg push</strong>ed the local repo to the server, Mercurial is aware of the changes, but has not applied those changes to the working copy on the server. The changes are all sitting in the <strong>.hg</strong> subfolder (~/hg/repos/HotPotato/.hg). If you never want to work on code and commit changes from the server, this is fine. It doesn&#8217;t really matter what the working copy on the server contains. But if you ever want to be able to edit code directly from an ssh session on the server, you&#8217;ll have to bring the working copy up to date.</p>
<pre>hg update
</pre>
<p>You&#8217;ll also have to do this from any repo that you clone from the server copy.</p>
<p>And that&#8217;s it! Don&#8217;t worry, the workflow seems like a lot to remember but it will start to feel really natural after a while.</p>
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=19</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Mercurial Running on DreamHost</title>
		<link>http://pr.ogra.ms/blog/?p=17</link>
		<comments>http://pr.ogra.ms/blog/?p=17#comments</comments>
		<pubDate>Wed, 05 Jan 2011 18:53:06 +0000</pubDate>
		<dc:creator>brian</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://pr.ogra.ms/blog/?p=17</guid>
		<description><![CDATA[A while back, Joel Spolsky wrote a fantastic tutorial on distributed version control systems. It&#8217;s a really clear and honest overview of Mercurial from the perspective of a recently converted skeptic. DVCS has many advantages over the old client-server model of source control, but I think the one killer advantage is that it works with [...]]]></description>
			<content:encoded><![CDATA[<p>A while back, Joel Spolsky wrote a <a title="Hg Init: a Mercurial tutorial by Joel Spolsky" href="http://hginit.com">fantastic</a> tutorial on distributed version control systems. It&#8217;s a really clear and honest overview of <a title="Mercurial SCM" href="http://mercurial.selenic.com/">Mercurial</a> from the perspective of a recently converted skeptic. DVCS has many advantages over the old client-server model of source control, but I think the one killer advantage is that it works with or without a central server. This means that whenever I&#8217;m working on a personal project, I can just type &#8220;hg init&#8221; in the directory and BOOM, I&#8217;m tracking my changes. Later on, if I want to go through the whole process of remembering passwords to my web host, installing Mercurial, and setting up my local copy to push to a central server, I can. The real magic of DVCS though is that central server really means anything here, I could start pushing code to my analog watch if I could get Mercurial running on it.</p>
<div class="wp-caption alignleft" style="width: 190px"><img class="  " src="http://farm6.static.flickr.com/5281/5327252831_5f261cc926_m.jpg" alt="" width="180" height="240" /><p class="wp-caption-text">Terrorism is also distributed</p></div>
<p>Joel&#8217;s tutorial had me intrigued, <em>Mercurious</em> if you will. So when I finally got some time to work on personal projects, I started using it. And I&#8217;m hooked. I haven&#8217;t had much need for the D in DVCS yet though because I&#8217;m the only one committing any code. I&#8217;ve been using Mercurial as local revision control, but I&#8217;ve been using it for EVERYTHING; my resume redesign, Arduino code, even Movable Type theme modifications. I can&#8217;t get over how easy and quick it is to turn any normal project into a legitimate source controlled juggernaut. And there&#8217;s no guilt about polluting the codebase! After a while, I started thinking that maybe I should version control my OkCupid profile, or my Facebook friends. I know I&#8217;m addicted because sometimes when I&#8217;m at the bar, I think &#8220;I wish I could hg commit right now and revert if it turns out that I drank too much.&#8221;</p>
<p>I started to get nervous though. Any important data that&#8217;s not in the cloud makes me nervous. I had some time on my hands the other day, so I decided to try to install Mercurial on my <a title="Dreamhost" href="http://www.dreamhost.com/">DreamHost</a> account and keep a main repository there. It would also give me a chance to commit code from different machines, or different partitions on a single machine without breaking the flow of work. I was thirsting for that all-powerful D.</p>
<p>Usually when I want to do something new with DreamHost, I pray that they have a one-click install in their web panel and if they don&#8217;t I give up. I&#8217;ve been writing software for most of my life and am embarrassed to say, installing things in Unix baffles me. I wasn&#8217;t so lucky on this one, there is no one-click install, but they did have the next best thing. One of the great things about DreamHost is that they have a large user base and their <a title="Dreamhost Support Wiki" href="http://wiki.dreamhost.com/Main_Page">support wiki</a> is packed with enough documentation to hang yourself. Sure enough, there&#8217;s a page on <a title="How to Install Mercurial" href="http://wiki.dreamhost.com/Mercurial#How_To_Install_Mercurial">installing Mercurial</a>. That&#8217;s not the end of the story though, there are really three things I want to do here:</p>
<ol>
<li><em>Install Mercurial on my DreamHost account</em></li>
<li><em>Configure Mercurial to allow me to push and pull code from the server</em></li>
<li><em>Clone my existing local repositories to the server and then make that server the parent</em></li>
<p><em> </em></p>
<p><em> </em></ol>
<h4>1. Install Mercurial on my DreamHost account</h4>
<div class="wp-caption alignright" style="width: 220px"><img title="Turtles are shell users too" src="http://farm6.static.flickr.com/5125/5327553453_48a5f569a0_o.png" alt="" width="210" height="144" /><p class="wp-caption-text">Turtles are shell users too</p></div>
<p>In order to do this, we&#8217;re going to need a shell account and we&#8217;re going to need to log in to it. If you don&#8217;t already have a shell account, go to the DreamHost web panel and click <strong>Users &gt; Manage Users</strong>. Now click <strong>Add User</strong> and set the <strong>Type of User Account</strong> to <strong>Shell</strong>.</p>
<p>Next, we need to SSH into the account. Our trusty DreamHost support wiki also has an entry for <a title="SSH Passwordless Login" href="http://wiki.dreamhost.com/SSH#Passwordless_Login">configuring SSH for passwordless login</a>, which you can do to make it dead simple to login to your DreamHost shell:</p>
<pre>ssh TheBestHuman@pr.ogra.ms
</pre>
<p>Now that we&#8217;re logged in, we can actually install Mercurial from the source code. This part is pretty much just following the instructions from <a title="How to Install Mercurial" href="http://wiki.dreamhost.com/Mercurial#How_To_Install_Mercurial">this page</a> of the support wiki. I&#8217;m going to repeat the steps here with some explanations so we&#8217;ll have everything in one place.</p>
<p>First, make a directory for the Mercurial source and download it. I wanted to make things easier for myself so I went with the same version that&#8217;s in the tutorial.</p>
<pre>mkdir -p ~/srcs
cd ~/srcs
wget http://mercurial.selenic.com/release/mercurial-1.6.3.tar.gz
</pre>
<p>Mercurial&#8217;s latest stable release is 1.7.3, so we&#8217;re not that far off. Or are we? Who cares, I&#8217;m new to Mercurial, I won&#8217;t notice the difference. Next, unzip, make and make install it.</p>
<pre>tar xvzf mercurial-1.6.3.tar.gz
cd mercurial-1.6.3
make all
make install-home
</pre>
<p>Now do some bash configuration stuff, changing the default path for Python and the Mercurial configuration file or something.</p>
<pre>vi ~/.bash_profile

* add these lines at the bottom:
export PYTHONPATH=~/lib/python
export PATH=~/bin:$PATH
export HGRCPATH=TheBestHuman/.hgrc
</pre>
<p>Make sure to replace <strong>TheBestHuman</strong> with your DreamHost username because, well, there can be only one. After all this, you should be able to do</p>
<pre>hg --version
</pre>
<p>and get 1.6.3 or whatever version you decided to go rogue and install.</p>
<p>So now we have Mercurial installed on the server. Badass. It&#8217;s only accessible if we&#8217;re shelled into our account though; we want to be able to push and pull code<em> from Malaysia</em> if we happen to be there and the McDonald&#8217;s has free wifi.</p>
<h4>2. Configure Mercurial to allow us to push and pull code from the server</h4>
<p>The heart of Mercurial&#8217;s code publishing capabilities is a Python script called <a title="HgWeb Step-by-Step" href="http://mercurial.selenic.com/wiki/HgWebDirStepByStep">HgWeb.cgi</a>. It&#8217;s a nice little piece of code that not only serves the repos up to remote users, but also provides you with a slick read-only web interface to your revisions (basically a friendly web version of the hg log command). Sounds awesome, right? Let&#8217;s set it up!</p>
<p>First, make a subdirectory for your repos.</p>
<pre>mkdir -p ~/hg/repos
</pre>
<p>Now create the configuration file for the publishing script.</p>
<pre>vi ~/hg/hgweb.config

* ...and add the following lines:
[collections]
repos/ = repos/
[web]
style = gitweb
</pre>
<p>The default script is packaged with the Mercurial source, so copy it from there to your hg directory and add execute privileges to the copied file.</p>
<pre>cp ~/srcs/mercurial-1.6.3/hgweb.cgi ~/hg
chmod +x ~/hg/hgweb.cgi
</pre>
<p>At this point, the wiki tells you to change the python version in hgweb.cgi, but I followed the directions and eventually (after a painful 20 minutes) had to switch this back to its original value. I&#8217;d recommend leaving the script as-is at first. If you&#8217;re getting a 500 error trying to access the hgweb.cgi page later on, you can go back and force the script to use  python 2.4.</p>
<p>Next, change the following lines in hgweb.cgi</p>
<pre>config = "/path/to/repo/or/config"
#import sys; sys.path.insert(0, "/path/to/python/lib")
</pre>
<p>to:</p>
<pre>config = "/home/TheBestHuman/hg/hgweb.config"
import sys; sys.path.insert(0, "/home/TheBestHuman/lib/python")
</pre>
<p>Remember to replace <strong>TheBestHuman</strong> with your shell user name. Next, do some Apache crap:</p>
<pre>vi ~/hg/.htaccess

* ...add the following lines (Comments optional) and then save the file 

# Taken from http://www.pmwiki.org/wiki/Cookbook/CleanUrls#samedir
# Used at http://ggap.sf.net/hg/
Options +ExecCGI
RewriteEngine On
#write base depending on where the base url lives
RewriteBase /hg
RewriteRule ^$ hgweb.cgi  [L]
# Send requests for files that exist to those files.
RewriteCond %{REQUEST_FILENAME} !-f
# Send requests for directories that exist to those directories.
RewriteCond %{REQUEST_FILENAME} !-d
# Send requests to hgweb.cgi, appending the rest of url.
RewriteRule (.*) hgweb.cgi/$1  [QSA,L]
</pre>
<p>After that, all that&#8217;s left to do is map the hg directory to somewhere on your domain. You can do this by creating a symbolic link to it from a sub directory of your domain.</p>
<pre>cd ~/pr.ogra.ms
ln -s ~/hg
</pre>
<p>You might need to change some permissions.</p>
<pre> chmod 755 ~
 find ~/pr.ogra.ms -type d -print0 | xargs -0r chmod 755
 find ~/pr.ogra.ms -type f -print0 | xargs -0r chmod 644
</pre>
<p>At this point, you should be able to see an empty Mercurial page if you navigate to http://yourdomain/hg. Don&#8217;t worry, when you get some projects in there, it&#8217;ll look like this:</p>
<div class="wp-caption aligncenter" style="width: 650px"><img title="Mercurial Web" src="http://farm6.static.flickr.com/5201/5327662875_e83e6e419f_z.jpg" alt="" width="640" height="150" /><p class="wp-caption-text">A preview of what&#39;s to come</p></div>
<p>So right now, we have an empty Mercurial installation with no repositories that&#8217;s absolutely useless. Mission Accomplished!</p>
<p>Not really, the next post will show you how to move an existing repo to your newly pimped Mercurial server and making it the root repo.</p>
<p>Continue on to <a title="Getting Mercurial Running on DreamHost Part II: Cloning an Existing Local Repo to the Server and Making it the Parent" href="http://pr.ogra.ms/blog/?p=19">Getting Mercurial Running on DreamHost Part II: Cloning an Existing Local Repo to the Server and Making it the Parent</a></p>
<p style="text-align: center;">
]]></content:encoded>
			<wfw:commentRss>http://pr.ogra.ms/blog/?feed=rss2&#038;p=17</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

