#!/bin/sh -e

export LC_ALL=C
verbose=
OPTIONS=
LONGOPTIONS=
REPOSITORY_BRANCH="sisyphus"
# alt system gits
git_default_url=git://git.altlinux.org
# alt system web shared tasks
web_default_tasks_url=http://git.altlinux.org
WEBERY_HOST=
WEB_TASKS_URL=
# alt personal gits
gitery_default_url=git://gitery.altlinux.org
gitery_default_host=
GITERY_HOST=
GIRAR_HOST=
DRY_RUN=
TASKID=
BEFORE_SUBTASK=
add_to_task=
build_task=
case $0 in *-task-add*) add_to_task=1;; *girar-build-*) build_task=1;; esac;
TASK_SHARE=
task_deps=
TASK_RUN_HURRY=
TASK_RUN_UNHURRY=
TASK_RUN_TEST_ONLY=
TASK_RUN_FAIL_LATE=
girar_message=
OUTGITS=OUT.gits
OUTSRPMS=OUT.SRPMS
OUTREBUILD=OUT.rebuild
rebuild_if_not_found=
SRPMOPTS=
GITOPTS=
MISCOPTS=

for config_file in /etc/girar-nmu/default ${XDG_CONFIG_HOME:-$HOME/.config}/girar-nmu/default; do
    ! [ -e "$config_file" ] || . "$config_file"
done
# --- autodetection in absence of config file ---
if [ -z "$gitery_default_host" ]; then
    if grep -E '^Host[[:space:]]+gitery[[:space:]]*$' ~/.ssh/config >/dev/null; then
	gitery_default_host=gitery
    elif grep -E '^Host[[:space:]]+git.alt[[:space:]]*$' ~/.ssh/config >/dev/null; then
	gitery_default_host=git.alt
    else
	gitery_default_host=gitery
    fi
fi
if [ -z "$GIRAR_HOST" ]; then
    if grep -E '^Host[[:space:]]+girar[[:space:]]*$' ~/.ssh/config >/dev/null; then
	GIRAR_HOST=girar
    elif grep -E '^Host[[:space:]]+gyle[[:space:]]*$' ~/.ssh/config >/dev/null; then
	GIRAR_HOST=gyle
    elif grep -E '^Host[[:space:]]+gyle.alt[[:space:]]*$' ~/.ssh/config >/dev/null; then
	GIRAR_HOST=gyle.alt
    elif grep -E '^Host[[:space:]]+sborochnitsa[[:space:]]*$' ~/.ssh/config >/dev/null; then
	GIRAR_HOST=sborochnitsa
    else
	GIRAR_HOST=girar
    fi
fi
# --- end autodetection ---------------------------

OPTIONS=a:AB:''SD:m:O''ZS:G:''cCE:kKm:M:p:rTt:''nNgrF
LONGOPTIONS=,add,add-to-task:,task:,before:,before-subtask:'',deps:,share,no-share,fail-early,fail-late,hurry,no-hurry,unhurry,no-test-only,test-only,message:,gm:,gyle-message:,girar-message:'',rpmsign:,sign:'',rebuild-not-found,GITS:,SRPMS:,REBUILD:,--out.gits:,--out.srpms:,--out.rebuild:'',auto-tag,no-auto-tag,try-tag,no-try-tag,commit,no-commit,commit-no-edit,no-edit,expect-git-branch:,gitery-path:,gitery-name:,kill-after,kill-before,cm:,tm:,commit-message:,tag-message:,prefix:,repo-prefix:,push-related-tags,no-push-related-tags,tag:
# not compatible with set -e
#getopt --test > /dev/null; #if [ "$?" -ne 4 ]; then
if getopt --test > /dev/null; then
    echo "Oops! `getopt --test` not failed. Bad getopt!." >&2
    exit 1
fi
__OPTS=hqVvb:H:P:R:
__LONGOPTS=dry-run,help,quiet,verbose,version,branch:,girar:,gyle:,gitery:,git.alt:,profile:,webery:,web_tasks_url:
PARSED=$(getopt --options=$__OPTS$OPTIONS --longoptions=$__LONGOPTS$LONGOPTIONS --name "$0" -- "$@")
if [ "$?" -ne 0 ]; then
    exit 2
fi
eval set -- "$PARSED"

while true; do
    case "$1" in
	-a|--add-to-task|--task) TASKID="$2"
	    add_to_task=1
	    readonly TASKID
            shift 2 ;;
	-A|--add)
	    TASKID=
	    add_to_task=1
	    readonly TASKID
	    shift ;;
	-B|--before|--before-subtask) BEFORE_SUBTASK="$2"
	    readonly BEFORE_SUBTASK
            shift 2 ;;
	-D|--deps) task_deps="$2"
            shift 2 ;;
	--no-share) TASK_SHARE=
            shift ;;
	-S|--share) TASK_SHARE=1
            shift ;;

	--gm|--girar-message|gyle-message) girar_message="$2"
	    girar_message=${girar_message// /_}
            shift 2 ;;
	-m|--message) girar_message="$2"
	    echo "WARINING: option -m (--message) is ambiguous. Assuming --girar-message">&2;
	    echo "Please, use --gm (--girar-message), --cm (--commit-message), --tm (--tag-message).">&2
	    girar_message=${girar_message// /_}
	    shift 2 ;;
	--test-only) TASK_RUN_TEST_ONLY=--test-only
            shift ;;
	-O|--no-test-only) TASK_RUN_TEST_ONLY=
            shift ;;
	--fail-late) TASK_RUN_FAIL_LATE=1
            shift ;;
	--fail-early) TASK_RUN_FAIL_LATE=
            shift ;;
	--no-hurry) TASK_RUN_HURRY=
            shift ;;
	--unhurry) TASK_RUN_UNHURRY=1
		TASK_RUN_HURRY=
            shift ;;
	--hurry) TASK_RUN_HURRY=1
		TASK_RUN_UNHURRY=
            shift ;;
	-S|--SRPMS|--out.srpms) OUTSRPMS="$2"
            shift 2 ;;
	-G|--GITS|--out.gits) OUTGITS="$2"
            shift 2 ;;
	--REBUILD|--out.rebuild) OUTREBUILD="$2"
            shift 2 ;;
	-Z|--rebuild-not-found) rebuild_if_not_found=1
            shift ;;
	-n|-g|-r|-F|-N)
	    SRPMOPTS="$SRPMOPTS $1"
            shift ;;
	--sign|--rpmsign)
	    SRPMOPTS="$SRPMOPTS $1=$2"
            shift 2 ;;
	-c|--commit|--no-commit|-C|--commit-no-edit|--no-edit|-k|--kill-before|-K|--kill-after|-r|--push-related-tags|--no-push-related-tags|-T|--auto-tag|--no-auto-tag|--try-tag|--no-try-tag)
	    GITOPTS="$GITOPTS $1"
            shift ;;
	-E|--expect-git-branch|--cm|--commit-message|-M|--tm|--tag-message|--gitery-path|--gitery-name|-p|--prefix|--repo-prefix|-t|--tag)
	    GITOPTS="$GITOPTS $1=$2"
            shift 2 ;;
	-P|--profile)
	    local profile_file="$2"
	    for config_file in /etc/girar-nmu/"$profile_file" ${XDG_CONFIG_HOME:-$HOME/.config}/girar-nmu/"$profile_file"; do
		! [ -e "$config_file" ] || . "$config_file"
	    done
            shift 2 ;;
        -q|--quiet)
            verbose=
            shift ;;
        -V|--version)
            echo "2.015.3"
	    exit 0
            shift ;;
        -v|--verbose)
            verbose=$(($verbose+1))
            shift ;;
	-h|--help)
	    pod2usage --exit=0 "$0";
	    exit 0 ;;
	-b|--branch)
	    REPOSITORY_BRANCH="$2"
	    readonly REPOSITORY_BRANCH
            shift 2 ;;
	-H|--gitery|--git.alt)
	    GITERY_HOST="$2"
	    readonly GITERY_HOST
            shift 2 ;;
	-R|--girar|--gyle)
	    GIRAR_HOST="$2"
	    readonly GIRAR_HOST
            shift 2 ;;
	-W|--webery)
	    WEBERY_HOST="$2"
	    readonly WEBERY_HOST
            shift 2 ;;
	--web-tasks-url)
	    WEB_TASKS_URL="$2"
	    readonly WEB_TASKS_URL
            shift 2 ;;
        --dry-run)
            DRY_RUN=echo
            shift ;;
        --)
            shift
            break
            ;;
        *)
	    echo "Internal error: Unexpected option: $1 $2" >&2
	    #pod2usage --exit=3 "$0"
            exit 3
            ;;
    esac
done

RETVAL=0
task_options_applied=
apply_task_properties()
{
    if [ -n "$TASK_SHARE" ] && [ $RETVAL -eq 0 ]; then
	$DRY_RUN ssh $GIRAR_HOST task share $TASKID enable || RETVAL=$?
    fi
    if [ -n "$task_deps" ] && [ $RETVAL -eq 0 ]; then
	for dep in `perl -e 'map {print $_, " " } split(",",$ARGV[0])' $task_deps`; do
	    $DRY_RUN ssh $GIRAR_HOST task deps $TASKID add $dep || RETVAL=$?
	done
    fi
    task_options_applied=1
    return $RETVAL
}

if [ -z "$TASKID" ]; then
   [ -z "$add_to_task" ] || MISCOPTS="$MISCOPTS -A"
else
    MISCOPTS="$MISCOPTS -a $TASKID"
fi
[ -z "$BEFORE_SUBTASK" ] || MISCOPTS="$MISCOPTS -B $BEFORE_SUBTASK"
[ -z "$GIRAR_HOST" ] || MISCOPTS="$MISCOPTS -R $GIRAR_HOST"
[ -z "$GITERY_HOST" ] || MISCOPTS="$MISCOPTS -H $GITERY_HOST"
[ -z "$REPOSITORY_BRANCH" ] || MISCOPTS="$MISCOPTS -b $REPOSITORY_BRANCH"
[ -z "$verbose" ] || [ "$verbose" -eq 0 ] || MISCOPTS="$MISCOPTS -v"

if [ "$OUTGITS" = OUT.gits ] && ! [ -d OUT.gits ] && [ -d OUT.GITS ]; then
    echo "WARNING: OUTGITS=OUT.gits, but OUT.GITS found. please, check"
fi

[ 0"$verbose" -ge 3 ] && set -x ||:

apply_task_properties

_GIRAR_CMD=girar-task-add-
for arg in "$@"; do
    name=`basename $arg`
    if [ -d "$OUTGITS/$name" ]; then
	$DRY_RUN ${_GIRAR_CMD}git $GITOPTS $MISCOPTS "$OUTGITS/$name"
    elif [ -d "$OUTGITS/$name.git" ]; then
	$DRY_RUN ${_GIRAR_CMD}git $GITOPTS $MISCOPTS "$OUTGITS/$name.git"
    elif [ -d "$OUTSRPMS/$name" ]; then
	if [ -e "$OUTSRPMS/$name/"*.src.rpm ]; then
	    $DRY_RUN ${_GIRAR_CMD}srpm $SRPMOPTS $MISCOPTS "$OUTSRPMS/$name/"*.src.rpm
	elif [ -e "$OUTSRPMS/$name/"*.tar ]; then
	    echo "ERROR: $OUTSRPMS/$name/ contains hasher tar but not src.rpm."
	    echo "To get src.rpm rebuild $OUTSRPMS/$name/"*.tar "in hasher."
	    exit 3
	else
	    echo "ERROR: strange: neither src.rpm nor tar is not found in $OUTSRPMS/$name/. maybe error during girar-nmu-prepare?."
	    exit 3
	fi
    elif [ -e "$OUTREBUILD/$name" ]; then
	$DRY_RUN ${_GIRAR_CMD}rebuild $MISCOPTS "$name"
    elif [ -n "$rebuild_if_not_found" ]; then
	$DRY_RUN ${_GIRAR_CMD}rebuild $MISCOPTS "$name"
    else
	echo "ERROR: prepared NMU package not found for $name."
	echo "run girar-nmu-prepare first or add -Z option to use rebuild in girar by default."
	exit 3;
    fi
done


: <<'__EOF__'

=head1	NAME

girar-nmu-task-add - add NMU generated packages to the given task in prescribed order.

=head1	SYNOPSIS

B<girar-nmu-task-add>
[B<-G|--GITS|--out.gits> I<path/to/OUT.gits dir>]
[B<-S|--SRPMS|--out.srpms> I<path/to/OUT.SRPMS dir>]
[B<--REBUILD|--out.rebuild> I<path/to/OUT.rebuild dir>]
[B<-Z>]
[B<-a|--add-to-task|--task> I<task ID>]
[B<-A|--add>]
[B<-B|--before|--before-subtask> I<before_subtask_id>]
[B<-D|--deps> I<comma separated list>]
[B<-S|--share>]
[B<--gm|--girar-message|--gyle-message> I<message>]
[B<-O|--no-test-only>]
[B<--test-only>]
[B<--unhurry>]
[B<--hurry>]
[B<--fail-early|--fail-late>]
[B<-n> | B<-g> | B<-r> | B<-F> | B<-N>]
[B<-c|--commit|-C|--commit-no-edit>]
[B<--no-edit>]
[B<--no-commit>]
[B<-E|--expect-git-branch> I<local git branch>]
[B<-k|--kill-before>]
[B<-K|--kill-after>]
[B<-p|--prefix> I<prefix>]
[B<-r|--push-related-tags>]
[B<--no-push-related-tags>]
[B<--gitery-name|--gitery-path> I<gitery name or path>]
[B<--cm|--commit-message> I<commit message>]
[B<--tm|--tag-message> I<tag message>]
[B<-t|--tag> I<tag>]
[B<-T|--auto-tag>]
[B<--no-auto-tag>]
[B<--try-tag>]
[B<--no-try-tag>]
[B<-H|--gitery> I<ssh gitery alias>]
[B<-R|--girar> I<ssh girar(gule) alias>]
[B<-W|--webery> I<tasks web site>]
[B<--web-tasks-url> I<tasks web site url>]
[B<-b|--branch> I<repository>]
[B<--dry-run>]
[B<-P|--profile> I<profile>]
[B<-h|--help>]
[B<-v|--verbose>]
[B<-q|--quiet>]

I<name ...>

=head1	DESCRIPTION

B<girar-nmu-task-add>
add NMU generated packages to the given task in prescribed order.
It takes a list of names as an argument.

=head1	OPTIONS

=over

=item	B<-G|--GITS|--out.gits> I<dir>

name of output directory with Git repositories.
Default is "OUT.gits".

=item	B<-S|--SRPMS|--out.srpms> I<dir>

name of output directory with src.rpms.
Default is "OUT.SRPMS".

=item	B<--REBUILD|--out.rebuild> I<dir>

name of output directory with names to rebuild.
Default is "OUT.rebuild".

=item	B<-Z|--rebuild-not-found>

Generate girar task add rebuild <name> commands if prepared packages
are not found.

=item  Add to task options.

=over

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

Specifies the girar task to add.
Also enables "task add" mode, see below.

=item	B<-A|--add>

Enables "task add" mode. In this mode, the argument(s) are added
to the current or the specified task. This disables "for each" mode
and stops "build" mode from creating a separate task.

=item	[B<-B|--before|--before-subtask> I<before_subtask_id>]

I<before_subtask_id> is used in the extended format of girar-task add command:
girar-task add [<task_id> [<before_subtask_id>]] srpm <filename>

=back


=item  Run task options.

=over

=item	B<-D|--deps> I<dep1,...,depN>

Comma separated list of task dependencies to add.

=item	B<-S|--share>

Create and run a shared task. Disabled by default.
Also, B<--no-share> disables it.


=item	B<--gm|--girar-message|--gyle-message> I<message>

Specifies a girar task message.

=item	B<--test-only>

Run task --test-only

=item	B<--commit|-O|--no-test-only>

Do not run task --test-only (default).

=item	B<--hurry>

Run task with --hurry (undocumented girar option)

=item	B<--no-hurry>

Remove --hurry from run command line,
B<--no-hurry> option does not set --unhurry.

=item	B<--unhurry>

Run task with --unhurry (undocumented girar option)

=item	B<--fail-early>

Stop building the task after the first error.

=item	B<--fail-late>

Do not stop building the task after the first error.

=back


=item  B<-F> | B<-g> | B<-n> | B<-N> | B<-r>

select a rpm sign command to sign a src.rpm.

=over

=item -g) rpm-sign-gpg-agent - use gpg agent to cache passphrase

=item -F) rpm-sign-forwarded-gpg-agent - use forwarded gpg agent to cache passphrase

=item -n) rpm-sign-no-passphrase - useful when key has no passphrase.

=item -r) rpm use plain rpm.

=item -N) do not sign rpm - useful when rpm is already signed

=back


=item  Git/Gear repository options.

=over

=item   B<-c|--commit>, B<--no-edit>

Commit. If modified files are found, call gear-commit.
If B<--no-edit> is present, call gear-commit with --no-edit option.
The modified files should be added to git index. If not, the script
will abort to prevent accidental modifications to be commited.
B<--no-commit> disables B<-c|--commit>.

=item   B<-C|--commit-no-edit>

Shortcut option. Same as B<-c|--commit> B<--no-edit> above.

=item	B<-E|--expect-git-branch> I<git branch name>

Name of the local git branch. Default is none.
If provided, the script will check that we are on the branch
and abort if we are not.

=item	B<-k|--kill-before>

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

=item	B<-K|--kill-after>

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

=item	B<--cm|--tag-message> I<tag message>

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

=item	B<--cm|--commit-message> I<commit message>

Specifies a message for git commit. Default is none (git will ask itself).

=item	B<--gitery-name|--gitery-path> I<name or path on gitery>

Specifies a repository name or path on gitery.
Sometimes the name on gitery differs from the name of local git repository.
It also can be used to run a task from a tag in a repository of another maintainer.
Together with -R <alias> it can be used to run task from an alias.
Default is to guess from current gear repository.
If a path a specified, then git init-db / clone / push is skipped.

=item	B<-p|--prefix> I<prefix>

Prefix to add before gitery repository name.
Useful to distinguish among automated and own repositories on gitery.
By default prefix is "00-tmp-".

=item	B<-r|--push-related-tags>

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.
Disabled by default. If enabled in config, is disabled by B<--no-push-related-tags>.

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

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

=item	B<-T|--auto-tag>

Call git tag %VERSION-%RELEASE.
If B<-t> or B<-T> is not specified then the last commit is expected to be a tag.
B<--no-auto-tag> disables B<-T|--auto-tag>.

=item	B<--try-tag>

If the auto tag already exists, B<--try-tag> adds I<.tryN> to the tag where N
is 2 or more such that I<tag.tryN> does not exist.
B<--no-try-tag> disables B<--try-tag>.

=back


=item	B<-b|--branch> I<repository branch>

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

=item	B<-R|--girar> I<girar(gyle) ssh alias>

By default, gyle.altlinux.org account should be configured as girar or gyle in ~/.ssh/config.
If you do not follow that convention, use -R <your girar ssh alias> option.

=item	B<-H|--gitery> I<gitery ssh alias>

Alternative gitery or ssh alias for gitery, for example, git.e2k.
If not specified, by default, gitery is used where ssh account is
required and git.altlinux.org is used where http:// is enough.

=item	B<-W|--webery> I<tasks web site>

Alternative site that hosts girar tasks.
If not specified, by default, git.altlinux.org is used.

=item	[B<--web-tasks-url> I<tasks web site url>]

The default URL for web task site is http://I<tasks web site>.
See --webery for details. B<--web-tasks-url> overrides this URL.

=item	B<--dry-run>

Echo state-changing commands instead of doing them. An extra safety.
Also a bit useful for debugging.

=item	B<-P|--profile> I<profile>

Name of the configuration profile. The profile is loaded as
/etc/girar-nmu/I<profile> and $HOME/.config/girar-nmu/I<profile>.
Note that default configuration is stored in
/etc/girar-nmu/default and $HOME/.config/girar-nmu/default.

=item	B<-V|--version>

Print version and exit.

=item	B<-v|--verbose>

Verbose. Prints extra information. Multiple -v accumulate.
-v -v -v set debug mode (set -x).

=item	B<-q|--quiet>

Quiet. Print no warnings.

=item	B<-h|--help>

Display this help and exit.


=back

=head1	AUTHOR

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

=head1	COPYING

Copyright (c) 2010-2023 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__
