#!/bin/bash
# Simple shell script for creating Debian source releases from a git repository
#
# Copyright(C) 2007 - 2011, Ron <ron@debian.org>
# This script is distributed according to the terms of the GNU GPL.

set -e

# This has nothing to do with the release version of the package, it is for
# hook scripts to check what guarantees we might make for them. The number
# to the right of point will get incremented every time we add some new
# variable a hook might access, or add some new knob it might tweak.
# Existing interfaces should not have changed.  If we do screw up and need
# to change some current thing, the number to the left will get bumped.
# For what you get with each revision see gitpkg(1).
GITPKG_HOOK_API="0.1"


# Everything here assumes we started in the TLD of the repo.
# So if we aren't there already, let's go there now.
_TLD=$(git rev-parse --show-cdup)
[ -z "$_TLD" ] || cd "$_TLD"

# Remember where we are right now, in absolute terms, in case things that run
# out of the repo tree really need to do something in it. Like call git-config.
# Usually if you're out of the tree you should stay there though, so if you do
# use this for something, think carefully about what you are really doing.
REPO_DIR=$(pwd)


# You can ignore most of this first lot.  We temporarily waste a bunch of your
# startup cycles being far too friendly about migrating users to the new config.
# It could probably be packed into just a few lines of deep recursion, but we'll
# just drop it completely once people have migrated.
# I figure if it saves me two "how do I ..." email exchanges with users, it will
# have paid for every line of itself in time saved for everyone :)
# {{{

if [ -r /etc/gitpkg.conf ]; then
    . /etc/gitpkg.conf

    if [ -n "$BUILD_ROOTCMD" ]; then
	EXIT_MSG="${EXIT_MSG}# git config --system gitpkg.build-rootcmd '$BUILD_ROOTCMD'\n"
	_BUILD_ROOTCMD="$BUILD_ROOTCMD"
    fi
    if [ -n "$DEB_DIR" ]; then
	EXIT_MSG="${EXIT_MSG}# git config --system gitpkg.deb-dir '$DEB_DIR'\n"
	_DEB_DIR="$DEB_DIR"
    fi
    if [ -n "$HOOK_FILE" ]; then
	EXIT_MSG="${EXIT_MSG}  (You may want to hook only one of the next two)\n"
	EXIT_MSG="${EXIT_MSG}# git config --system gitpkg.deb-export-hook '$HOOK_FILE'\n"
	EXIT_MSG="${EXIT_MSG}# git config --system gitpkg.orig-export-hook '$HOOK_FILE'\n"
	_HOOK_FILE="$HOOK_FILE"
    fi
    if [ -n "$EXIT_MSG" ]; then
	OLD_ROOT_CONFIG="# rm /etc/gitpkg.conf\n"
    fi
fi

if [ -r ~/.gitpkg ]; then
    . ~/.gitpkg

    if [ "$_BUILD_ROOTCMD" != "$BUILD_ROOTCMD" ]; then
	EXIT_MSG="${EXIT_MSG}\$ git config --global gitpkg.build-rootcmd '$BUILD_ROOTCMD'\n"
	_BUILD_ROOTCMD="$BUILD_ROOTCMD"
	_OLD_CONFIG="~/.gitpkg"
    fi
    if [ "$_DEB_DIR" != "$DEB_DIR" ]; then
	EXIT_MSG="${EXIT_MSG}\$ git config --global gitpkg.deb-dir '$DEB_DIR'\n"
	_DEB_DIR="$DEB_DIR"
	_OLD_CONFIG="~/.gitpkg"
    fi
    if [ "$_HOOK_FILE" != "$HOOK_FILE" ]; then
	EXIT_MSG="${EXIT_MSG}  (You may want to hook only one of the next two)\n"
	EXIT_MSG="${EXIT_MSG}\$ git config --global gitpkg.deb-export-hook '$HOOK_FILE'\n"
	EXIT_MSG="${EXIT_MSG}\$ git config --global gitpkg.orig-export-hook '$HOOK_FILE'\n"
	_HOOK_FILE="$HOOK_FILE"
	_OLD_CONFIG="~/.gitpkg"
    fi
    OLD_CONFIG="$_OLD_CONFIG"
    _OLD_CONFIG=
fi

if [ -r .git/gitpkg.conf ]; then
    . .git/gitpkg.conf

    if [ "$_BUILD_ROOTCMD" != "$BUILD_ROOTCMD" ]; then
	EXIT_MSG="${EXIT_MSG}\$ git config gitpkg.build-rootcmd '$BUILD_ROOTCMD'\n"
	_OLD_CONFIG=".git/gitpkg.conf"
    fi
    if [ "$_DEB_DIR" != "$DEB_DIR" ]; then
	EXIT_MSG="${EXIT_MSG}\$ git config gitpkg.deb-dir '$DEB_DIR'\n"
	_OLD_CONFIG=".git/gitpkg.conf"
    fi
    if [ "$_HOOK_FILE" != "$HOOK_FILE" ]; then
	EXIT_MSG="${EXIT_MSG}  (You may want to hook only one of the next two)\n"
	EXIT_MSG="${EXIT_MSG}\$ git config gitpkg.deb-export-hook '$HOOK_FILE'\n"
	EXIT_MSG="${EXIT_MSG}\$ git config gitpkg.orig-export-hook '$HOOK_FILE'\n"
	_OLD_CONFIG=".git/gitpkg.conf"
    fi
    OLD_CONFIG="${OLD_CONFIG:+$OLD_CONFIG }$_OLD_CONFIG"
fi

if [ -n "$OLD_CONFIG" ]; then
    OLD_CONFIG="$ rm $OLD_CONFIG\n"
fi

EXIT_MSG="$EXIT_MSG$OLD_ROOT_CONFIG$OLD_CONFIG"


# sorry_dude OLD_VAR new-config new-value
# We could loop harder and probably resolve conflicts like this, but it really
# is better to just get rid of them asap.  This should only bite the hardcore
# tweakers, if there is some common pattern of innocent victims then we can see
# what to do about those if or as they come.
sorry_dude()
{ #{{{

    cat 1>&2 <<-EOF

	 Hmm.  You have $1 set in an old-style config file and also have
	 gitpkg.$2 set in git-config.  Mixing old and new config
	 options could go badly.  Your old-style config options can be migrated
	 into git-config now using the following:

	$(printf "$EXIT_MSG")

	 The current git-config reported value for gitpkg.$2
	 is: '$3'

	 When you have merged the desired options into git-config, simply run
	 gitpkg again and everything should be peachy.  Sorry for the hassle,
	 but it's best you check this gets untangled in the right way for you
	 before we continue in this repo.

	EOF

    exit 1

} #}}}

# git-config is where static user preferences should be now.
# In the case of a system with a partial transition between old and new config,
# we bark and stop until the user can have a look and set it right.  If it's
# purely using the old config then we just growl and point -- people who didn't
# fiddle with things deserve to have them still be working like they left them.
if _GCBR="$(git config --get gitpkg.build-rootcmd)"; then
    [ -z "$BUILD_ROOTCMD" ]	|| sorry_dude BUILD_ROOTCMD build-rootcmd "$_GCBR"
    [ -z "$DEB_DIR" ]		|| sorry_dude DEB_DIR build-rootcmd "$_GCBR"
    [ -z "$HOOK_FILE" ]		|| sorry_dude HOOK_FILE build-rootcmd "$_GCBR"
    BUILD_ROOTCMD="$_GCBR"
fi
if _GCDD="$(git config --get gitpkg.deb-dir)"; then
    [ -z "$DEB_DIR" ]		|| sorry_dude DEB_DIR deb-dir "$_GCDD"
    [ -n "$_GCBR" ]		\
    || [ -z "$BUILD_ROOTCMD" ]	|| sorry_dude BUILD_ROOTCMD deb-dir "$_GCDD"
    [ -z "$HOOK_FILE" ]		|| sorry_dude HOOK_FILE deb-dir "$_GCDD"
    DEB_DIR="$_GCDD"
fi
if DEB_EXPORT_HOOK="$(git config --get gitpkg.deb-export-hook)"; then
    [ -z "$HOOK_FILE" ]		|| sorry_dude HOOK_FILE deb-export-hook "$DEB_EXPORT_HOOK"
    [ -n "$_GCBR" ]		\
    || [ -z "$BUILD_ROOTCMD" ]	|| sorry_dude BUILD_ROOTCMD deb-export-hook "$DEB_EXPORT_HOOK"
    [ -n "$_GCDD" ]		\
    || [ -z "$DEB_DIR" ]	|| sorry_dude DEB_DIR deb-export-hook "$DEB_EXPORT_HOOK"
fi
if ORIG_EXPORT_HOOK="$(git config --get gitpkg.orig-export-hook)"; then
    [ -z "$HOOK_FILE" ]		|| sorry_dude HOOK_FILE orig-export-hook "$ORIG_EXPORT_HOOK"
    [ -n "$_GCBR" ]		\
    || [ -z "$BUILD_ROOTCMD" ]	|| sorry_dude BUILD_ROOTCMD orig-export-hook "$ORIG_EXPORT_HOOK"
    [ -n "$_GCDD" ]		\
    || [ -z "$DEB_DIR" ]	|| sorry_dude DEB_DIR orig-export-hook "$ORIG_EXPORT_HOOK"
fi

# Really this should check against the treeish being exported, but this
# first approximation should catch most affected people on the first pass.
if [ -e .gitpkg_hook ] && [ "$HOOK_FILE" != ".gitpkg_hook" ] &&
			  [ "$DEB_EXPORT_HOOK" != ".gitpkg_hook" ] &&
			  [ "$ORIG_EXPORT_HOOK" != ".gitpkg_hook" ]; then
    cat 1>&2 <<-EOF

	Uh Oh.  You're the one corner case I can't safely make life easy for.
	  You have a .gitpkg_hook in the local repo but you never explicitly
	  enabled it in your config.  To enable it now you will need to do
	  something like:

	\$ git config gitpkg.deb-export-hook '.gitpkg_hook'
	  and/or
	\$ git config gitpkg.orig-export-hook '.gitpkg_hook'

	  possibly in conjunction with a gitpkg.package-config-hook too.
	  Please see gitpkg(1) for details of the new hook and config options.

	  Since I can't tell this fine .gitpkg_hook of yours from a rogue
	  power you found drifting about the nastyweb, I'm not going to
	  give it a shell until you say that is OK with you, explicitly.
	  And since your things probably need it, I should stop right here
	  until you sort that out.  Sorry.
	$(if [ -n "$EXIT_MSG" ]; then
	    printf "\nTo migrate the rest of your existing config to use git-config(1)\n"
	    printf "the following commands may be helpful too:\n\n"
	    printf "$EXIT_MSG"
	    printf " "
	fi)
	EOF

    exit 1
fi

if [ -n "$HOOK_FILE" ]; then
    # This is just for compatibility with the the original trivial hook,
    # not a recommendation of a particularly good idea in most cases.
    DEB_EXPORT_HOOK="$HOOK_FILE"
    ORIG_EXPORT_HOOK="$HOOK_FILE"
fi

# if the user is still using old config, prepare a gentle warning about that
# to nag them with after all the action is over.  It is expected this will
# only be shown if subsequent operations succeed, in the event of some other
# failure we can save the nagging until they are in a better mood for it.
if [ -n "$EXIT_MSG" ]; then
    EXIT_MSG=$(cat <<-EOF

	 OH HAI! gitpkg now uses git-config(1) for configuration data,
	 and you have some options set in the old configuration files.
	 They still worked ok this time, but you can use the following
	 to migrate your existing config:

	$EXIT_MSG
	 If you do nothing, things will continue to work as they do at
	 present, and this message will continue to report the commands
	 needed to migrate over to the standard git-config interface.\n\n

	EOF
    )
    # I guess we _could_ add a "no really, just do it button here" ...
fi

# if all else fails, fit them up with some sensible shoes for the trek.
: "${BUILD_ROOTCMD="fakeroot"}"
: "${DEB_DIR="../deb-packages"}"

# }}}



# Ok you can open your eyes again now, this is where the script really starts.
# All new config options should go below here, leave all that stuff above alone
# until we can drop support for the old config files and just remove it again.

# So...  first we see what the local user left for us in git-config
# Roughly in the order that they are used below:
PACKAGE_CONFIG_HOOK="$(git config --get gitpkg.package-config-hook)" || true
PRE_EXPORT_HOOK="$(git config --get gitpkg.pre-export-hook)" || true
#DEB_EXPORT_HOOK="$(git config --get gitpkg.deb-export-hook)" || true
PREBUILD_TARGET="$(git config --get gitpkg.prebuild-target)" || true
CREATE_FAKE_ORIG="$(git config --get --bool gitpkg.create-fake-orig)" || true
FORCE_OVERWRITE_ORIG="$(git config --get --bool gitpkg.force-overwrite-orig)" || true
#ORIG_EXPORT_HOOK="$(git config --get gitpkg.orig-export-hook)" || true
ORIG_COMPRESSOR="$(git config --get gitpkg.orig-compressor)" || ORIG_COMPRESSOR=gzip
ORIG_COMPRESS_LEVEL="$(git config --get gitpkg.orig-compress-level)" || true
DEB_COMPRESSOR="$(git config --get gitpkg.deb-compressor)" || true
DEB_COMPRESS_LEVEL="$(git config --get gitpkg.deb-compress-level)" || true

while read opt; do DPKG_SOURCE_OPTS+=("$opt")
		done < <(git config --get-all gitpkg.dpkg-source)

EXIT_HOOK="$(git config --get gitpkg.exit-hook)" || true

# XXX should the (an?) exit hook be run on failure too?
#     if we do that, we might also need to tell it how far we got
#     and why we croaked.  Wait until someone needs that maybe.


usage()
{ #{{{
    # We may not actually know the real final type yet here.
    case $ORIG_COMPRESSOR in
	gzip)	OCEXT=".gz"  ;;
	bzip2)	OCEXT=".bz2" ;;
	xz)	OCEXT=".xz"  ;;
	*)	OCEXT=".wtf" ;;
    esac

    cat 1>&2 <<EOF

gitpkg branch [origbranch]

  If gitpkg is run in a git repo with a single branch specified, then it will
  do a git-archive export of that branch to the $DEB_DIR directory.  If
  the package is Debian native it will simply create a source package from it.
  $(case "$CREATE_FAKE_ORIG" in
    (true)
	echo "If the package has a Debian version, then an orig.tar$OCEXT will be created"
	echo "  containing everything except the debian/ dir, if it does not already exist."
	;;
    (false)
	echo "If the package has a Debian version, then an orig.tar$OCEXT must already exist"
	echo "  for it (or it is expected to have been retrieved by one of the hooks)."
	;;
    (*)
	echo "If the package has a Debian version, and an orig.tar$OCEXT does not already"
	echo "  exist for it, then you will be prompted to either go find one, or to let"
	echo "  gitpkg fake one up for you."
	;;
  esac)

  If gitpkg is invoked with two branches specified, then the first branch will
  be checked out as the unpacked complete source, while the second branch will
  be checked out as the orig.tar$OCEXT.  This allows all local changes to the
  source to be recorded in the resulting diff.gz if a pristine upstream branch
  exists in the repository.  $(

  case "$FORCE_OVERWRITE_ORIG" in
    (true)
	echo "If the orig.tar$OCEXT already exists it will be"
	echo "  overwritten by the source exported from the specified branch."
	;;
    (false)
	echo "If the orig.tar$OCEXT already exists gitpkg will"
	echo "  cry foul."
	;;
    (*)
	echo "If the orig.tar$OCEXT already exists gitpkg will"
	echo "  ask you whether to overwrite it or not."
	;;
  esac)

  'branch' should always have a debian/ dir and may be any tree-ish object that
  is accepted by git-archive(1).  The 'origbranch', if supplied, should usually
  not have a debian/ dir.

EOF

    exit $1
} #}}}

[ $# -gt 0 ] && [ $# -lt 3 ] || usage 1


# As a general rule it is not in gitpkg's idiom to accept command line options.
# The main reason for this being the importance of ensuring an export is easily
# and reliably reproducible - and if reproducing the build depends on recalling
# the precise options that gitpkg was called with beyond simply the version you
# wish to export, then you've pretty much guaranteed failure at that before you
# even begin.  That said though, it's also evident that some people have formed
# the habit of blindly expecting every application should support the following
# two options -- and we shouldn't fail horribly if they blindly attempt passing
# them to gitpkg either.  Since they have nothing to do with actually producing
# a package, we'll take exception, just this once, to handle them here and exit.
[ "$1" != "--help" ]	|| exec man gitpkg
[ "$1" != "--version" ] || exec dpkg-query -W -f='${Package} ${Version}\n' gitpkg



# Export these explicitly to the hook scripts, but few should actually need them.
GITPKG_TREEISH=$1
GITPKG_ORIG_TREEISH=$2


# Next we see what the package itself wants to force for this release
if [ -n "$PACKAGE_CONFIG_HOOK" ]; then
    mkdir -p "$DEB_DIR"

    git archive --format=tar --prefix="gitpkg-${1}/" $1 $PACKAGE_CONFIG_HOOK |
		tar -C "$DEB_DIR" -xf -

    # since it's valid for this hook to alter DEB_DIR we need to cache it
    # somewhere that it won't accidently get run over, so we can clean up.
    dont_alter_this_copy_of_deb_dir_mkay="$DEB_DIR"

    # and since bash 3.2.48 (at least) apparently wants to crap out immediately
    # if sourcing a file fails under set -e, disable that so we can catch and
    # clean up before bailing out.
    set +e
    . "$DEB_DIR/gitpkg-${1}/$PACKAGE_CONFIG_HOOK" || omg=1

    # Don't complain at them, or waste time testing if we should.  just fix it.
    cd "$REPO_DIR"
    rm -rf "$dont_alter_this_copy_of_deb_dir_mkay/gitpkg-$1"
    [ -z "$omg" ] || exit 1
    set -e
fi

# Give the BOFH one last chance to look things over and dickheadproof them.
if ADMIN_CONFIG_HOOK="$(git config --get gitpkg.admin-config-hook)"; then
    . "$ADMIN_CONFIG_HOOK"
    cd "$REPO_DIR"
    # even admins can screw up sometimes.  catch an easy one for them too.
fi

# Do a little post-last chance option crunching.
case $ORIG_COMPRESSOR in
    gzip)   OCEXT=".gz"  ;;
    bzip2)  OCEXT=".bz2" ;;
    xz)	    OCEXT=".xz"  ;;
    *)
	echo "gitpkg: Invalid orig-compressor '$ORIG_COMPRESSOR' requested."
	echo "        Are you from the ... future?"
	# If so, please add support for new formats here.
	# lzma is explicitly not supported since .xz already killed it.
	exit 1
	;;
esac
case $DEB_COMPRESSOR in
    gzip|bzip2|xz)
	DPKG_SOURCE_OPTS+=("-Z$DEB_COMPRESSOR")
	;;
    '')	;;
    *)
	echo "gitpkg: Invalid deb-compressor '$DEB_COMPRESSOR' requested."
	echo "        Are you from the ... future?"	# If so, see above.
	exit 1
	;;
esac

[ -z "$DEB_COMPRESS_LEVEL" ] || DPKG_SOURCE_OPTS+=("-z$DEB_COMPRESS_LEVEL")

ORIG_COMPRESS_LEVEL="${ORIG_COMPRESS_LEVEL:+ -$ORIG_COMPRESS_LEVEL}"


get_deb_version()
{ #{{{
    DEB_SOURCE="$(cd "$1" && dpkg-parsechangelog | awk '/Source:/ {print $2}')"
    DEB_VERSION="$(cd "$1" && dpkg-parsechangelog | sed -rne 's/^Version: ([^:]+:)?//p')"
    UPSTREAM_VERSION="${DEB_VERSION%-*}"
    DEB_PACKAGE="${DEB_SOURCE}-${UPSTREAM_VERSION}"
    DEB_DSC="${DEB_SOURCE}_${DEB_VERSION}.dsc"

    case $DEB_VERSION in
	*-*)
	    DEB_ORIG="${DEB_SOURCE}_${UPSTREAM_VERSION}.orig.tar$OCEXT"
	    ;;
    esac
} #}}}


# Fetch (just) the changelog, and loop out through another hook with the package
# name and version information available too.  It's too late to change anything
# now, but not too late to check that it's all ok before getting started.
if [ -n "$PRE_EXPORT_HOOK" ]; then
    mkdir -p "$DEB_DIR"

    git archive --format=tar --prefix="gitpkg-${1}/" $1 debian/changelog |
		tar -C "$DEB_DIR" -xf -

    get_deb_version "$DEB_DIR/gitpkg-$1"
    rm -rf "$DEB_DIR/gitpkg-$1"

    if [ -z "$DEB_SOURCE" ] || [ -z "$DEB_VERSION" ];  then
	echo "ERROR: Failed to parse debian/changelog"
	exit 1
    fi

    if ! ( . "$PRE_EXPORT_HOOK" ); then
	echo "ERROR: pre-export-hook '$PRE_EXPORT_HOOK' failed"
	exit 1
    fi
fi


export_debian_tree()
{ #{{{
    echo "git archive exporting $1"
    git archive --format=tar --prefix="gitpkg-${1}/" $1 |
    (
	mkdir -p "$DEB_DIR"
	cd "$DEB_DIR"
	tar xf -
    ) || exit 1

    # We don't do this from the subshell so that it's still visible to EXIT_HOOK
    [ -n "$PRE_EXPORT_HOOK" ] || get_deb_version "$DEB_DIR/gitpkg-$1"

    if [ -z "$DEB_SOURCE" ] || [ -z "$DEB_VERSION" ];  then
	rm -rf "$DEB_DIR/gitpkg-$1"
	echo "ERROR: Failed to parse debian/changelog"
	exit 1
    fi

    echo "preparing $DEB_DIR/$DEB_SOURCE/$DEB_PACKAGE"
    (
	cd "$DEB_DIR"

	[ -e "$DEB_SOURCE/$DEB_PACKAGE" ] && rm -rf "$DEB_SOURCE/$DEB_PACKAGE"

	mkdir -p "$DEB_SOURCE"
	mv "gitpkg-$1" "$DEB_SOURCE/$DEB_PACKAGE"

	cd "$DEB_SOURCE/$DEB_PACKAGE"

	if [ -n "$DEB_EXPORT_HOOK" ] && ! ( . "$DEB_EXPORT_HOOK" ); then
	    echo "ERROR: deb-export-hook '$DEB_EXPORT_HOOK' failed"
	    echo "       in: $DEB_DIR/$DEB_SOURCE/$DEB_PACKAGE"
	    exit 1
	fi

	if [ -n "$PREBUILD_TARGET" ]; then
	    echo "$BUILD_ROOTCMD debian/rules $PREBUILD_TARGET"
	    $BUILD_ROOTCMD debian/rules $PREBUILD_TARGET
	fi

    ) || exit 1
} #}}}

format3_lameness()
{ #{{{
    if [ "$ORIG_COMPRESSOR" != "gzip" ] ||
       [ "${DEB_COMPRESSOR:-gzip}" != "gzip" ] ||
       grep -q "^3\.0" "$DEB_PACKAGE/debian/source/format" 2>/dev/null;
    then
	echo "dpkg-source" "${DPKG_SOURCE_OPTS[@]}" "-b $DEB_PACKAGE"
	dpkg-source "${DPKG_SOURCE_OPTS[@]}" -b "$DEB_PACKAGE" || exit 1
    else
	return 1
    fi
} #}}}

build_with_existing_orig_tarball()
{ #{{{
    if ! format3_lameness; then
	echo "dpkg-source" "${DPKG_SOURCE_OPTS[@]}" "-b -sp $DEB_PACKAGE"
	dpkg-source "${DPKG_SOURCE_OPTS[@]}" -b -sp "$DEB_PACKAGE"
    fi
} #}}}

build_native_package()
{ #{{{
    if ! format3_lameness; then
	echo "dpkg-source" "${DPKG_SOURCE_OPTS[@]}" "-b -sn $DEB_PACKAGE"
	dpkg-source "${DPKG_SOURCE_OPTS[@]}" -b -sn "$DEB_PACKAGE"
    fi
} #}}}

build_with_exported_orig()
{ #{{{
    # We build this ourselves and use -ss rather than -sR because dpkg-source
    # handles making tarballs badly anyhow and will leave the .orig suffix
    # in the path inside them.

    echo "tar cf - $DEB_PACKAGE(.orig) | $ORIG_COMPRESSOR$ORIG_COMPRESS_LEVEL > $DEB_ORIG"
    tar --transform "s,^$DEB_PACKAGE.orig,$DEB_PACKAGE," \
	-cf - "$DEB_PACKAGE.orig" | $ORIG_COMPRESSOR $ORIG_COMPRESS_LEVEL > "$DEB_ORIG"

    if ! format3_lameness; then
	echo "dpkg-source" "${DPKG_SOURCE_OPTS[@]}" "-b -ss $DEB_PACKAGE"
	dpkg-source "${DPKG_SOURCE_OPTS[@]}" -b -ss "$DEB_PACKAGE"
    fi
    rm -rf "$DEB_PACKAGE.orig"
} #}}}

build_with_faked_orig()
{ #{{{
    if [ "$CREATE_FAKE_ORIG" != "true" ]; then
	cat <<-EOF

	The package you are exporting has a Debian version, but there is no
	 $DEB_ORIG
	already present and you did not provide a treeish to export one from.
	EOF

	if [ "$CREATE_FAKE_ORIG" = "false" ]; then
	    rm -rf "$DEB_PACKAGE"
	    exit 1
	fi

	cat <<-EOF
	We can fake one up from everything but the debian/ directory if you
	would like, but this may not be what you had originally intended.

	You have exported '$GITPKG_TREEISH'.
	EOF
	printf "Fake a $DEB_ORIG from that (y/N)? "
	read -e yesno
	case "$yesno" in
	    Y* | y*)
		cat <<-EOF

		Ok then.  If you plan to make a habit of this you may wish to set:
		 git config gitpkg.create-fake-orig 'true'
		To avoid being asked about it again each time.

		EOF
		;;
	    *)
		cat <<-EOF
		Yeah, good call.

		To avoid being asked about this again you can set
		 git config gitpkg.create-fake-orig 'false'
		then in future this will simply print an error and fail.
		EOF

		rm -rf "$DEB_PACKAGE"
		exit 1
		;;
	esac
    fi

    [ -e "$DEB_PACKAGE.orig" ] && rm -rf "$DEB_PACKAGE.orig"

    cp -al "$DEB_PACKAGE" "$DEB_PACKAGE.orig"
    rm -rf "$DEB_PACKAGE.orig/debian"

    build_with_exported_orig
} #}}}

do_exit()
{ #{{{
    if [ -n "$EXIT_HOOK" ] && ! ( cd "$DEB_DIR/$DEB_SOURCE" && . "$EXIT_HOOK" );
    then
	echo "ERROR: gitpkg.exit-hook '$EXIT_HOOK' failed"
	exit 1
    fi

    printf "$EXIT_MSG"

    exit $1
} #}}}


# Ok, if we're still here, let's reap what they've sown.
if [ $# -eq 1 ]; then

    export_debian_tree $1

    (
	cd "$DEB_DIR/$DEB_SOURCE"

	case $DEB_VERSION in
	    *-*)
		if [ -e "$DEB_ORIG" ]; then
		    build_with_existing_orig_tarball
		else
		    build_with_faked_orig
		fi
		;;

	    *)
		build_native_package
		;;
	esac

    ) || exit 1
fi

if [ $# -eq 2 ]; then

    export_debian_tree $1

    # Check that get_deb_version really did find a debian version number
    if [ -z "$DEB_ORIG" ]; then
	cat <<-EOF

	 You have requested an orig tarball to be exported from '$GITPKG_ORIG_TREEISH',
	 but the debian source from '$GITPKG_TREEISH' does not have a debian version
	 in the changelog (version '$DEB_VERSION' was found).

	 If this is really a native package, you probably want to call gitpkg
	 with just a single treeish.  If it is not, now might be a good time
	 to fix the changelog entry to include a debian version part.

	 Stopping here until that is sorted out.
	EOF

	exit 1
    fi

    # Check for an existing orig.tar.gz and what to do if we have one ...
    if [ -e "$DEB_DIR/$DEB_SOURCE/$DEB_ORIG" ]
    then
	if [ "$FORCE_OVERWRITE_ORIG" = "true" ]; then
	    echo "Overwriting existing $DEB_DIR/$DEB_SOURCE/$DEB_ORIG"
	else
	    cat <<-EOF

		You have requested '$GITPKG_ORIG_TREEISH' be exported,
		but $DEB_ORIG is already present.
		EOF

	    if [ "$FORCE_OVERWRITE_ORIG" = "false" ]; then
		rm -rf "$DEB_DIR/$DEB_SOURCE/$DEB_PACKAGE"
		exit 1
	    fi

	    printf "Overwrite the existing orig with this repo export (y/N)? "
	    read -e yesno
	    case "$yesno" in
		Y* | y*)
		    cat <<-EOF

			Ok then.  If you plan to make a habit of this you may wish to set:
			 git config gitpkg.force-overwrite-orig 'true'
			To avoid being asked about it again each time.

			EOF
		    ;;
		*)
		    printf "Using the existing $DEB_ORIG, that's probably smart.\n\n"
		    (
			cd "$DEB_DIR/$DEB_SOURCE"
			build_with_existing_orig_tarball

		    ) || exit 1

		    # All done!
		    do_exit 0
		    ;;
	    esac
	fi
    fi

    # else check out the requested pristine upstream branch now too
    if [ -n "$ORIG_EXPORT_HOOK" ]; then

	[ -e "$DEB_DIR/$DEB_SOURCE/$DEB_PACKAGE.orig" ] &&
	    rm -rf "$DEB_DIR/$DEB_SOURCE/$DEB_PACKAGE.orig"

	echo "git archive exporting $2 to $DEB_PACKAGE.orig/"
	git archive --format=tar --prefix="$DEB_PACKAGE.orig/" $2 |
	(
	    cd "$DEB_DIR/$DEB_SOURCE"
	    tar xf -
	    (
		cd "$DEB_PACKAGE.orig"

		if ! ( . "$ORIG_EXPORT_HOOK" ); then
		    echo "ERROR: orig-export-hook '$ORIG_EXPORT_HOOK' failed"
		    echo "       in: $DEB_DIR/$DEB_SOURCE/$DEB_PACKAGE.orig"
		    exit 1
		fi

	    ) || exit 1

	    build_with_exported_orig

	) || exit 1
    else
	printf "git archive --prefix=$DEB_PACKAGE/ $2"
	printf " | $ORIG_COMPRESSOR$ORIG_COMPRESS_LEVEL > $DEB_ORIG\n"
	git archive --format=tar --prefix="$DEB_PACKAGE/" $2 |
		$ORIG_COMPRESSOR $ORIG_COMPRESS_LEVEL        \
		> "$DEB_DIR/$DEB_SOURCE/$DEB_ORIG"
	(
	    cd "$DEB_DIR/$DEB_SOURCE"
	    build_with_existing_orig_tarball

	) || exit 1
    fi
fi

do_exit 0

# vi:sts=4:sw=4:noet:foldmethod=marker
