Page Breaks: IsLeaveWindow() is unreliable, we do not need it here.
[LibreOffice.git] / g
blob5b39c462ef748789ba85a4bb346ab53e3b110c73
1 #!/usr/bin/env bash
3 # Wrapper for git to handle more subdirs at the same time
6 # no params, no action
7 if [ "$#" -eq "0" ] ; then
8 git
9 echo
10 echo "Additional options available only in this 'g' wrapper:"
11 echo
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";
22 exit $?
25 if [ ! "`type -p git`" ]; then
26 echo "Cannot find the git binary! Is git installed and is in PATH?"
27 exit 1
30 pushd $(dirname $0) > /dev/null
31 COREDIR=$(pwd)
32 popd > /dev/null
34 refresh_hooks()
36 repo=$1
37 case "$repo" in
38 core)
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
43 rm -f "$hook"
44 ln -sf "$COREDIR/git-hooks/$hook_name" "$hook"
46 done
47 popd > /dev/null
49 translations)
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
55 rm -f "$hook"
56 ln -sf "$COREDIR/clone/translations/git-hooks/$hook_name" "$hook"
58 done
59 # .gitattribute should be per-repo, avoid entangling repos
60 if [ -L .gitattributes ] ; then
61 rm -f .gitattributes
63 popd > /dev/null
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
75 rm -f "$hook"
76 ln -sf "$COREDIR/git-hooks/$hook_name" "$hook"
78 done
79 # .gitattribute should be per-repo, avoid entangling repos
80 if [ -L .gitattributes ] ; then
81 rm -f .gitattributes
83 popd > /dev/null
86 esac
89 refresh_all_hooks()
91 repos="core $(cat "$COREDIR/bin/repo-list")"
92 for repo in $repos ; do
93 refresh_hooks $repo
94 done
97 postprocess()
99 rc=$1
100 if $DO_HOOK_REFRESH ; then
101 refresh_all_hooks
104 exit $rc;
107 CLONEDIR="$COREDIR/clone"
108 if [ ! -e ${CLONEDIR} ]; then mkdir -p "$CLONEDIR"; fi
110 # extra params for some commands, like log
111 EXTRA=
112 COMMAND="$1"
113 PAGER=
114 RELATIVIZE=1
115 PUSH_ALL=
116 PUSH_USER=
117 PUSH_NOTES=
118 LAST_WORKING=
119 SET_LAST_WORKING=
120 ALLOW_EMPTY=
121 KEEP_GOING=0
122 REPORT_REPOS=1
123 REPORT_COMMANDS=0
124 REPORT_COMPACT=0
125 DO_HOOK_REFRESH=false
127 while [ "${COMMAND:0:1}" = "-" ] ; do
128 case "$COMMAND" in
129 -f) KEEP_GOING=1
131 -s) REPORT_REPOS=0
133 -v) REPORT_COMMANDS=1
135 -1) REPORT_COMPACT=1
137 --set-push-user)
138 shift
139 PUSH_USER="$1"
141 --last-working) LAST_WORKING=1
143 --set-last-working) SET_LAST_WORKING=1
145 --push-notes) PUSH_NOTES=1
148 DO_HOOK_REFRESH=true
149 postprocess 0
151 esac
152 shift
153 COMMAND="$1"
154 done
156 case "$COMMAND" in
157 apply)
158 EXTRA="-p0 --stat --apply --index --ignore-space-change --whitespace=error"
159 RELATIVIZE=0
161 clone|fetch|pull)
162 DO_HOOK_REFRESH=true
164 diff)
165 PAGER='--no-pager'
166 REPORT_REPOS=0
168 log)
169 if [ "$#" = "1" ] ; then
170 EXTRA='-1'
172 PAGER='--no-pager'
174 push)
175 if [ "$#" != "1" ] ; then
176 PUSH_ALL=1
179 esac
181 # absolutize the parameters first
182 unset FILES
183 FILESNUM=0
184 while shift ; do
185 PARAM="$1"
186 if [ -z "$PARAM" ] ; then
187 continue
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" \) ]
194 then
195 # params that take an argument
196 FILES[$FILESNUM]="$PARAM"
197 FILESNUM=$(($FILESNUM+1))
198 shift
199 FILES[$FILESNUM]="$1"
200 FILESNUM=$(($FILESNUM+1))
201 else
202 if [ "$COMMAND" = "commit" -a "$PARAM" = "-F" ]
203 then
204 shift
205 # this still needs some magic to handle relative paths
206 EXTRA="${EXTRA} -F ${1}"
207 else
208 [ "$COMMAND" = "commit" -a "$PARAM" = "--allow-empty" ] && ALLOW_EMPTY=1
209 FILES[$FILESNUM]="$PARAM"
210 FILESNUM=$(($FILESNUM+1))
213 else
214 if [ "$COMMAND" = "apply" ] ; then
215 grep -qs $'^+ *\t' "$PARAM" && {
216 echo "Patch '$PARAM' introduces tabs in indentation, aborting."
217 echo
218 echo "Please fix the patch (something like s/^\(+ *\)\t/\1 /) and try again."
219 echo
220 exit 1
223 if [ "$COMMAND" == "rev-parse" ] ; then
224 # this is not a file
225 FILES[$FILESNUM]="$PARAM"
226 FILESNUM=$(($FILESNUM+1))
227 else
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))
237 done
239 # do it!
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"
246 NAME="$REPO"
247 if [ "$REPO" = "core" ] ; then
248 DIR="$COREDIR"
249 NAME="main repo"
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)
262 else
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
276 cd "$DIR"
277 else
278 cd "$CLONEDIR"
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
284 FILESNUM=0
285 INSERTNUM=0
286 PWD=$(pwd)
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))
298 else
299 FILES[$INSERTNUM]="$I"
300 INSERTNUM=$(($INSERTNUM+1))
302 done
303 [ "$INSERTNUM" = "0" ] && exit 0
306 # some extra params
307 case "$COMMAND" in
308 apply)
309 for I in * ; do
310 if [ -d "$I" ] ; then
311 EXTRA="$EXTRA --include=$I/*"
312 else
313 EXTRA="$EXTRA --include=$I"
315 done
317 commit)
318 if [ "$ALLOW_EMPTY" != "1" ] ; then
319 [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0
322 push)
323 if [ "$PUSH_ALL" != "1" ] ; then
324 [ -n "$(git rev-list origin..HEAD)" ] || exit 0
327 status)
328 LOCALCOMMITS="$(git rev-list origin..HEAD)"
329 if [ -z "$LOCALCOMMITS" ] ; then
330 [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0
333 clone)
334 EXTRA="$(git config remote.origin.url)"
335 EXTRA=${EXTRA/core/${REPO}}
337 esac
339 # do it!
340 if [ "$COMMAND" != "clone" -o ! -d $DIR ] ; then
341 if [ "$REPORT_REPOS" = "1" -a "$COMMAND" != "grep" ] ; then
342 if [ "$REPORT_COMPACT" = "1" ] ; then
343 echo -n "${REPO}:"
344 else
345 echo "===== $NAME ====="
348 if [ "$REPORT_COMMANDS" = "1" ] ; then
349 echo "+ git $PAGER $COMMAND $EXTRA ${FILES[@]}"
351 git $PAGER "$COMMAND" $EXTRA "${FILES[@]}"
352 RETURN=$?
355 # now we can change the dir in case of clone as well
356 if [ "$COMMAND" = "clone" ] ; then
357 cd $DIR
360 case "$COMMAND" in
361 pull|clone)
362 # update links
363 if [ "$DIR" != "$COREDIR" ]; then
364 for link in $(ls) ; do
365 if [ ! -e "$COREDIR/$link" ] ; then
366 if test -h "$COREDIR/$link"; then
367 rm "$COREDIR/$link"
368 echo -n "re-"
370 echo "creating missing link $link"
371 ln -s "$DIR/$link" "$COREDIR/$link"
373 done
376 status)
377 # git status returns error in some versions, clear that
378 RETURN=0
380 grep)
381 # git grep return an 'error' if nothing is found
382 # still we should continue grepping the other repos
383 RETURN=0
385 esac
386 if [ "$KEEP_GOING" = "1" ] ; then
387 RETURN=0
390 exit $RETURN
391 ) || postprocess $?
393 done
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"
400 rm $COREDIR/$link
402 done
405 # warn
406 if [ "$COMMAND" = "apply" ] ; then
407 echo
408 echo "Don't forget to check the status & commit now ;-)"
409 echo
412 postprocess $?
414 # vi:set shiftwidth=4 expandtab: