diff options
Diffstat (limited to 'g')
-rwxr-xr-x | g | 444 |
1 files changed, 444 insertions, 0 deletions
@@ -0,0 +1,444 @@ +#!/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_submodule_hooks() +{ + local repo=$1 + 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##*/}" + if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${hook_name}" "${hook?}" + fi + 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##*/}" + if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${hook_name}" "${hook?}" + fi + 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##*/}" + if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${hook_name}" "${hook?}" + fi + 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##*/}" + if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${hook_name}" "${hook?}" + fi + done + fi + +} + +refresh_all_hooks() +{ + local repo + local hook_name + local hook + local winlnk + local wingit + local gitbash + local lnkfile=".git/hooks/pre-commit" + + pushd "${COREDIR?}" > /dev/null + + # it is 'GIT for Windows' + wingit=$(git --version | grep -ic windows) + gitbash=$(echo $OSTYPE | grep -ic msys) + + # In the win-git-bash, do not make links, it makes only copies + if [ $gitbash -eq 1 ]; then + if [ -d ".git" ]; then + if [ ! -e "${lnkfile}" ] || [ ! -L "${lnkfile}" ] ; then + # here when wrong link then the file not exist + echo "Your hooks not right, solve this in cygwin with" + echo " ./g -z" + fi + fi + else + if [ $wingit -eq 1 ]; then + # There's no ".git" e.g. in a secondary worktree + if [ -d ".git" ]; then + winlnk=0 + if [ -e "${lnkfile}" ] && [ -L "${lnkfile}" ] ; then + # if linux-links or windows-links? + # dos dir output windows link: + # 04.09.2020 10:54 <SYMLINK> pre-commit [..\..\.git-hooks\pre-commit] + # dos dir output linux link: + # file not found + winlnk=$(cmd /C "DIR ${lnkfile//'/'/'\'}" 2>&1) + winlnk=$(echo "$winlnk" | grep -icE "<SYMLINK>.*${lnkfile##*/} \[") + fi + + if [ $winlnk -eq 0 ]; then + echo "You using GIT for Windows, but the hook-links not right, change with mklink" + cat .git-hooks/README + fi + fi + else + # 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##*/}" + if [ ! -e "${hook?}" ] || [ ! -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${hook_name}" "${hook?}" + fi + done + fi + + for repo in ${SUBMODULES_ALL?} ; do + refresh_submodule_hooks "$repo" + done + fi + fi + + 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: |