3 # Wrapper for git to handle more subdirs at the same time
7 if [ "$#" -eq "0" ] ; then
10 echo "Additional options available only in this 'g' wrapper:"
12 echo "Usage: g [options] [git commands]"
13 echo " -f Force - act on all the repos, not only the changed ones"
14 echo " -s Silent - do not report the repo names."
15 echo " -v Verbose - Print git commands."
16 echo " -1 report the repos name on the first line of the output as <repo>:"
17 echo " -z just to some house cleaning (hooks mostly). this is a stand-alone option as in ./g -z"
18 echo " --set-push-user [username] re-write an existing tree's config with an fd.o commit account name"
19 echo " --last-working checks out the last known working build (useful for windows)";
20 echo " --set-last-working adds a note denoting a working build";
21 echo " --push-notes pushes all notes";
25 if [ ! "`type -p git`" ]; then
26 echo "Cannot find the git binary! Is git installed and is in PATH?"
30 pushd $
(dirname $0) > /dev
/null
39 pushd $COREDIR > /dev
/null
40 for hook_name
in $
(ls -1 $COREDIR/git-hooks
) ; do
41 hook
=".git/hooks/$hook_name"
42 if [ ! -x "$hook" ] ; then
44 ln -sf "$COREDIR/git-hooks/$hook_name" "$hook"
50 if [ -d $COREDIR/clone
/translations
] ; then
51 pushd $COREDIR/clone
/translations
> /dev
/null
52 for hook_name
in $
(ls -1 $COREDIR/clone
/translations
/git-hooks
); do
53 hook
=".git/hooks/$hook_name"
54 if [ ! -x "$hook" ] ; then
56 ln -sf "$COREDIR/clone/translations/git-hooks/$hook_name" "$hook"
59 # .gitattribute should be per-repo, avoid entangling repos
60 if [ -L .gitattributes
] ; then
66 binfilter|
help|dictionaries
)
67 if [ -d $COREDIR/clone
/$repo ] ; then
68 pushd $COREDIR/clone
/$repo > /dev
/null
69 # fixme: we should really keep these per-repo to
70 # keep the repos independant. since these two
71 # are realy not independant yet, we keep using core's hooks
72 for hook_name
in $
(ls -1 $COREDIR/git-hooks
) ; do
73 hook
=".git/hooks/$hook_name"
74 if [ ! -x "$hook" ] ; then
76 ln -sf "$COREDIR/git-hooks/$hook_name" "$hook"
79 # .gitattribute should be per-repo, avoid entangling repos
80 if [ -L .gitattributes
] ; then
91 repos
="core $(cat "$COREDIR/bin
/repo-list
")"
92 for repo
in $repos ; do
100 if $DO_HOOK_REFRESH ; then
107 CLONEDIR
="$COREDIR/clone"
108 if [ ! -e ${CLONEDIR} ]; then mkdir
-p "$CLONEDIR"; fi
110 # extra params for some commands, like log
125 DO_HOOK_REFRESH
=false
127 while [ "${COMMAND:0:1}" = "-" ] ; do
133 -v) REPORT_COMMANDS
=1
141 --last-working) LAST_WORKING
=1
143 --set-last-working) SET_LAST_WORKING
=1
145 --push-notes) PUSH_NOTES
=1
158 EXTRA
="-p0 --stat --apply --index --ignore-space-change --whitespace=error"
169 if [ "$#" = "1" ] ; then
175 if [ "$#" != "1" ] ; then
181 # absolutize the parameters first
186 if [ -z "$PARAM" ] ; then
188 elif [ "${PARAM:0:1}" = "-" ] ; then
189 if [ \
( "$COMMAND" = "checkout" -a "$PARAM" = "-b" \
) -o \
190 \
( "$COMMAND" = "clone" -a "$PARAM" = "--reference" \
) -o \
191 \
( "$COMMAND" = "commit" -a "$PARAM" = "-m" \
) -o \
192 \
( "$COMMAND" = "commit" -a "$PARAM" = "-am" \
) -o \
193 \
( "$COMMAND" = "tag" -a "$PARAM" = "-m" \
) ]
195 # params that take an argument
196 FILES
[$FILESNUM]="$PARAM"
197 FILESNUM
=$
(($FILESNUM+1))
199 FILES
[$FILESNUM]="$1"
200 FILESNUM
=$
(($FILESNUM+1))
202 if [ "$COMMAND" = "commit" -a "$PARAM" = "-F" ]
205 # this still needs some magic to handle relative paths
206 EXTRA
="${EXTRA} -F ${1}"
208 [ "$COMMAND" = "commit" -a "$PARAM" = "--allow-empty" ] && ALLOW_EMPTY
=1
209 FILES
[$FILESNUM]="$PARAM"
210 FILESNUM
=$
(($FILESNUM+1))
214 if [ "$COMMAND" = "apply" ] ; then
215 grep -qs $
'^+ *\t' "$PARAM" && {
216 echo "Patch '$PARAM' introduces tabs in indentation, aborting."
218 echo "Please fix the patch (something like s/^\(+ *\)\t/\1 /) and try again."
223 if [ "$COMMAND" == "rev-parse" ] ; then
225 FILES
[$FILESNUM]="$PARAM"
226 FILESNUM
=$
(($FILESNUM+1))
228 # make the paths absolute
229 FILES
[$FILESNUM]=$
(perl
-e 'use Cwd "abs_path"; print abs_path(shift);' "$PARAM")
230 if [ -z "${FILES[$FILESNUM]}" -o ! -e "${FILES[$FILESNUM]}" ] ; then
231 # it is probably not a file, but a tag name, or something
232 FILES
[$FILESNUM]="$PARAM"
234 FILESNUM
=$
(($FILESNUM+1))
240 DIRS
="core $(cd $CLONEDIR ; ls)"
241 if [ "$COMMAND" = "clone" ] ; then
242 DIRS
=$
(cat "$COREDIR/bin/repo-list")
244 for REPO
in $DIRS ; do
245 DIR
="$CLONEDIR/$REPO"
247 if [ "$REPO" = "core" ] ; then
252 if [ -d "$DIR" -a "z$PUSH_USER" != "z" ]; then
253 echo "setting up push url for $DIR"
254 (cd $DIR && git config remote.origin.pushurl
"ssh://${PUSH_USER}@git.freedesktop.org/git/libreoffice/${REPO}")
255 elif [ -d "$DIR" -a "z$LAST_WORKING" != "z" ]; then
256 echo "fetching notes for $REPO ..."
257 (cd $DIR && git fetch origin
'refs/notes/*:refs/notes/*')
258 hash=`(cd $DIR && git log --pretty='%H %N' | grep 'win32 working build' | head -n1 | sed 's/ win32.*//')`
259 if test "z$hash" != "z"; then
260 echo "update to $hash"
261 (cd $DIR && git checkout
$hash)
263 echo "Warning: missing known working note on repo $REPO"
265 elif [ -d "$DIR" -a "z$SET_LAST_WORKING" != "z" ]; then
266 echo "fetching notes for $REPO ..."
267 (cd $DIR && git fetch origin
'refs/notes/*:refs/notes/*')
268 (cd $DIR && git notes add
-m 'win32 working build')
269 elif [ -d "$DIR" -a "z$PUSH_NOTES" != "z" ]; then
270 echo "pushing notes for $REPO ..."
271 (cd $DIR && git push origin
'refs/notes/*:refs/notes/*')
272 elif [ \
( -d "$DIR" -a -d "$DIR"/.git \
) -o \
( "$COMMAND" = "clone" \
) ] ; then
274 # executed in a subshell
275 if [ "$COMMAND" != "clone" ] ; then
281 # relativize the absolutized params again if we want to operate
282 # only on the files belonging to this exact repo
283 if [ "$RELATIVIZE" = "1" -a -n "$FILES" ] ; then
287 PWDLEN
=$
(pwd |
wc -c)
288 for I
in "${FILES[@]}" ; do
289 I
="${I//@REPO@/${REPO}}"
290 unset FILES
[$FILESNUM]
291 FILESNUM
=$
(($FILESNUM+1))
292 # filter out files that don't belong to this repo
293 if [ \
( "${I:0:1}" = "/" \
) -a \
( "$COMMAND" != "clone" \
) ] ; then
294 if [ "${I:0:$PWDLEN}" = "$PWD/" ] ; then
295 FILES
[$INSERTNUM]="${I:$PWDLEN}"
296 INSERTNUM
=$
(($INSERTNUM+1))
299 FILES
[$INSERTNUM]="$I"
300 INSERTNUM
=$
(($INSERTNUM+1))
303 [ "$INSERTNUM" = "0" ] && exit 0
310 if [ -d "$I" ] ; then
311 EXTRA
="$EXTRA --include=$I/*"
313 EXTRA
="$EXTRA --include=$I"
318 if [ "$ALLOW_EMPTY" != "1" ] ; then
319 [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0
323 if [ "$PUSH_ALL" != "1" ] ; then
324 [ -n "$(git rev-list @{upstream}..HEAD)" ] ||
exit 0
328 LOCALCOMMITS
="$(git rev-list @{upstream}..HEAD)"
329 if [ -z "$LOCALCOMMITS" ] ; then
330 [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0
334 EXTRA
="$(git config remote.origin.url)"
335 EXTRA
=${EXTRA/core/${REPO}}
340 if [ "$COMMAND" != "clone" -o ! -d $DIR ] ; then
341 if [ "$REPORT_REPOS" = "1" -a "$COMMAND" != "grep" ] ; then
342 if [ "$REPORT_COMPACT" = "1" ] ; then
345 echo "===== $NAME ====="
348 if [ "$REPORT_COMMANDS" = "1" ] ; then
349 echo "+ git $PAGER $COMMAND $EXTRA ${FILES[@]}"
351 git
$PAGER "$COMMAND" $EXTRA "${FILES[@]}"
355 # now we can change the dir in case of clone as well
356 if [ "$COMMAND" = "clone" ] ; then
363 if [ "$DIR" != "$COREDIR" ]; then
364 for link
in $
(ls) ; do
365 if [ ! -e "$COREDIR/$link" ] ; then
366 if test -h "$COREDIR/$link"; then
370 echo "creating missing link $link"
371 ln -s "$DIR/$link" "$COREDIR/$link"
377 # git status returns error in some versions, clear that
381 # git grep return an 'error' if nothing is found
382 # still we should continue grepping the other repos
386 if [ "$KEEP_GOING" = "1" ] ; then
395 # Cleanup the broken links
396 if [ "$COMMAND" = "pull" ] ; then
397 for link
in $
(ls $COREDIR) ; do
398 if [ -h "$COREDIR/$link" -a ! -e "$COREDIR/$link" ]; then
399 echo "Removing broken link $link"
406 if [ "$COMMAND" = "apply" ] ; then
408 echo "Don't forget to check the status & commit now ;-)"
414 # vi:set shiftwidth=4 expandtab: