diff options
Diffstat (limited to 'g')
-rwxr-xr-x | g | 587 |
1 files changed, 228 insertions, 359 deletions
@@ -3,116 +3,207 @@ # Wrapper for git to handle more subdirs at the same time # -# no params, no action -if [ "$#" -eq "0" ] ; then - git - echo - echo "Additional options available only in this 'g' wrapper:" - echo - echo "Usage: g [options] [git commands]" - echo " -f Force - act on all the repos, not only the changed ones" - echo " -s Silent - do not report the repo names." - echo " -v Verbose - Print git commands." - echo " -1 report the repos name on the first line of the output as <repo>:" - echo " -z just to some house cleaning (hooks mostly). this is a stand-alone option as in ./g -z" - echo " --set-push-user [username] re-write an existing tree's config with an fd.o commit account name" - echo " --last-working checks out the last known working build (useful for windows)"; - echo " --set-last-working adds a note denoting a working build"; - echo " --push-notes pushes all notes"; - exit $? +if [ -n "$g_debug" ] ; then + set -x fi -if [ ! "`type -p git`" ]; then - echo "Cannot find the git binary! Is git installed and is in PATH?" - exit 1 -fi +SUBMODULES_ALL="binfilter dictionaries helpcontent2 translations" pushd $(dirname $0) > /dev/null COREDIR=$(pwd) popd > /dev/null -if test -f $COREDIR/bin/repo-list -then - ALLREPOS="core `cat "$COREDIR/bin/repo-list"`" -else - ALLREPOS=core -fi +usage() +{ + git + echo + echo "Usage: g [options] [git (checkout|clone|fetch|grep|pull|push|reset) [git options/args..]]" + echo "" + echo " -z restaure the git hooks and others sanity checks" +} -refresh_hooks() +refresh_submodule_hooks() { - repo=$1 - case "$repo" in - core) - pushd $COREDIR > /dev/null - for hook_name in $(ls -1 $COREDIR/git-hooks) ; do - hook=".git/hooks/$hook_name" - if [ ! -x "$hook" ] ; then - rm -f "$hook" - ln -sf "$COREDIR/git-hooks/$hook_name" "$hook" - fi - done - popd > /dev/null - ;; - translations) - if [ -d $COREDIR/clone/translations ] ; then - pushd $COREDIR/clone/translations > /dev/null - for hook_name in $(ls -1 $COREDIR/clone/translations/git-hooks); do - hook=".git/hooks/$hook_name" - if [ ! -x "$hook" ] ; then - rm -f "$hook" - ln -sf "$COREDIR/clone/translations/git-hooks/$hook_name" "$hook" - fi - done - # .gitattribute should be per-repo, avoid entangling repos - if [ -L .gitattributes ] ; then - rm -f .gitattributes - fi - popd > /dev/null - fi - ;; - binfilter|help|dictionaries) - if [ -d $COREDIR/clone/$repo ] ; then - pushd $COREDIR/clone/$repo > /dev/null - # fixme: we should really keep these per-repo to - # keep the repos independant. since these two - # are realy not independant yet, we keep using core's hooks - for hook_name in $(ls -1 $COREDIR/git-hooks) ; do - hook=".git/hooks/$hook_name" - if [ ! -x "$hook" ] ; then - rm -f "$hook" - ln -sf "$COREDIR/git-hooks/$hook_name" "$hook" - fi - done - # .gitattribute should be per-repo, avoid entangling repos - if [ -L .gitattributes ] ; then - rm -f .gitattributes - fi - popd > /dev/null +local repo=$1 +local hook +local hook_name + + if [ -d ${repo?}/.git ] ; then + # use core's hook by default + for hook_name in $(ls -1 ${COREDIR?}/.git-hooks) ; do + hook="${repo?}/.git/hooks/${hook_name?}" + if [ ! -e "${hook?}" -o -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${COREDIR?}/.git-hooks/${hook_name?}" "${hook?}" fi - ;; - esac + done + # override if need be by the submodules' own hooks + for hook_name in $(ls -1 ${COREDIR?}/${repo?}/.git-hooks 2>/dev/null) ; do + hook="${repo?}/.git/hooks/${hook_name?}" + if [ ! -e "${hook?}" -o -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${COREDIR?}/${repo?}/.git-hooks/${hook_name?}" "${hook?}" + fi + done + fi } refresh_all_hooks() { - repos="$ALLREPOS" - for repo in $repos ; do - refresh_hooks $repo +local repo +local hook_name +local hook + + pushd ${COREDIR?} > /dev/null + for hook_name in $(ls -1 ${COREDIR?}/.git-hooks) ; do + hook=".git/hooks/${hook_name?}" + if [ ! -e "${hook?}" -o -L "${hook?}" ] ; then + rm -f "${hook?}" + ln -sf "${COREDIR?}/.git-hooks/${hook_name?}" "${hook?}" + fi + done + + for repo in ${SUBMODULES_ALL?} ; do + refresh_submodule_hooks $repo + 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}gerrit.libreoffice.org:29418/help" + else + git config remote.origin.pushurl "ssh://${PUSH_USER}gerrit.libreoffice.org:29418/${repo?}" + fi + popd > /dev/null +} + +set_push_urls() +{ + PUSH_USER="$1" + if [ -n "$PUSH_USER" ] ; then + PUSH_USER="${PUSH_USER}@" + fi + 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 ] ; then + SUBMODULES_ACTIVE="${repo?} ${SUBMODULES_ACTIVE?}" + fi done } -postprocess() +get_configured_submodules() { - rc=$1 - if $DO_HOOK_REFRESH ; then - refresh_all_hooks + SUBMODULES_CONFIGURED="" + if [ -f "config_host.mk" ] ; then + SUBMODULES_CONFIGURED=$(cat config_host.mk | grep GIT_NEEDED_SUBMODULES | sed -e "s/.*=//") + else + # if we need the configured submoduel before the configuration is done. we assumed you want them all + SUBMODULES_CONFIGURED=${SUBMODULES_ALL?} fi +} + +do_git_cmd() +{ + echo "cmd:$@" + git "$@" + git submodule foreach git "$@" $KEEP_GOING +} + +do_checkout() +{ +local cmd +local create_branch="0" +local branch + + git checkout "$@" || return $? + for cmd in "$@" ; do + if [ "$cmd" = "-f" ]; then + return 0 + elif [ "$cmd" = "-b" ] ; then + create_branch=1 + elif [ "$create_branch" = "1" ] ; then + branch="$arg" + fi + done + if [ -f .gitmodules ] ; then + if [ -n "$branch" ] ; then + git submodules foreach git branch ${branch} HEAD || return $? + fi + else + # now that is the nasty case we moved prior to submodules + # 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 || return $? + else + # now that is the nasty case we moved prior to submodules + # make sure we have the needed repo in clone + ./g clone && ./g -f reset "$@" + fi + return $?; +} + +do_init_modules() +{ +local module +local configured - exit $rc; + for module in $SUBMODULES_CONFIGURED ; do + configured=$(git config --local --get submodule.${module}.url) + if [ -z "$configured" ] ; then + git submodule init $module || return $? + fi + done + return 0 } -CLONEDIR="$COREDIR/clone" -if [ ! -e ${CLONEDIR} ]; then mkdir -p "$CLONEDIR"; fi + +# 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 + + + # extra params for some commands, like log EXTRA= @@ -125,7 +216,7 @@ PUSH_NOTES= LAST_WORKING= SET_LAST_WORKING= ALLOW_EMPTY= -KEEP_GOING=0 +KEEP_GOING= REPORT_REPOS=1 REPORT_COMMANDS=0 REPORT_COMPACT=0 @@ -133,289 +224,67 @@ DO_HOOK_REFRESH=false while [ "${COMMAND:0:1}" = "-" ] ; do case "$COMMAND" in - -f) KEEP_GOING=1 - ;; - -s) REPORT_REPOS=0 - ;; - -v) REPORT_COMMANDS=1 - ;; - -1) REPORT_COMPACT=1 - ;; - --set-push-user) - shift - PUSH_USER="$1" - ;; - --last-working) LAST_WORKING=1 - ;; - --set-last-working) SET_LAST_WORKING=1 - ;; - --push-notes) PUSH_NOTES=1 + -f )KEEP_GOING="||:" ;; -z) - DO_HOOK_REFRESH=true - postprocess 0 + 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 + exit 0; + ;; + -*) + echo "option: $COMMAND not supported" 1>&2 + exit 1 esac shift COMMAND="$1" done +shift + case "$COMMAND" in - apply) - EXTRA="-p0 --stat --apply --index --ignore-space-change --whitespace=error" - RELATIVIZE=0 - ;; - clone|fetch|pull) - DO_HOOK_REFRESH=true - ;; - diff) - PAGER='--no-pager' - REPORT_REPOS=0 - ;; - log) - if [ "$#" = "1" ] ; then - EXTRA='-1' - fi - PAGER='--no-pager' + branch) + do_git_cmd ${COMMAND} "$@" + ;; + checkout) + do_checkout "$@" && git submodule foreach git checkout "$@" + ;; + clone) + do_init_modules && git submodule update && refresh_all_hooks ;; + fetch) + (git fetch "$@" && git submodule foreach git fetch "$@" ) && git submodule update + + ;; + grep) + KEEP_GOING="||:" + do_git_cmd ${COMMAND} "$@" + ;; + pull) + git pull "$@" && git submodule update && refresh_all_hooks + ;; push) - if [ "$#" != "1" ] ; then - PUSH_ALL=1 - fi + git submodule foreach git push "$@" + if [ "$?" = "0" ] ; then + git push "$@" + fi + ;; + reset) + do_reset + ;; + *) + echo "./g does not support command:$COMMAND" 1>&2 + exit 1; ;; esac -# absolutize the parameters first -unset FILES -FILESNUM=0 -while shift ; do - PARAM="$1" - if [ -z "$PARAM" ] ; then - continue - elif [ "${PARAM:0:1}" = "-" ] ; then - if [ \( "$COMMAND" = "checkout" -a "$PARAM" = "-b" \) -o \ - \( "$COMMAND" = "clone" -a "$PARAM" = "--reference" \) -o \ - \( "$COMMAND" = "commit" -a "$PARAM" = "-m" \) -o \ - \( "$COMMAND" = "commit" -a "$PARAM" = "-am" \) -o \ - \( "$COMMAND" = "tag" -a "$PARAM" = "-m" \) ] - then - # params that take an argument - FILES[$FILESNUM]="$PARAM" - FILESNUM=$(($FILESNUM+1)) - shift - FILES[$FILESNUM]="$1" - FILESNUM=$(($FILESNUM+1)) - else - if [ "$COMMAND" = "commit" -a "$PARAM" = "-F" ] - then - shift - # this still needs some magic to handle relative paths - EXTRA="${EXTRA} -F ${1}" - else - [ "$COMMAND" = "commit" -a "$PARAM" = "--allow-empty" ] && ALLOW_EMPTY=1 - FILES[$FILESNUM]="$PARAM" - FILESNUM=$(($FILESNUM+1)) - fi - fi - else - if [ "$COMMAND" = "apply" ] ; then - grep -qs $'^+ *\t' "$PARAM" && { - echo "Patch '$PARAM' introduces tabs in indentation, aborting." - echo - echo "Please fix the patch (something like s/^\(+ *\)\t/\1 /) and try again." - echo - exit 1 - } - fi - if [ "$COMMAND" == "rev-parse" ] ; then - # this is not a file - FILES[$FILESNUM]="$PARAM" - FILESNUM=$(($FILESNUM+1)) - else - # make the paths absolute - FILES[$FILESNUM]=$(perl -e 'use Cwd "abs_path"; print abs_path(shift);' "$PARAM" 2>/dev/null) - if [ -z "${FILES[$FILESNUM]}" -o ! -e "${FILES[$FILESNUM]}" ] ; then - # it is probably not a file, but a tag name, or something - FILES[$FILESNUM]="$PARAM" - fi - FILESNUM=$(($FILESNUM+1)) - fi - fi -done - -# do it! -DIRS="core $(cd $CLONEDIR ; ls)" -if [ "$COMMAND" = "clone" ] ; then - DIRS="$ALLREPOS" -fi -for REPO in $DIRS ; do - DIR="$CLONEDIR/$REPO" - NAME="$REPO" - if [ "$REPO" = "core" ] ; then - DIR="$COREDIR" - NAME="main repo" - fi - - if [ -d "$DIR" -a "z$PUSH_USER" != "z" ]; then - echo "setting up push url for $DIR" - (cd $DIR && git config remote.origin.pushurl "ssh://${PUSH_USER}@gerrit.libreoffice.org:29418/${REPO}") - elif [ -d "$DIR" -a "z$LAST_WORKING" != "z" ]; then - echo "fetching notes for $REPO ..." - (cd $DIR && git fetch origin 'refs/notes/*:refs/notes/*') - hash=`(cd $DIR && git log --pretty='%H %N' | grep 'win32 working build' | head -n1 | sed 's/ win32.*//')` - if test "z$hash" != "z"; then - echo "update to $hash" - (cd $DIR && git checkout $hash) - else - echo "Warning: missing known working note on repo $REPO" - fi - elif [ -d "$DIR" -a "z$SET_LAST_WORKING" != "z" ]; then - echo "fetching notes for $REPO ..." - (cd $DIR && git fetch origin 'refs/notes/*:refs/notes/*') - (cd $DIR && git notes add -m 'win32 working build') - elif [ -d "$DIR" -a "z$PUSH_NOTES" != "z" ]; then - echo "pushing notes for $REPO ..." - (cd $DIR && git push origin 'refs/notes/*:refs/notes/*') - elif [ \( -d "$DIR" -a -d "$DIR"/.git \) -o \( "$COMMAND" = "clone" \) ] ; then - ( - # executed in a subshell - if [ "$COMMAND" != "clone" ] ; then - cd "$DIR" - else - cd "$CLONEDIR" - fi - - # relativize the absolutized params again if we want to operate - # only on the files belonging to this exact repo - if [ "$RELATIVIZE" = "1" -a -n "$FILES" ] ; then - FILESNUM=0 - INSERTNUM=0 - PWD=$(pwd) - PWDLEN=$(pwd | wc -c) - for I in "${FILES[@]}" ; do - I="${I//@REPO@/${REPO}}" - unset FILES[$FILESNUM] - FILESNUM=$(($FILESNUM+1)) - # filter out files that don't belong to this repo - if [ \( "${I:0:1}" = "/" \) -a \( "$COMMAND" != "clone" \) ] ; then - if [ "${I:0:$PWDLEN}" = "$PWD/" ] ; then - FILES[$INSERTNUM]="${I:$PWDLEN}" - INSERTNUM=$(($INSERTNUM+1)) - fi - else - FILES[$INSERTNUM]="$I" - INSERTNUM=$(($INSERTNUM+1)) - fi - done - [ "$INSERTNUM" = "0" ] && exit 0 - fi - - # some extra params - case "$COMMAND" in - apply) - for I in * ; do - if [ -d "$I" ] ; then - EXTRA="$EXTRA --include=$I/*" - else - EXTRA="$EXTRA --include=$I" - fi - done - ;; - commit) - if [ "$ALLOW_EMPTY" != "1" ] ; then - [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0 - fi - ;; - push) - if [ "$PUSH_ALL" != "1" ] ; then - [ -n "$(git rev-list @{upstream}..HEAD)" ] || exit 0 - fi - ;; - status) - LOCALCOMMITS="$(git rev-list @{upstream}..HEAD)" - if [ -z "$LOCALCOMMITS" ] ; then - [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0 - fi - ;; - clone) - EXTRA="$(git config remote.origin.url)" - EXTRA=${EXTRA/core/${REPO}} - ;; - esac - - # do it! - if [ "$COMMAND" != "clone" -o ! -d $DIR ] ; then - if [ "$REPORT_REPOS" = "1" -a "$COMMAND" != "grep" ] ; then - if [ "$REPORT_COMPACT" = "1" ] ; then - echo -n "${REPO}:" - else - echo "===== $NAME =====" - fi - fi - if [ "$REPORT_COMMANDS" = "1" ] ; then - echo "+ git $PAGER $COMMAND $EXTRA ${FILES[@]}" - fi - git $PAGER "$COMMAND" $EXTRA "${FILES[@]}" - RETURN=$? - fi - - # now we can change the dir in case of clone as well - if [ "$COMMAND" = "clone" ] ; then - cd $DIR - fi - - case "$COMMAND" in - pull|clone) - # update links - if [ "$DIR" != "$COREDIR" ]; then - for link in $(ls) ; do - if [ ! -e "$COREDIR/$link" ] ; then - if test -h "$COREDIR/$link"; then - rm "$COREDIR/$link" - echo -n "re-" - fi - echo "creating missing link $link" - ln -s "$DIR/$link" "$COREDIR/$link" - fi - done - fi - ;; - status) - # git status returns error in some versions, clear that - RETURN=0 - ;; - grep) - # git grep return an 'error' if nothing is found - # still we should continue grepping the other repos - RETURN=0 - ;; - esac - if [ "$KEEP_GOING" = "1" ] ; then - RETURN=0 - fi - - exit $RETURN - ) || postprocess $? - fi -done - -# Cleanup the broken links -if [ "$COMMAND" = "pull" ] ; then - for link in $(ls $COREDIR) ; do - if [ -h "$COREDIR/$link" -a ! -e "$COREDIR/$link" ]; then - echo "Removing broken link $link" - rm $COREDIR/$link - fi - done -fi - -# warn -if [ "$COMMAND" = "apply" ] ; then - echo - echo "Don't forget to check the status & commit now ;-)" - echo -fi - -postprocess $? +exit $? # vi:set shiftwidth=4 expandtab: |