#!/bin/sh -f
# note: bash-dependent due to checkbashisms

export LC_ALL=C
repobranch=sisyphus
gitbranch=
GITALTHOST=git.alt
message=
tag=
use_default_tag=
kill_remote_repo_before=
kill_remote_repo_after=
add_to_task=
autocommit=
push_related_tags=
REPOPREFIX=
TASKID=

while getopts a:Ab:cd:hH:kKm:n:p:rt:T opt; do
	case "$opt" in
		b) repobranch="${OPTARG:?}"
			readonly repobranch ;;
		c) autocommit=1 ;;
		d) gitbranch="${OPTARG:?}" 
			readonly gitbranch ;;
		p) REPOPREFIX="${OPTARG:?}"
			readonly REPOPREFIX ;;
		H) GITALTHOST="${OPTARG:?}"
			readonly GITALTHOST ;;
		a) TASKID="${OPTARG:?}"
		        add_to_task=1 
			readonly TASKID ;;
		A) TASKID=
		        add_to_task=1 
			readonly TASKID ;;
		m) message="${OPTARG:?}" ;;
		n) name="${OPTARG:?}" ;;
		r) push_related_tags=1 ;;
		t) tag="${OPTARG:?}" ;;
		T) use_default_tag=1 ;;
		k) kill_remote_repo_before=1 
			readonly kill_remote_repo_before ;;
		K) kill_remote_repo_after=1 
			readonly kill_remote_repo_after ;;
		:) missing="${OPTARG:?}"
		case "$missing" in
		    a) add_to_task=1 ;;
		    t) use_default_tag=1 ;;
		    *) pod2usage --exit=0 "$0"; exit 0 ;;
		esac
		;;
		h) pod2usage --exit=0 "$0"; exit 0 ;;
		*) pod2usage --exit=2 "$0"; exit 2 ;;
	esac
done
shift "$((OPTIND-1))"

if [ -n "$1" ] && [ -e "$1/.git" ] && ([ -e "$1/.gear" ] || [ -e "$1/.gear-rules" ]); then
    echo "entering $1 ..."
    cd "$1"
    [ -z "$name" ] && name=`basename "$1"`
fi

if ! [ -e .git ] || ! ([ -e .gear ] || [ -e .gear-rules ]) ; then 
    echo "this program should be run inside git/gear repository"; exit 2;
fi

modified_files=`git status --porcelain --untracked-files=no`
[ -n "$modified_files" ] && [ -n "$autocommit" ] && gear-commit

modified_files=`git status --porcelain --untracked-files=no`
if [ -n "$modified_files" ]; then
	echo "WARNING: found modified files:"
	git status --porcelain --untracked-files=no
	echo "please, commit or discard them first."
	exit 3;
fi

if [ -n "$gitbranch" ]; then
    CURRENT_BRANCH="$(git branch | awk '/^\*/{print $2}')"
    #[ "$CURRENT_BRANCH" = "(no_branch)" ] && CURRENT_BRANCH=
    if [ "$CURRENT_BRANCH" != "$gitbranch" ]; then
	echo "WARNING: local branch is $CURRENT_BRANCH but should be $gitbranch"
	exit 9;
    fi
fi

gear_pkg_version=`gear --command sh -- -c 'printf %s "$gear_pkg_version"'`
gear_pkg_release=`gear --command sh -- -c 'printf %s "$gear_pkg_release"'`
gear_pkg_name=`gear --command sh -- -c 'printf %s "$gear_pkg_name"'`

[ -z "$name" ] && name="$gear_pkg_name"
name=${name%%.git}

if [ -z "$name" ]; then 
    pod2usage --exit=2 "$0"; exit 2;
fi

# TODO: check if the tag already exists and create $tag.tryN
[ -n "$use_default_tag" ] && tag="${gear_pkg_version}-$gear_pkg_release"

if [ -z "$tag" ]; then
    tag=`git describe --exact-match --abbrev=0`;
    if [ $? -gt 0 ]; then
	echo "tag not found! to create a tag, add one of the options"
	echo "	-T (creates tag %version-%release), or"
	echo "	-t <tag> option, or place tag manually."
	exit 5;
    fi
else
    message="${message:-$tag}"
    git tag -s -m "$message" $tag || exit 3
fi
uploadname=`echo $name | sed -e 's,[^-A-Za-z0-9_.],,g'`
reponame="${REPOPREFIX}${uploadname}"
if [ -n "$kill_remote_repo_before" ];then 
    echo ssh $GITALTHOST git-rm-db "${reponame}"
    ssh $GITALTHOST git-rm-db "${reponame}"
fi

commit=`git ls-remote -h git://git.altlinux.org/gears/${name:0:1}/${name}.git refs/heads/$repobranch | awk '{print $1}'`
if [ -n "$commit" ]; then
    ssh $GITALTHOST clone "/gears/${name:0:1}/${name}.git" "${reponame}"
else
    # $name is not a git-built package"
    ssh $GITALTHOST git-init-db "${reponame}"
fi

PUSHLIST=$tag
if [ -n "$push_related_tags" ]; then
    # Restore gears tags and branches
    gear-restore-tags -f
    # append related tags to pushlist
    PUSHLIST="$PUSHLIST "`gear-restore-tags -q -l --no-tags --no-type --no-sha1 | sed -r -n 's/^[[:space:]]*([^[:space:]]+)[[:space:]]*$/\1:\1/p'`
    PUSHLIST="$PUSHLIST "`gear-restore-tags -q -l --no-branches --no-type --no-sha1`
fi
git push --force ${GITALTHOST}:packages/${reponame}.git ${gitbranch:+$gitbranch:$gitbranch} $PUSHLIST
RETVAL=0
if [ -z "$add_to_task" ]; then
    ssh $GITALTHOST build ${repobranch:+-b $repobranch} ${reponame}.git $tag || RETVAL=$?
else
    ssh $GITALTHOST task add $TASKID repo "$reponame.git" $tag || RETVAL=$?
fi
if [ -n "$kill_remote_repo_after" ];then 
    echo ssh $GITALTHOST git-rm-db "${reponame}"
    ssh $GITALTHOST git-rm-db "${reponame}"
fi
#popd

[ $RETVAL -gt 0 ] && exit $RETVAL

: <<'__EOF__'

=head1	NAME

girar-nmu-helper-git-push-build - NMU helper for git/gear repository.

=head1	SYNOPSIS

B<girar-nmu-helper-git-push-build>
[B<-h>] 
[B<-a> I<task ID>] 
[B<-A>]
[B<-b> I<repository branch>]
[B<-c>]
[B<-d> I<local branch>]
[B<-H> I<ssh git.alt alias>]
[B<-k>] 
[B<-K>] 
[B<-p> I<prefix>]
[B<-r>] 
[B<-m> I<tag message>] 
[B<-t> I<tag>] 
[B<-T>] 
[</path/to/gear-repository.git>]


=head1	DESCRIPTION

B<girar-nmu-helper-git-push-build> NMU helper for git/gear repository.
It (optionally) create a tag in current git repository, 
remotely clones git.alt/gears/ repository, pushes the tag to git.alt,
and either adds package build with the tag to a specified task with -a option,
or current task, with -A option, or builds a package from the tag. 
It also can remove the remote repository (with -K option).

=head1	OPTIONS

=over

=item	B<-a> [I<task ID>]

git.alt task [I<task ID>] add.

=item	B<-A> 

git.alt task add.

=item	B<-b> I<repository name>

Name of the repository branch. Values: sisyphus|5.1|p5|..
Default is sisyphus.

=item   B<-c>

Commit. If modified files are found, call gear-commit.

=item	B<-d> I<local branch name>

Name of the local branch to build from. Default is master.

=item	B<-H> [I<git.alt ssh alias>]

By default, git.altlinux.org account should be configured as git.alt in ~/.ssh/config.
If you does not follow that convention, use -H <git.alt your ssh alias> option.

=item	B<-h>

Display this help and exit.

=item	B<-k>

Try to kill remote git repository before upload (useful for robotic and nmu builds).

=item	B<-K>

Kill remote git repository after upload (useful for robotic and nmu builds).

=item	B<-m> [I<tag message>]

Specifies a message for git tag [I<tag>]. Default is tag name.

=item	B<-p> I<prefix>

Prefix to add before git repository name.
Use something like 00-tmp- to distinguish among automated and own repositories.

=item	B<-r>

Push related tags as well. Push all tags that are ancestors of the current build tag.
Useful when intermediate tags, like v@version@, are created.

=item	B<-t> [I<tag>]

Call git tag [I<tag>]. Default is %NAME-%VERSION.
If B<-t> or B<-T> is not specified then last commit is expected to be tag.

=item	B<-T> 

Call git tag %NAME-%VERSION.
If B<-t> or B<-T> is not specified then last commit is expected to be tag.

=back

=head1	AUTHOR

Written by Igor Vlasenko <viy@altlinux.org>.

=head1	COPYING

Copyright (c) 2010 Igor Vlasenko, ALT Linux Team.

This is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

=cut

__EOF__
