mirror of
ssh://git.janware.com/janware/proj/jw-pkg
synced 2026-04-24 09:13:37 +02:00
This commit allows pgit.sh to target not only multiple projects below a projects-directory, but also one single project. If invoked from the toplevel directory of a project, it uses that as the only project it should deal with. This is meant to facilitate running the same VCS abstraction logic for one project as for many projects. The project or projects to deal with should probably be specified on the command line, but changing the auto-detection mechanism buys us what we want for now with low hassle. Signed-off-by: Jan Lindemann <jan@janware.com>
278 lines
6.4 KiB
Bash
278 lines
6.4 KiB
Bash
#!/bin/sh
|
|
|
|
# ----------------- Helper functions
|
|
|
|
log()
|
|
{
|
|
echo $@
|
|
}
|
|
|
|
err()
|
|
{
|
|
log $@
|
|
}
|
|
|
|
fatal()
|
|
{
|
|
err $@
|
|
exit 1
|
|
}
|
|
|
|
marker()
|
|
{
|
|
log "# ------------- [$cur/$n_projects] $@"
|
|
}
|
|
|
|
fat_marker()
|
|
{
|
|
log "# ==================================================== [$cur/$n_projects] $@"
|
|
}
|
|
|
|
#
|
|
# Guess and set the following global variables:
|
|
#
|
|
# - projects_dir: The directory all projects are contained in
|
|
# - project_dirs: A space separated list of all directories containing a project
|
|
# - n_projects: the number of projects
|
|
#
|
|
set_global_variables()
|
|
{
|
|
[ "$projects_dir" ] || {
|
|
projects_dir=`pwd`
|
|
# If we're in a toplevel directory, suppose projects_dir == project_dirs,
|
|
# i.e. we only want to target this Git repo
|
|
if [ ! -d .git ]; then
|
|
while [ ! -r Makefile ] || ! grep -q some-random-string-to-id-this-makefile Makefile; do
|
|
[ "$projects_dir" = / ] && fatal "Failed to find projects directory"
|
|
projects_dir=`dirname $projects_dir`
|
|
done
|
|
fi
|
|
}
|
|
|
|
[ "$project_dirs" ] || {
|
|
project_dirs=`(cd $projects_dir; ls -d */.git 2>/dev/null | sed 's%/.git%%')`
|
|
}
|
|
n_projects=`echo $project_dirs | wc -w`
|
|
}
|
|
|
|
run_git()
|
|
{
|
|
marker git "$@"
|
|
git "$@"
|
|
}
|
|
|
|
# ----------------- Commands
|
|
|
|
cmd_run()
|
|
(
|
|
local d
|
|
local cmd=$1
|
|
shift
|
|
|
|
set_global_variables
|
|
cd $projects_dir
|
|
|
|
if [ "$PGIT_KEEP_GOING" != y ]; then set -e; fi
|
|
for d in $project_dirs; do
|
|
cur=`expr $cur + 1`
|
|
run_git -C $d $cmd "$@"
|
|
done
|
|
)
|
|
|
|
cmd_commit()
|
|
(
|
|
local d do_cvs
|
|
|
|
if [ "$1" = --cvs ]; then
|
|
do_cvs=true
|
|
shift
|
|
fi
|
|
|
|
set_global_variables
|
|
cd $projects_dir
|
|
|
|
if [ "$PGIT_KEEP_GOING" != y ]; then set -e; fi
|
|
for d in $project_dirs; do
|
|
cur=`expr $cur + 1`
|
|
if run_git -C $d diff-index --quiet HEAD --; then
|
|
log "Nothing to commit"
|
|
continue
|
|
fi
|
|
run_git -C $d commit "$@"
|
|
done
|
|
)
|
|
|
|
cmd_clone()
|
|
(
|
|
run_clone() {
|
|
local url="$1"
|
|
local p="$2"
|
|
run_git $GIT_GLOBAL_OPTS clone "$url" "$p"
|
|
if [[ "$GIT_GLOBAL_OPTS" =~ proactiveAuth ]]; then
|
|
run_git -C $p config set http.proactiveAuth basic
|
|
fi
|
|
}
|
|
|
|
local remote_base="$global_remote_base"
|
|
local remote_subpath="$global_remote_subpath"
|
|
local whoami="$(id -un)"
|
|
set_global_variables
|
|
cd $projects_dir
|
|
local projects="$PGIT_CLONE_PROJECTS"
|
|
local ignore="$PGIT_IGNORE"
|
|
local thisdir="${0%/*}"
|
|
local jw_projects="/usr/bin/python3 $thisdir/jw-pkg.py"
|
|
local create_remote_user_repos=false
|
|
local long_opts="create-remote-user-repos"
|
|
local refspec=()
|
|
long_opts="$long_opts,refspec:"
|
|
local login="$whoami"
|
|
[ "$remote_user" ] && login="$remote_user"
|
|
|
|
local opts
|
|
opts=$(getopt -o C --long "$long_opts" -n clone -- "$@") || fatal "Failed to parse options $@"
|
|
eval set -- "$opts"
|
|
while [ "$1" != -- ]; do
|
|
case "$1" in
|
|
-C | --create-remote-user-repos)
|
|
create_remote_user_repos=true
|
|
;;
|
|
--refspec)
|
|
refspec=(${2//:/ })
|
|
shift
|
|
;;
|
|
*)
|
|
fatal "Unknown option $1"
|
|
;;
|
|
|
|
esac
|
|
shift
|
|
done
|
|
|
|
local fromuser="${refspec[0]}"
|
|
local fromref="${refspec[1]}"
|
|
local toref="${refspec[2]}"
|
|
[ "$fromuser" ] || fromuser=$whoami
|
|
[ "$fromref" ] || fromref=master
|
|
local git_srv_admin="$SSH $login@git.janware.com /opt/jw-pkg/bin/git-srv-admin.sh"
|
|
|
|
if [ -z "$projects" ]; then
|
|
projects=`$jw_projects projects list-repos --from-user $fromuser $remote_base`
|
|
[ "$?" != 0 ] && exit 1
|
|
fi
|
|
|
|
if [ "$login" ]; then
|
|
[ "${remote_base/@/}" = "${remote_base}" ] || fatal "Specified both --login $login and user in URL $remote_base"
|
|
remote_base=$(echo $remote_base | sed "s|://|://$login@|")
|
|
fi
|
|
|
|
n_projects=`echo $projects | wc -w`
|
|
if [ "$PGIT_KEEP_GOING" != y ]; then set -e; fi
|
|
local project_dir
|
|
for project_dir in $projects; do
|
|
local project_name=$(readlink -f $project_dir | xargs basename)
|
|
if echo $ignore | grep -q "\b$project_name\b"; then
|
|
continue
|
|
fi
|
|
cur=`expr $cur + 1`
|
|
local pullurl=$remote_base/$fromuser$remote_subpath/$project_name
|
|
local pushurl=$remote_base/$login$remote_subpath/$project_name
|
|
local curref=""
|
|
fat_marker "Fetching project $project_name from user $fromuser"
|
|
if [ "$fromuser" = "$login" ]; then
|
|
if [ -d $project_dir ]; then
|
|
run_git -C $project_dir pull --recurse-submodules=on-demand
|
|
run_git -C $project_dir submodule foreach --recursive 'git fetch --tags -f origin'
|
|
else
|
|
run_clone $remote_base/$fromuser$remote_subpath/$project_name $project_dir
|
|
fi
|
|
else
|
|
local remotename="jw-$fromuser"
|
|
if [ -d $project_dir ]; then
|
|
run_git -C $project_dir remote | grep -q "^$remotename$" || {
|
|
run_git -C $project_dir remote add $remotename $pullurl
|
|
run_git -C $project_dir remote set-url --push $remotename no_push
|
|
}
|
|
run_git -C $project_dir fetch --prune --recurse-submodules=on-demand $remotename $fromref
|
|
run_git -C $project_dir submodule foreach --recursive 'git fetch --tags -f origin'
|
|
if [ "$toref" ]; then
|
|
run_git -C $project_dir rebase --autostash $remotename/$fromref $toref
|
|
run_git -C $project_dir merge --ff-only $remotename/$fromref $toref
|
|
fi
|
|
else
|
|
# set -x
|
|
run_clone $remote_base/$fromuser$remote_subpath/$project_name $project_dir
|
|
run_git -C $project_dir remote rename origin $remotename || fatal "Failed to rename remote in $project_dir"
|
|
run_git -C $project_dir remote set-url --push $remotename no_push
|
|
if [ $create_remote_user_repos = true ]; then
|
|
$git_srv_admin -u $login -j create-personal-project $project_name
|
|
run_git -C $project_dir remote add origin $pushurl
|
|
run_git -C $project_dir push --recurse-submodules=on-demand origin master
|
|
$git_srv_admin -u $login -j update-descriptions $project_name
|
|
run_git -C $project_dir branch --set-upstream-to origin/master master
|
|
fi
|
|
fi
|
|
fi
|
|
run_git -C $project_dir submodule update --init --recursive || fatal "git submodule update failed in $project_dir"
|
|
done
|
|
)
|
|
|
|
cmd_diff()
|
|
(
|
|
local d
|
|
set_global_variables
|
|
cd $projects_dir
|
|
for d in $project_dirs; do
|
|
cur=`expr $cur + 1`
|
|
# marker $d
|
|
run_git -C $d diff --src-prefix=$d/ --dst-prefix=$d/ "$@"
|
|
done
|
|
)
|
|
|
|
echo "running $0 $@ GIT_SSH=$GIT_SSH" >&2
|
|
|
|
cur=0
|
|
SSH=ssh
|
|
[ "$GIT_SSH" ] && SSH=$GIT_SSH
|
|
global_remote_base="ssh://git.janware.com/srv/git"
|
|
|
|
while [ "${1:0:1}" = - ]; do
|
|
case "$1" in
|
|
'--remote-base')
|
|
global_remote_base="$2"
|
|
shift
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Only janware.com ssh git supports subdirectories below users
|
|
if [[ "$global_remote_base" =~ git.janware.com ]]; then
|
|
global_remote_subpath="/proj"
|
|
else
|
|
global_remote_subpath=""
|
|
fi
|
|
|
|
cmd=$1
|
|
shift
|
|
|
|
while [ "${1:0:1}" = - ]; do
|
|
case $1 in
|
|
'--login')
|
|
remote_user="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case $cmd in
|
|
clone|diff|commit)
|
|
cmd_${cmd//-/_} "$@"
|
|
;;
|
|
*)
|
|
cmd_run $cmd "$@"
|
|
;;
|
|
esac
|