summaryrefslogtreecommitdiff
path: root/g
diff options
context:
space:
mode:
Diffstat (limited to 'g')
-rwxr-xr-xg587
1 files changed, 228 insertions, 359 deletions
diff --git a/g b/g
index a82fc313c2db..d73b8a6052fa 100755
--- a/g
+++ b/g
@@ -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: