#!/bin/sh -e
# $Id: sisyphus_link_owner,v 1.4 2005/06/21 16:33:56 legion Exp $

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

cd "$PREFIX"

export LC_ALL=C
export LANG=C

PROG="${0##*/}"
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 name owners owners_old ownerslist
    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)"
    subst "s,^$package[[:space:]].*$,$package\t$ownerslist," "$list_file"
    [ -z "$verbose" ] || Message "User added (${list_file##*/}): $package = $ownerslist"
}

del_owner() {
    local package n 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 "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; }
    subst "s,^$package[[:space:]].*$,$package\t$new_owners," "$list_file"
    [ -z "$verbose" ] || Message "User removed (${list_file##*/}): $package = $new_owners"
}

bts_owner() {
    local package 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 [ -z "$owners" ]; then
	subst "s,^$package[[:space:]].*$,$package\t$new_owners," "$list_file"
	[ -z "$verbose" ] || Message "BTS user changed (${list_file##*/}): $package = $new_owners"
    fi
}

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

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

pkg_exist() {
    local p="$1" && shift
    [ "$(cut -f1 files/list.src.* | grep -xF "$p" | wc -l)" = 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,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
	    ;;
	-v| --verbose) verbose=-v
	    ;;
	--) shift; break
	    ;;
	*) Fatal "unrecognized option: $1"
	    ;;
    esac
    shift
done

# At least one argument, please.
if ! [ "$#" -ge 1 ]; then
	Info "at least one argument is 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" ;;
    esac
done
