Install software to make software that makes software


I’m watching my terminal as Homebrew installs during my latest episode of yak-shaving. I feel a strange urge to explore the Homebrew site, a step that has nothing to do with the reason why I’m here. Hi, I’m Cliff. You’re here as the result of an unfortunate chain of events. You probably started to wash laundry when you realized you were out of detergent. On your way out the door to get detergent you noticed the handle was slightly loose and decided it needed to be tightened. Somewhere between looking for the screwdriver to fix the door something prompted you to check your email, before long you found yourself on Facebook where my post caught your eye. That’s one possible reason why you’re here. I’m here because some four footed hoofed creature with too much hair demanded my attention.

Hairy four legged beast demanding attention
Hairy four legged beast demanding attention

Extreme Yak Shaving
Have you ever found yourself downloading an OpenGL & SDL framework while watching a tutorial when what you really needed to do was install a missing JDBC driver? Today I found myself in a similar situation where I merely wanted to change a dependency in my Android project. That got me thinking about dependency management on iOS, and hey I just learned about this cool project called CocoaPods. To install Cocoa Pods I need Ruby. I can’t install Ruby the old school way, I’m downloading RVM! RVM’s install directions use the gpg command which isn’t available on Mac OS X. I need Mac Ports or Homebrew to install the Linux package. NO!!! I refuse to get side tracked with Homebrew! I’ll skip the gpg step and just use the curl command to direct install without checking security signatures!! The RVM install completes and while I install Ruby I notice the shell is going out to Homebrew land to automate the install. Gosh, I haven’t looked into Homebrew in over a year… I should check out their webpage to see what’s new. It’s always good to get the latest scoop on long living tech like Homebrew. Yak shaving is the work of doing meta work in order to do actual work. Extreme yak shaving is the distraction that results from work of doing the meta work.

I am installing software (Homebrew) to install software (ruby) to install software (Cocoa Pods) which I’ll use to install my iOS software dependencies. I’m not even getting into the learning curve associated with this major distraction. Am I losing it? (Don’t act like it’s just me! Some of you are waiting on a Unity or gaming engine download right now because you ran out of toilet paper!) How do we get some many layers of abstraction between us and the work we actually intend to do? I’m thinking eventually things will swing in the other direction as they always do. Instead of using systems to manage the install of managers that install frameworks we use to build systems (which ultimately manage the install of managers that install…) we will obsess over slim code and vanilla iOS/Java. Languages like Go are already becoming mainstream I’m waiting for the idea to spill into mobile which has currently gone the way of EJB. Until then I’ll keep watching my progress bar fill while the next software installing software installs.

Mac Automator tip of the day


So I was looking in TextMate for one of my most favorite tools from IntelliJ. It’s the “Compare with clipboard” action that takes whatever you have selected and runs a side-by-side diff with whatever is on your clipboard. I thought for sure it would exist in TextMate but I was disappointed so I built my own using Automator. See the pic below for the entire source. (There’s gotta be a better way to share Automator source but I’m in a hurry and lazy so there ya’ go.) This workflow depends on Xcode’s FileMerge but you can substitute whatever diff tool you’re comfortable with. To create it, start Automator and select System service from the “New…” action then copy in the actions from the image. Name it “Compare selection with clipboard” and then where ever you are in your Mac you will have access to the tool from the context menu (right clicking) of any selection.

Automator workflow
Compare selection with clipboard

When I first posted this there was a small bug. I changed the get clipboard step to an Applescript command “get the clipboard” since the built-in Automator task returns styled text instead of raw text.

Fetch Keychain credentials from Ant


It’s been sooo long since I’ve done any serious Java coding. I thought I would never be back in the doc pages for Ant and Ivy. Alas, here I am, revisiting topics of yesteryear. I was stubbing my toe this morning on our artifact repository which requires manual entry of LDAP credentials and it was hurting a lot! The problem is how our custom version of Ivy does multiple authentication retries when it gets an error which effectively locks you out of the system for 30 minutes the 1st time you enter your password incorrectly. This was as unacceptable as my tacky solution of storing my credentials in a plain-text file on my hard drive. I thought it was high time I did something about my pain.

I thought to myself, “Self…”, (I always refers to myself in the 2nd person speaking on behalf of an undefined third person but using a capital “Self” as the proper noun.) “how come every other application on your Mac is smart enough to use keychain whenever you need to lookup your LDAP credentials? Surely there has to be a modern solute for your problem these days.” A quick Bing search revealed a shell command that I could execute on the command line and output either my user name or my password. The commands were slightly different but sufficient for the Ant exec task after a little massaging. The hardest part was, as always, escaping the quotes and special characters in the command. Here’s my working target which accepts a domain parameter to authenticate against:

    <target name="keychain-credentials">
        <property name="domain" value="mydomain.com"/>
        <property name="uid.cmd">-c 'security find-internet-password -s ${domain} | grep acct | cut -d "\"" -f 4'</property>
        <property name="pwd.cmd"><![CDATA[-c 'security 2>&1 >/dev/null find-internet-password -gs ${domain} | cut -d "\"" -f 2']]></property>

        <exec executable="sh" osfamily="mac" outputproperty="uid" errorproperty="uid.error" failonerror="false" failifexecutionfails="false">
            <arg line="${uid.cmd}"/>
        </exec>
        <exec executable="sh" osfamily="mac" outputproperty="pwd" errorproperty="pwd.error" failonerror="false" failifexecutionfails="false">
            <arg line="${pwd.cmd}"/>
        </exec>
        <condition property="my.userid" value="${uid}">
            <not><equals arg1="${pwd}" arg2="password:" trim="true"/></not>
        </condition>
        <condition property="my.password" value="${pwd}">
            <not><equals arg1="${pwd}" arg2="password:" trim="true"/></not>
        </condition>
    </target>