From e589caf73f0514df2334aa77e61a8458a09caa6d Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Mon, 17 Nov 2025 08:52:12 +0100 Subject: [PATCH] Re-add git-srv-admin.sh: Needed for enumerating repos via SSH Since currently remote SSH git repos are identified via git-srv-admin.sh, we still need it to run make over a bare toplevel Makefile. Signed-off-by: Jan Lindemann --- scripts/git-srv-admin.sh | 246 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 scripts/git-srv-admin.sh diff --git a/scripts/git-srv-admin.sh b/scripts/git-srv-admin.sh new file mode 100644 index 00000000..2b4221c8 --- /dev/null +++ b/scripts/git-srv-admin.sh @@ -0,0 +1,246 @@ +#!/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 +