office-gobmx/g
Christian Lohmaier caf0071d60 fix refreshing git-hooks when using git-bash
real symlinks require admin-rights or developer mode, and the other
fallback mechanisms won't work for the version of git that comes with
git-bash. Either spawning the process failes or worse it silently fails
and basically ignores the hook.
MSYS uses regular file copy when using "ln -s" which means to make sure
the current version of a hook is used the hooks need to replaced
everytime or the file contents need to be compared. When using hardlinks
instead it is enough to check whether the source and target share the
same inode.

Change-Id: Ib2e325048779828313afc7fc9d120661d55fc3a5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177498
Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
Tested-by: Jenkins
2024-11-29 13:25:59 +01:00

418 lines
10 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Wrapper for git to handle more subdirs at the same time
#
if [ -n "$g_debug" ] ; then
set -x
fi
SUBMODULES_ALL="dictionaries helpcontent2 translations"
pushd $(dirname $0) > /dev/null
if [ -f ${BUILDDIR}/config_host.mk ] ; then
# we are in the SRCDIR
SRC_ROOT=$(< ${BUILDDIR}/config_host.mk grep -a SRC_ROOT | sed -e "s/.*=//")
else
SRC_ROOT=$(pwd)
fi
popd > /dev/null
COREDIR="$SRC_ROOT"
usage()
{
git
echo
echo "Usage: g [options] [git (checkout|clone|fetch|gc|grep|pull|push|reset) [git options/args..]]"
echo ""
echo " -z restore the git hooks and do other sanity checks"
}
refresh_create_link()
{
local hook_name=$1
local hook=$2
local lnarg=$3
# if it doesn't exist or is neither a symlink nor sharing the same inode (hardlink)
if [ ! -e "${hook?}" ] || [ ! \( -L "${hook?}" -o "${hook_name}" -ef "${hook?}" \) ] ; then
rm -f "${hook?}"
ln -f $lnarg "${hook_name}" "${hook?}"
fi
}
refresh_submodule_hooks()
{
local repo=$1
local lnarg=$2
local hook
local hook_name
if [ -d "${repo?}"/.git ] ; then
# use core's hook by default
for hook_name in "${COREDIR?}/.git-hooks"/* ; do
if [ ! -e "${hook_name}" ] ; then
continue
fi
hook="${repo?}/.git/hooks/${hook_name##*/}"
refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
done
# override if need be by the submodules' own hooks
for hook_name in "${COREDIR?}/${repo?}/.git-hooks"/* ; do
if [ ! -e "${hook_name}" ] ; then
continue
fi
hook="${repo?}/.git/hooks/${hook_name##*/}"
refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
done
elif [ -d .git/modules/"${repo}"/hooks ] ; then
for hook_name in "${COREDIR?}/.git-hooks"/* ; do
if [ ! -e "${hook_name}" ] ; then
continue
fi
hook=".git/modules/${repo?}/hooks/${hook_name##*/}"
refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
done
# override if need be by the submodules' own hooks
for hook_name in "${COREDIR?}/${repo?}/.git-hooks"/* ; do
if [ ! -e "${hook_name}" ] ; then
continue
fi
hook=".git/modules/${repo?}/hooks/${hook_name##*/}"
refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
done
fi
}
refresh_all_hooks()
{
local repo
local hook_name
local hook
local gitbash
local lnarg
pushd "${COREDIR?}" > /dev/null
# it is 'GIT for Windows'
gitbash=$(echo $OSTYPE | grep -ic msys)
# git-bash/MSYS doesn't create symlinks by default, and "real" symlinks are restricted to
# Admin-mode or when devmode is activated, junction points as fallback would work for bash/
# regular use but not when git tries to spawn them, similar for plain windows shortcuts (worse
# because running the hooks will fail silently/they'd be inactive)
# ln -s without setting MSYS to contain winsymlinks:{lnk,native,nativestrict,sys} to force one
# of the other modes described above will do plain copies.
# So in case of git-bash use hardlinks since those work just fine, everywhere else use symlinks
if [ $gitbash -ne 1 ]; then
lnarg="--symbolic"
fi
# There's no ".git" e.g. in a secondary worktree
if [ -d ".git" ]; then
for hook_name in "${COREDIR?}/.git-hooks"/* ; do
hook=".git/hooks/${hook_name##*/}"
refresh_create_link "${hook_name}" "${hook?}" "$lnarg"
done
fi
for repo in ${SUBMODULES_ALL?} ; do
refresh_submodule_hooks "$repo" "$lnarg"
done
popd > /dev/null
}
set_push_url()
{
local repo
repo="$1"
if [ -n "$repo" ] ; then
pushd "${COREDIR?}/${repo?}" > /dev/null
else
pushd "${COREDIR?}" > /dev/null
repo="core"
fi
echo "setting up push url for ${repo?}"
if [ "${repo?}" = "helpcontent2" ] ; then
git config remote.origin.pushurl "ssh://${PUSH_USER}logerrit/help"
else
git config remote.origin.pushurl "ssh://${PUSH_USER}logerrit/${repo?}"
fi
popd > /dev/null
}
set_push_urls()
{
PUSH_USER="$1"
set_push_url
for repo in ${SUBMODULES_ACTIVE?} ; do
set_push_url "${repo?}"
done
}
get_active_submodules()
{
SUBMODULES_ACTIVE=""
local repo
for repo in ${SUBMODULES_ALL?} ; do
if [ -d "${repo?}"/.git ] || [ -f "${repo?}"/.git ] ; then
SUBMODULES_ACTIVE="${repo?} ${SUBMODULES_ACTIVE?}"
fi
done
}
get_configured_submodules()
{
SUBMODULES_CONFIGURED=""
if [ -f ${BUILDDIR}/config_host.mk ] ; then
SUBMODULES_CONFIGURED=$(< ${BUILDDIR}/config_host.mk grep -a GIT_NEEDED_SUBMODULES | sed -e "s/.*=//")
else
# if we need the configured submodule before the configuration is done. we assumed you want them all
SUBMODULES_CONFIGURED=${SUBMODULES_ALL?}
fi
}
get_git_reference()
{
REFERENCED_GIT=""
if [ -f ${BUILDDIR}/config_host.mk ]; then
REFERENCED_GIT=$(< ${BUILDDIR}/config_host.mk grep -a GIT_REFERENCE_SRC | sed -e "s/.*=//")
fi
LINKED_GIT=""
if [ -f ${BUILDDIR}/config_host.mk ]; then
LINKED_GIT=$(< ${BUILDDIR}/config_host.mk grep -a GIT_LINK_SRC | sed -e "s/.*=//")
fi
}
do_shortcut_update()
{
local module
local repo
for module in $SUBMODULES_CONFIGURED ; do
if [ ! -d "${module?}"/.git ] ; then
case "${module?}" in
helpcontent2)
if [ -d clone/help/.git ] ; then
repo="clone/help/.git"
fi
;;
*)
if [ -d clone/"${module?}"/.git ] ; then
repo="clone/${module?}/.git"
fi
;;
esac
if [ -n "$repo" ] ; then
cp -r "${repo?}" "${module?}/."
fi
fi
done
}
do_git_cmd()
{
echo "cmd:$*"
git "$@"
git submodule foreach git "$@" $KEEP_GOING
}
do_checkout()
{
local cmd
local create_branch="0"
local branch
local module
git checkout "$@" || return $?
for cmd in "$@" ; do
if [ "$cmd" = "-f" ]; then
continue
elif [ "$cmd" = "-b" ] ; then
create_branch=1
elif [ "$create_branch" = "1" ] ; then
branch="$cmd"
create_branch=0
fi
done
if [ -f .gitmodules ] ; then
git submodule update --progress
if [ -n "$branch" ] ; then
git submodule foreach git checkout -b "${branch}" HEAD || return $?
fi
else
# now that is the nasty case we moved prior to submodules
# delete the submodules left over if any
for module in $SUBMODULES_ALL ; do
echo "clean-up submodule $module"
rm -fr "${module}"
done
# make sure we have the needed repo in clone
./g clone && ./g -f checkout "$@" || return $?
fi
return $?
}
do_reset()
{
git reset "$@" || return $?
if [ -f .gitmodules ] ; then
git submodule update --progress || return $?
else
# now that is the nasty case we moved prior to submodules
# delete the submodules left over if any
for module in $SUBMODULES_ALL ; do
echo "clean-up submodule $module"
rm -fr "${module}"
done
# make sure we have the needed repo in clone
./g clone && ./g -f reset "$@"
fi
return $?;
}
do_init_modules()
{
local module
local configured
do_shortcut_update
for module in $SUBMODULES_CONFIGURED ; do
if [ -n "$LINKED_GIT" ] ; then
if ! [ -d ".git/modules/${module}" ]; then
./bin/git-new-module-workdir "${LINKED_GIT}/${module}" "${module}"
fi
fi
configured=$(git config --local --get submodule."${module}".url)
if [ -z "$configured" ] ; then
git submodule init "$module" || return $?
fi
done
for module in $SUBMODULES_CONFIGURED ; do
if [ -n "$REFERENCED_GIT" ] ; then
git submodule update --reference "$REFERENCED_GIT/.git/modules/$module" --progress "$module" || return $?
else
git submodule update --progress "$module" || return $?
fi
done
return 0
}
# no params, no action
if [ "$#" -eq "0" ] ; then
usage
fi
if [ ! "$(type -p git)" ]; then
echo "Cannot find the git binary! Is git installed and is in PATH?"
exit 1
fi
get_active_submodules
get_configured_submodules
get_git_reference
# extra params for some commands, like log
EXTRA=
COMMAND="$1"
PAGER=
RELATIVIZE=1
PUSH_ALL=
PUSH_USER=
PUSH_NOTES=
LAST_WORKING=
SET_LAST_WORKING=
ALLOW_EMPTY=
KEEP_GOING=
REPORT_REPOS=1
REPORT_COMMANDS=0
REPORT_COMPACT=0
DO_HOOK_REFRESH=false
while [ "${COMMAND:0:1}" = "-" ] ; do
case "$COMMAND" in
-f )KEEP_GOING="||:"
;;
-z)
refresh_all_hooks
exit 0;
;;
--set-push-urls)
shift
PUSH_USER="$1"
if [ -n "${PUSH_USER}" ] ; then
PUSH_USER="${PUSH_USER}@"
fi
set_push_urls "$PUSH_USER"
exit 0;
;;
-*)
echo "option: $COMMAND not supported" 1>&2
exit 1
esac
shift
COMMAND="$1"
done
shift
case "$COMMAND" in
branch)
do_git_cmd "${COMMAND}" "$@"
;;
checkout)
do_checkout "$@"
;;
clone)
do_init_modules && refresh_all_hooks
;;
fetch)
(git fetch "$@" && git submodule foreach git fetch "$@" ) && git submodule update --progress
;;
gc)
(git gc "$@" && git submodule foreach git gc "$@" )
;;
grep)
KEEP_GOING="||:"
do_git_cmd "${COMMAND}" "$@"
;;
pull)
git pull "$@" && git submodule update --progress && refresh_all_hooks
;;
push)
git submodule foreach git push "$@"
if [ "$?" = "0" ] ; then
git push "$@"
fi
;;
reset)
do_reset
;;
tag)
do_git_cmd "${COMMAND}" "$@"
;;
"")
;;
*)
echo "./g does not support command: $COMMAND" 1>&2
exit 1;
;;
esac
exit $?
# vi:set shiftwidth=4 expandtab: