jw-pkg/scripts/git-srv-admin.sh
Jan Lindemann e589caf73f 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 <jan@janware.com>
2025-11-17 08:52:12 +01:00

246 lines
4.3 KiB
Bash

#!/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