#!/bin/sh
# $Id: git-pbuilder,v 1.22 2011-05-23 06:03:13 eagle Exp $
#
# git-pbuilder -- Wrapper around pbuilder for git-buildpackage
#
# Written by Russ Allbery <rra@stanford.edu>
# Based on the example in the git-buildpackage documentation
# Copyright 2008, 2009, 2010, 2011
#     The Board of Trustees of the Leland Stanford Junior University
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of Stanford University not be used in
# advertising or publicity pertaining to distribution of the software without
# specific, written prior permission.  Stanford University makes no
# representations about the suitability of this software for any purpose.  It
# is provided "as is" without express or implied warranty.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

set -e

# Set BUILDER, DIST, and ARCH based on the name we were invoked as.  This
# allows people to create symlinks like git-pbuilder-lenny and
# git-qemubuilder-lenny-amd64 pointing to git-pbuilder and auto-detecting the
# builder, distribution, and architecture from that.
if [ -z "$BUILDER" ] && [ -z "$DIST" ] ; then
    BUILDER=${0#*git-}
    DIST=${BUILDER#*-}
    BUILDER=${BUILDER%%-*}
    case $BUILDER in
        pbuilder|cowbuilder) BUILDER=cowbuilder ;;
        /*)                  BUILDER=cowbuilder ;;
    esac
    case $BUILDER in
        *builder) ;;
        *)        BUILDER=cowbuilder ;;
    esac
    case $DIST in
        *builder)
            DIST=
            ;;
        *-*)
            ARCH=${DIST#*-}
            DIST=${DIST%%-*}
            ;;
    esac
else
    BUILDER=cowbuilder
fi

# Make sure we have the necessary tools
if [ ! -x /usr/sbin/"$BUILDER" ]; then
    echo "$BUILDER not found; you need to install the $BUILDER package" >&2
    exit 1
fi

# Default options come from the environment.
OPTIONS="$GIT_PBUILDER_OPTIONS"

# How we handle options depends on what type of builder we're using.
case $BUILDER in
    cowbuilder)
        # The root directory where different cowbuilder --basepath directories
        # are found.  git-pbuilder expects them to be named base-<dist>.cow.
        : ${COWBUILDER_BASE:=/var/cache/pbuilder}

        # If DIST is set, use base-$DIST.cow.  If DIST is not set, the sid
        # chroot may be either base.cow or base-sid.cow.  Try both.  If ARCH
        # is set, use base-$DIST-$ARCH.cow.
        if [ -z "$DIST" ] ; then
            DIST=sid
        fi
        if [ -n "$ARCH" ] ; then
            BASE="$COWBUILDER_BASE/base-$DIST-$ARCH.cow"
            OPTIONS="$OPTIONS --architecture $ARCH"
        elif [ "$DIST" = 'sid' ] ; then
            if [ -d "$COWBUILDER_BASE/base-sid.cow" ] ; then
                BASE="$COWBUILDER_BASE/base-sid.cow"
            else
                BASE="$COWBUILDER_BASE/base.cow"
            fi
        else
            BASE="$COWBUILDER_BASE/base-$DIST.cow"
        fi
        OPTIONS="$OPTIONS --basepath $BASE"

        # Make sure the base directory exists.
        if [ ! -d "$BASE" ] && [ "$1" != "create" ]; then
            echo "Base directory $BASE does not exist" >&2
            exit 1
        fi

        # Set --debian-etch-workaround if DIST is etch.  Assume that
        # everything else is new enough that it will be fine.
        if [ "$DIST" = 'etch' ] || [ "$DIST" = 'ebo' ] ; then
            OPTIONS="$OPTIONS --debian-etch-workaround"
        fi
        ;;

    qemubuilder)
        # There always has to be an architecture for qemubuilder, and it
        # doesn't make much sense to default to the current architecture.
        # There's probably no good default, but this one at least makes some
        # sense.
        if [ -z "$DIST" ] ; then
            DIST=sid
        fi
        if [ -z "$ARCH" ]; then
            ARCH=armel
        fi

        # There has to be a configuration file matching our distribution and
        # architecture.
        QEMUBUILDER_CONFIG="/var/cache/pbuilder/qemubuilder-$ARCH-$DIST.conf"
        if [ ! -r "$QEMUBUILDER_CONFIG" ]; then
            echo "Cannot read configuration file $QEMUBUILDER_CONFIG" >&2
            exit 1
        fi
        OPTIONS="$OPTIONS --config $QEMUBUILDER_CONFIG"
        ;;

    *)
        echo "Unknown builder $BUILDER" >&2
        exit 1
        ;;
esac

# If the first argument to the script is update, create, or login, run the
# builder with the corresponding option under sudo rather than proceeding.
case $1 in
update|create|login)
    action="$1"
    shift
    sudo "$BUILDER" --"$action" --dist "$DIST" $OPTIONS "$@"
    exit $?
    ;;
*)
    if [ -z "$GBP_BUILD_DIR" ]; then
        echo "Warning: git-pbuilder should be run via git-buildpackage" >&2
    fi
    ;;
esac

# Print out some information about what we're doing.
if [ -n "$ARCH" ] ; then
    echo "Building with $BUILDER for distribution $DIST, architecture $ARCH"
else
    echo "Building with $BUILDER for distribution $DIST"
fi

# Source package format 1.0 doesn't automatically exclude Git files, so we
# want to add the appropriate flags to do that.  But source package format 3.0
# does exclude by default and has many other ways of controlling those
# exclusions that we don't want to tromp on.  So we don't want to give any -i
# or -I flags unless we're using source format 1.0.
if [ ! -f debian/source/format ] || grep -qs '^1.0' debian/source/format ; then
    echo 'Source format 1.0 detected, adding exclude flags'
    DEBBUILDOPTS="-i'(?:^|/)\\.git(attributes)?(?:\$|/.*\$)' -I.git $*"
else
    DEBBUILDOPTS="$*"
fi

# Now we can finally run pdebuild.  The quoting here is tricky, but this
# seems to pass everything through properly.
pdebuild --buildresult .. --pbuilder "$BUILDER" \
    --debbuildopts "$DEBBUILDOPTS" -- $OPTIONS
status="$?"
if [ -n "`ls ../*_source.changes`" ] ; then
    rm ../*_source.changes
fi
exit "$status"

# Documentation.  Use a hack to hide this from the shell.  Because of the
# above exit line, this should never be executed.
DOCS=<<__END_OF_DOCS__

=head1 NAME

git-pbuilder - Wrapper around cowbuilder/qemubuilder for git-buildpackage

=head1 SYNOPSIS

DIST=I<distribution> ARCH=I<architecture> [BUILDER=qemubuilder] \
    B<git-pbuilder> I<debbuild-options>

DIST=I<distribution> ARCH=I<architecture> [BUILDER=qemubuilder] \
    B<git-pbuilder> (update | create | login) I<cowbuilder-options>

=head1 DESCRIPTION

B<git-pbuilder> is a wrapper around B<pdebuild> intended for use by
B<git-buildpackage>.  It configures B<pdebuild> to use B<cowbuilder> by
default, passes appropriate options to B<debbuild>, and sets the base path
for B<cowbuilder> based on the environment variable DIST and, if set, the
environment variable ARCH.  B<qemubuilder> can be selected instead by
setting the environment variable BUILDER to C<qemubuilder>.

By default, B<git-pbuilder> assumes the target distribution is C<sid>, the
same architecture as the B<cowbuilder> default, and uses
F</var/cache/pbuilder/base-sid.cow> if it exists.  If it doesn't,
F</var/cache/pbuilder/base.cow> is tried.  If DIST is set, its value is
the target distribution and F</var/cache/pbuilder/base-I<dist>.cow> is
used instead.  If DIST is C<etch> or C<ebo>, B<--debian-etch-workaround>
is also passed to B<cowbuilder>.  If ARCH is set, its value is the target
architecture and F</var/cache/pbuilder/base-I<dist>-I<arch>.cow> is used,
with I<dist> being set to C<sid> if DIST was not set.

If B<qemubuilder> is used as the builder, no base directory is used.
Instead, B<qemubuilder> is invoked with the B<--config> option pointing to
the file F</var/cache/pbuilder/qemubuilder-I<arch>-I<dist>.conf>

If neither BUILDER nor DIST are set in the environment and B<git-pbuilder>
is invoked via a name that starts with C<git-*->, the part between the
hyphens is taken to be the name of the builder to use (with C<pbuilder>
mapped to B<cowbuilder>.).  The part after the last hyphen is taken to be
the distribution (if it contains no additional hyphen) or the distribution
followed by the architecture (if it contains a hyphen).  One can therefore
create symlinks like C<git-pbuilder-lenny> pointing to B<git-pbuilder> and
use that name when wanting to use a distribution of C<lenny>, or
C<git-qemubuilder-sid-armel> to use B<qemubuilder> to build for the
C<armel> architecture and the C<sid> distribution.

Any arguments are passed as-is to B<dpkg-buildpackage> via the
B<--debbuildopts> option to B<pdebuild>.  To pass arguments to the builder
instead, put them in the environment variable GIT_PBUILDER_OPTIONS.

Normally, one does not run this script directly.  Instead, it's used as
the builder script for B<git-buildpackage>.  To configure
B<git-buildpackage> to use it, add a stanza like:

    [DEFAULT]
    builder = /path/to/git-pbuilder

in your F<gbp.conf> file (which can be F<.gbp.conf> in your home directory
or at the top level of the repository, or F<gbp.conf> in the F<.git>
directory).  DIST and ARCH are read as an environment variable so that you
can set it before running B<git-buildpackage> without having to worry
about passing parameters through B<git-buildpackage>.

Alternately, B<git-pbuilder> may be called with an argument of C<update>,
C<create>, or C<login>.  In this case, it calls B<cowbuilder> (or the
configured builder as described above) using B<sudo> and passes the
corresponding command to the builder, using the same logic as above to
determine the base directory and distribution.  Any additional arguments
to B<git-pbuilder> are passed along to the builder.

=head1 ENVIRONMENT

=over 4

=item ARCH

Sets the target architecture.  For a B<cowbuilder> builder, this sets both
the base path and is passed as the B<--architecture> option.  For a
B<qemubuilder>, this controls the path to the configuration file.

=item BUILDER

Sets the builder to use.  The only supported settings are C<cowbuilder>
(the default) and C<qemubuilder>.

=item COWBUILDER_BASE

Set this environment variable to change the default location for the
cowbuilder base directories (F</var/cache/pbuilder>).

=item DIST

Sets the target distribution.  This is used primarily to determine the
base path for B<cowbuilder> or the configuration file path for
B<qemubuilder>, but it's also used to determine whether to pass
B<--debian-etch-workaround> to B<cowbuilder>.

=item GIT_PBUILDER_OPTIONS

Add additional options for the builder.  These options are passed as-is to
B<cowbuilder> or B<qemubuilder> via B<pdebuild>.  The contents of this
variable will undergo shell expansion, so any arguments containing shell
metacharacters or whitespace need to be quoted in the value of the
environment variable.

=back

=head1 FILES

=over 4

=item /var/cache/pbuilder/base-sid.cow

=item /var/cache/pbuilder/base.cow

The default C<cowbuilder --basepath> directories, searched for in that
order, if neither DIST nor ARCH is set.

=item /var/cache/pbuilder/base-sid-$ARCH.cow

The C<cowbuilder --basepath> directory used if ARCH is set and DIST is not
set.

=item /var/cache/pbuilder/base-$DIST.cow

The C<cowbuilder --basepath> directory used if DIST is set and ARCH is
not.

=item /var/cache/pbuilder/base-$DIST-$ARCH.cow

The C<cowbuilder --basepath> directory used if DIST and ARCH are both set.

=item /var/cache/pbuilder/qemubuilder-$ARCH-$DIST.conf

The C<qemubuilder --config> file used.  $ARCH defaults to C<armel> and
$DIST defaults to C<sid> if not set.

=back

=head1 SEE ALSO

cowbuilder(8), dpkg-buildpackage(1), git-buildpackage(1), pdebuild(1),
qemubuilder(8), sudo(8)

The latest version of this script is available from
L<http://www.eyrie.org/~eagle/software/scripts/>.

=head1 AUTHOR

Russ Allbery <rra@stanford.edu>

=cut

__END_OF_DOCS__
