#!/bin/sh -e
# $Id: sisyphus_link_owner,v 1.3 2005/06/06 15:26:43 legion Exp $

. /etc/sisyphus/config
. /etc/sisyphus/functions

cd "$PREFIX"

export LC_ALL=C LANG=C LANGUAGE=C

action=
bts_user=
users=
packages=
interactive=
verbose=
tab_char="$(printf \\t)"

Usage() {
    [ "$1" = 0 ] || exec >&2
    cat << EOF
Usage: $PROG [options] <user> [<user> ...]

Options:
    -a, --add                 add users to list;
    -d, --del                 remove users from the lists;
    -r, --replace             replace all users;
    -p, --package=PKGNAME     change user list for PKGNAME;
    -b, --bts=NAME            set user as BTS user;
    -i, --interactive         read the package names from the stdin.
    -h, --help                show this message

EOF
    [ -n "$1" ] && exit "$1" || exit
}

quote() {
    printf %s "$*" | sed -e 's,[-.,*/\`\"$],\\&,g' || return 1
}

cleanup_args() {
    printf %s "$*"
}

add_owner() {
    local package pn name owners owners_old ownerslist
    [ -n "$users" ] || Fatal "users required"
    package="$1" && shift || Fatal "argument 'package' required"

    owners_old="$( printf %s "$package" | join -t"$tab_char" -o 2.2 - "$list_file")"
    [ -n "$owners_old" ] || { Info "Error: '$package' not found in the lists"; return 1; }

    owners_old=" $owners_old "
    owners=
    for name in $users; do
        [ "${owners_old#* $name }" = "$owners_old" ] || 
	    { Message "$name already in lists"; continue; }
        owners="$name $owners"
    done
    [ -n "$owners" ] || { Info "Error: nothing to add"; return 1; } 

    ownerslist="$(cleanup_args $owners_old $owners)"
    pn="$(quote "$package")" || Fatal "unable quote string: $package"
    subst "s,^$pn[[:space:]].*$,$package\t$ownerslist," "$list_file"
    [ -z "$verbose" ] || Message "User added (${list_file##*/}): $package = $ownerslist"
}

del_owner() {
    local package pn n new_owners o owners 
    [ -n "$users" ] || Fatal "users required"
    package="$1" && shift || Fatal "argument 'package' required"

    owners="$( printf %s "$package" | join -t"$tab_char" -o 2.2 - "$list_file")"
    [ -n "$owners" ] || { Info "Package found at the lists, but I cannot find the any owners"; return 1; }

    new_owners=
    for o in $owners; do
	[ "${users#* $o }" = "$users" ] || continue
	new_owners="$new_owners $o"
    done
    new_owners="$(cleanup_args $new_owners)"
    [ -n "$new_owners" ] || { Info "Unable remove all owners: $users"; return 1; }
    pn="$(quote "$package")" || Fatal "unable quote string: $package"
    subst "s,^$pn[[:space:]].*$,$package\t$new_owners," "$list_file"
    [ -z "$verbose" ] || Message "User removed (${list_file##*/}): $package = $new_owners"
}

bts_owner() {
    local package pn new_owners o owners
    package="$1" && shift || Fatal "argument 'package' required"

    owners="$( printf %s "$package" | join -t"$tab_char" -o 2.2 - "$list_file")"
    [ -n "$owners" ] || { Info "Error: '$package' not found in the lists"; return 1; }

    new_owners=
    for o in $owners; do
	[ "$o" != "$bts_name" ] || continue
	new_owners="$new_owners $o"
    done
    new_owners="$(cleanup_args $bts_name $new_owners)"
    if [ -n "$new_owners" ]; then
	pn="$(quote "$package")" || Fatal "unable quote string: $package"
	subst "s,^$pn[[:space:]].*$,$package\t$new_owners," "$list_file"
	[ -z "$verbose" ] || Message "BTS user changed (${list_file##*/}): $package = $new_owners"
    fi
}

replace_owner() {
    local package pn owners
    [ -n "$users" ] || Fatal "users required"
    package="$1" && shift || Fatal "argument 'package' required"

    owners="$(cleanup_args $users)"
    if [ -n "$owners" ];  then
	pn="$(quote "$package")" || Fatal "unable quote string: $package"
	subst "s,^$pn[[:space:]].*$,$package\t$owners," "$list_file"
	[ -z "$verbose" ] || Message "Users replaced (${list_file##*/}): $package = $owners"
    fi
}

show_info() {
    local pn owners
    package="$1" && shift || Fatal "argument 'package' required"

    pn="$(quote "$package")" || Fatal "unable quote string: $package"
    owners="$(grep --mmap -G "^$pn[[:space:]]" "$list_file" | cut -f2)"

    printf 'Package: %s\n' "$package"
    printf '\tcomponent: %s\n' "${list_file##*.}"
    printf '\tbts owner: %s\n' "${owners%% *}"
    printf '\t   owners: %s\n' "$owners"
    printf '\n'
}

pkg_exist() {
    local p="$1" && shift
    [ "$(cut -f1 files/list.src.* | grep -cxF "$p" ||:)" = 1 ] || 
	{ Info "Error: package not found: $p"; return 1; }
    return 0
}

TEMP=`getopt -n $PROG -o a,b:,d,h,i,p:,r,v -l add,del,help,interactive,package:,replace,show,verbose -- "$@"` || Usage
eval set -- "$TEMP"

while :; do
    case $1 in
	-a| --add) action=add
	    ;;
	-b| --bts) shift
	    [ -z "$1" ] || { bts_name="$1"; action=bts; }
	    ;;
	-d| --del) action=del
	    ;;
	-h| --help) Usage 0
	    ;;
        -i| --interactive) interactive=1
            ;;
        -p| --package) shift
            [ -z "$1" ] || packages="$1"
            ;;
	-r| --replace) action=replace
	    ;;
	--show) action=show
	    ;;
	-v| --verbose) verbose=-v
	    ;;
	--) shift; break
	    ;;
	*) Fatal "unrecognized option: $1"
	    ;;
    esac
    shift
done

# At least one argument, please.
if [ -z "$action" ]; then
    Info "action required"
    Usage
fi

users=" $@ "

if [ -n "$interactive" ]; then
    arg=
    while read arg; do
        packages="$packages $arg"
    done
fi
[ -n "$packages" ] || Usage 1

for f in files/list.src.*; do
    [ "$f" != "files/list.src.*" ] || 
	{ Fatal "lists not found: $(pwd)/files/"; exit 1; }
    sort -u -o "$f" "$f"
done

for p in $packages; do
    pkg_exist "$p" || continue

    list_file=
    for l in files/list.src.*; do
	[ "$l" != "files/list.src.*" ] || break 2
	if cut -f1 "$l" | grep -qsxF "$p"; then
	    list_file="$l"
	    break
	fi
    done
    [ -n "$list_file" ] || Fatal "Unexpected error"

    case $action in
	add)     add_owner     "$p" ;;
	del)     del_owner     "$p" ;;
	bts)     bts_owner     "$p" ;;
	replace) replace_owner "$p" ;;
	show)    show_info     "$p" ;;
    esac
done
