caf0071d60
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
418 lines
10 KiB
Bash
Executable file
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:
|