Ant Tasks for Git

Ant has tasks for CVS and Subversion, but none that I could find for Git. I threw together these simple Ant macros to get started:

<macrodef name = "git">
    <attribute name = "command" />
    <attribute name = "dir" default = "" />
    <element name = "args" optional = "true" />
    <sequential>
        <echo message = "git @{command}" />
        <exec executable = "git" dir = "@{dir}">
            <arg value = "@{command}" />
            <args/>
        </exec>
    </sequential>
</macrodef>

<macrodef name = "git-clone-pull">
    <attribute name = "repository" />
    <attribute name = "dest" />
    <sequential>
        <git command = "clone">
            <args>
                <arg value = "@{repository}" />
                <arg value = "@{dest}" />
            </args>
        </git>
        <git command = "pull" dir = "@{dest}" />
    </sequential>
</macrodef>

The first one, “git” just runs git with whatever command you provide to it (clone, pull, etc) along with any arguments you pass to it. Clone:

<git command = "clone">
    <args>
        <arg value = "git://github.com/280north/ojunit.git" />
        <arg value = "ojunit" />
    </args>
</git>

And pull:

<git command = "pull" dir = "repository_path" />

(Other git command will likely work, these are just the ones I needed)

The second one, “git-clone-pull” uses the first one to clone a repository then pull from it. This effectively clones the repository if it hasn’t already been cloned, otherwise it pulls. However, since ant is fairly limited in what sorts of conditional execution you can perform, it just does both (clone will fail if it’s already been cloned, and pull will always be executed, even immediately after a the initial clone). Obviously not ideal, but it works, and I couldn’t figure out a better way without writing actual code.

<git-clone-pull repository="git://github.com/280north/ojunit.git" dest="ojunit" />

There is plenty of room for improvement, but I suspect a proper Ant task written in Java is the right way to go.

git bisect run

This feature of git is too cool not to blog about: git bisect, and more specifically, git bisect run.

“git bisect” is a tool that facilitates a binary search of changes to your git repository to help find where a bug was introduced. You can walk through the process manually using “git bisect {good,bad,skip}“, or if you can write a script that automates checking for the bug, you can use “git bisect run scriptname” to have git do all the work for you.

The script should return 0 if the bug does not exist, and some other number (except 125) if the bug does exist.

In my case, Cappuccino’s “steam” build tool was failing, so I wrote a simple script that would test it by trying to run “steam” on Foundation:

#!/bin/sh

# install a known working copy of the build tools
pushd ../tmp/Tools
sudo sh install-tools
popd

# build whatever version of Cappuccino git bisect has checked out for us
rm -rf $STEAM_BUILD
ant release

# install the freshly built tools
pushd $STEAM_BUILD/Cappuccino/Tools
sudo sh install-tools
popd

# run steam on Foundation to see if the built tools work
rm -rf $STEAM_BUILD
pushd Foundation
steam
RETURN=$?
popd

# return the recorded return value
exit $RETURN

I provided “git bisect start” with a known bad commit and a known good commit, then ran “git bisect run”:

git bisect start c1e882ace1dd29aea98d9247db304fe5d5077df7 d6c0f8802a2fd3a07e14418de7744ae04ae4499e
git bisect run ../test.sh

Sure enough, a few minutes later “git bisect” reported exactly which commit caused the problem:

01177a7e0237b1bd026cf0c4ca923fced8536772 is first bad commit
commit 01177a7e0237b1bd026cf0c4ca923fced8536772
Author: name removed to protect the not-so-innocent

Date:   Tue Sep 30 17:29:56 2008 -0700

   Fix keys conflict in CPDictionary

   [#77 state:resolved]

:040000 040000 bf4ceafbf439aa54790fc57a2a78dec8283abadf b269f85f3f4ed4d08e4c8261ee409e9d88255b1d M    AppKit
:040000 040000 f9c1fdb3c02c7c899285c8cb8123b29e99a17e46 48cc5aefde707119fe956dd882dcd8f8182e7012 M    Foundation
:040000 040000 b780743d17ddb0ebda188703725e9dabf23fd458 c72750dabd99ca42d9144f3074c68c42b727d028 M    Objective-J
bisect run success