#!/bin/sh myname=`basename $0` usage() { cat << EOT | sed 's/^ |//' | | $myname [global options] cmd [cmd-arguments] ... | | global options are: | | -F flavour : flavour is one of: priv, jw, contrib | | commands are: | | create-repo name | update-descriptions | list-repos | create-repo-dir | list-maintainers | EOT [ "$1" ] && exit $1 } log() { echo $@ logger -t $myname "$@" } err() { echo $@ >&2 logger -t $myname "error: $@" } fatal() { err "fatal: $@" exit 1 } md() { local dir=$1 local mode=$2 local owner=$3 local group=$4 [ -d $dir ] || { log "creating $dir as $owner.$group with mode $mode" /usr/bin/install -m $mode -o $owner -g $group -d $dir || { fatal "failed to create directory $dir" } } } check_user_is_self() { [ "$id" != "$user" ] && fatal "User $id is not allowed to do this to user $user's repositories." } # ----------------- commands md_p() { [ -d "$1" ] && return md_p `dirname "$1"` $2 $3 $4 md $@ } cmd_cmd_create_repo_dir() { [ "$UID" != 0 ] && fatal "tried to create directory \"$dir\" as `whoami`, needs to be done as root" local gid=`id -g $id` md_p /srv/git 750 root git md_p /srv/git/$id 750 root git md_p `dirname $dir` 750 $id $gid md_p $dir 02750 $id $gid } cmd_create_repo() { [ -e $dir ] && { err "$dir already exists" test $no_error_if_exists -eq 0 exit $? } /usr/bin/sudo `readlink -f $0` create-project-dir $dir || fatal "failed to create [$dir] as root" cd $dir || fatal "failed to change to $dir" git init --bare --shared=0640 || fatal "git init failed" } read_project_metadata() { local pd="$1" local field="$2" git -C $pd show HEAD:make/project.conf | sed -n "/^\[$field\]/,/^\[/ p" | grep -v '\[' | cat -s | sed '${/^$/d;}' } cmd_update_descriptions() { [ -d $pdir ] || return 0 cd $pdir || return 1 local projs="$*" [ "$projs" = all ] && projs=`cmd_list_repos` local proj for proj in $projs; do umask 0022 [ -d "$proj" ] || fatal "Failed to find project $pdir/$proj" local tmp=`mktemp /tmp/$myname-XXXXXXX` local descr=$proj/description read_project_metadata $proj summary > $tmp [ -s "$tmp" ] || read_project_metadata $proj description > $tmp if [ -s "$tmp" ] && ! diff -q "$tmp" "$descr" >/dev/null 2>&1; then chown --reference=$proj $tmp chmod 640 $tmp echo "====== Changing description of $proj" echo '-- old --' cat $descr echo '-- new --' cat $tmp mv $tmp $descr fi rm -f $tmp done } cmd_list_repos() { [ -d $pdir ] || return 0 cd $pdir || return 1 ls */HEAD | sed 's%/HEAD%%' 2>/dev/null return $? } cmd_list_maintainers() { local dev_chief=jan local master_dir=/srv/git/$dev_chief/proj local d pdir p val for d in $master_dir; do for pdir in `find $d -maxdepth 1 -mindepth 1 -type d`; do [ -x $pdir ] || continue [ -r $pdir ] || continue #echo "$d -> $pdir" p=`basename $pdir` val=`git -C $pdir show HEAD:make/project.conf 2>/dev/null | sed -n '/^\[global\]/,/^\[/ p' | sed ' /^[[:space:]]*jw-maintainer/ !d; s/.*= *// '` [ "$val" ] || val="unknown" [ "$val" ] || continue printf "%-30s %s\n" $p $val done done } # ----------------- here we go no_error_if_exists=0 id=`whoami` #user=$id flavour=priv OPTIND=1 while getopts jhu:F: flag; do case $flag in h) usage 0;; u) user=$OPTARG;; j) # legacy support flavour=jw;; F) flavour=$OPTARG;; p) no_error_if_exist=1;; *) usage 1;; esac done shift $(($OPTIND - 1)) if [ "$user" ]; then id=$user else if [ "$SUDO_UID" ]; then id=`/usr/bin/getent passwd $SUDO_UID | cut -d: -f1` [ "$id" ] || fatal "failed to find uid $SUDO_UID in user database" fi user=$id fi git_home=/srv/git/$id pdir=$git_home/priv case $flavour in jw|proj) pdir=$git_home/proj;; priv) pdir=$git_home/priv;; test) pdir=$git_home/test;; contrib) pdir=$git_home/contrib;; *) fatal "unknown repository flavour \"$flavour\"" esac cmd=$1 shift p=$1 dir=$pdir/$p case $cmd in create-personal-project|create-repo) check_user_is_self cmd_create_repo "$@" ;; update-descriptions|update-descr) cmd_update_descriptions "$@" ;; list-personal-projects|list-repos) cmd_list_repos "$@" ;; create-project-dir|create-repo-dir) dir=$1 # this is all a horrible variable and usage mess check_user_is_self cmd_cmd_create_repo_dir "$@" ;; list-maintainers|maintainers) cmd_list_maintainers ;; *) usage 1 ;; esac