dont attach, start own instance as otherwise it might be blocked via/proc/sys/kernel...
[LibreOffice.git] / g
bloba4f9af5941f675d90795e7403a89149a2cf82fcc
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 " -1 report the repos name on the first line of the output as <repo>:"
16 echo " -z just to some house cleaning (hooks mostly). this is a stand-alone option as in ./g -z"
17 echo " --set-push-user [username] re-write an existing tree's config with an fd.o commit account name"
18 echo " --last-working checks out the last known working build (useful for windows)";
19 echo " --set-last-working adds a note denoting a working build";
20 echo " --push-notes pushes all notes";
21 exit $?
24 if [ ! "`type -p git`" ]; then
25 echo "Cannot find the git binary! Is git installed and is in PATH?"
26 exit 1
29 pushd $(dirname $0) > /dev/null
30 COREDIR=$(pwd)
31 popd > /dev/null
33 refresh_hooks()
35 repo=$1
36 case "$repo" in
37 core)
38 pushd $COREDIR > /dev/null
39 for hook_name in $(ls -1 $COREDIR/git-hooks) ; do
40 hook=".git/hooks/$hook_name"
41 if [ ! -x "$hook" ] ; then
42 rm -f "$hook"
43 ln -sf "$COREDIR/git-hooks/$hook_name" "$hook"
45 done
46 popd > /dev/null
48 translations)
49 if [ -d $COREDIR/clone/translations ] ; then
50 pushd $COREDIR/clone/translations > /dev/null
51 for hook_name in $(ls -1 $COREDIR/clone/translations/git-hooks); do
52 hook=".git/hooks/$hook_name"
53 if [ ! -x "$hook" ] ; then
54 rm -f "$hook"
55 ln -sf "$COREDIR/clone/translations/git-hooks/$hook_name" "$hook"
57 done
58 # .gitattribute should be per-repo, avoid entangling repos
59 if [ -L .gitattributes ] ; then
60 rm -f .gitattributes
62 popd > /dev/null
65 binfilter|help|dictionaries)
66 if [ -d $COREDIR/clone/$repo ] ; then
67 pushd $COREDIR/clone/$repo > /dev/null
68 # fixme: we should really keep these per-repo to
69 # keep the repos independant. since these two
70 # are realy not independant yet, we keep using core's hooks
71 for hook_name in $(ls -1 $COREDIR/git-hooks) ; do
72 hook=".git/hooks/$hook_name"
73 if [ ! -x "$hook" ] ; then
74 rm -f "$hook"
75 ln -sf "$COREDIR/git-hooks/$hook_name" "$hook"
77 done
78 # .gitattribute should be per-repo, avoid entangling repos
79 if [ -L .gitattributes ] ; then
80 rm -f .gitattributes
82 popd > /dev/null
85 esac
88 refresh_all_hooks()
90 repos="core $(cat "$COREDIR/bin/repo-list")"
91 for repo in $repos ; do
92 refresh_hooks $repo
93 done
96 postprocess()
98 rc=$1
99 if $DO_HOOK_REFRESH ; then
100 refresh_all_hooks
103 exit $rc;
106 CLONEDIR="$COREDIR/clone"
107 if [ ! -e ${CLONEDIR} ]; then mkdir -p "$CLONEDIR"; fi
109 # extra params for some commands, like log
110 EXTRA=
111 COMMAND="$1"
112 PAGER=
113 RELATIVIZE=1
114 PUSH_ALL=
115 PUSH_USER=
116 PUSH_NOTES=
117 LAST_WORKING=
118 SET_LAST_WORKING=
119 ALLOW_EMPTY=
120 KEEP_GOING=0
121 REPORT_REPOS=1
122 REPORT_COMPACT=0
123 DO_HOOK_REFRESH=false
125 while [ "${COMMAND:0:1}" = "-" ] ; do
126 case "$COMMAND" in
127 -f) KEEP_GOING=1
129 -s) REPORT_REPOS=0
131 -1) REPORT_COMPACT=1
133 --set-push-user)
134 shift
135 PUSH_USER="$1"
137 --last-working) LAST_WORKING=1
139 --set-last-working) SET_LAST_WORKING=1
141 --push-notes) PUSH_NOTES=1
144 DO_HOOK_REFRESH=true
145 postprocess 0
147 esac
148 shift
149 COMMAND="$1"
150 done
152 case "$COMMAND" in
153 apply)
154 EXTRA="-p0 --stat --apply --index --ignore-space-change --whitespace=error"
155 RELATIVIZE=0
157 clone|fetch|pull)
158 DO_HOOK_REFRESH=true
160 diff)
161 PAGER='--no-pager'
162 REPORT_REPOS=0
164 log)
165 if [ "$#" = "1" ] ; then
166 EXTRA='-1'
168 PAGER='--no-pager'
170 push)
171 if [ "$#" != "1" ] ; then
172 PUSH_ALL=1
175 esac
177 # absolutize the parameters first
178 unset FILES
179 FILESNUM=0
180 while shift ; do
181 PARAM="$1"
182 if [ -z "$PARAM" ] ; then
183 continue
184 elif [ "${PARAM:0:1}" = "-" ] ; then
185 if [ \( "$COMMAND" = "checkout" -a "$PARAM" = "-b" \) -o \
186 \( "$COMMAND" = "clone" -a "$PARAM" = "--reference" \) -o \
187 \( "$COMMAND" = "commit" -a "$PARAM" = "-m" \) -o \
188 \( "$COMMAND" = "commit" -a "$PARAM" = "-am" \) -o \
189 \( "$COMMAND" = "tag" -a "$PARAM" = "-m" \) ]
190 then
191 # params that take an argument
192 FILES[$FILESNUM]="$PARAM"
193 FILESNUM=$(($FILESNUM+1))
194 shift
195 FILES[$FILESNUM]="$1"
196 FILESNUM=$(($FILESNUM+1))
197 else
198 if [ "$COMMAND" = "commit" -a "$PARAM" = "-F" ]
199 then
200 shift
201 # this still needs some magic to handle relative paths
202 EXTRA="${EXTRA} -F ${1}"
203 else
204 [ "$COMMAND" = "commit" -a "$PARAM" = "--allow-empty" ] && ALLOW_EMPTY=1
205 FILES[$FILESNUM]="$PARAM"
206 FILESNUM=$(($FILESNUM+1))
209 else
210 if [ "$COMMAND" = "apply" ] ; then
211 grep -qs $'^+ *\t' "$PARAM" && {
212 echo "Patch '$PARAM' introduces tabs in indentation, aborting."
213 echo
214 echo "Please fix the patch (something like s/^\(+ *\)\t/\1 /) and try again."
215 echo
216 exit 1
220 # make the paths absolute
221 FILES[$FILESNUM]=$(perl -e 'use Cwd "abs_path"; print abs_path(shift);' "$PARAM")
222 if [ -z "${FILES[$FILESNUM]}" -o ! -e "${FILES[$FILESNUM]}" ] ; then
223 # it is probably not a file, but a tag name, or something
224 FILES[$FILESNUM]="$PARAM"
226 FILESNUM=$(($FILESNUM+1))
228 done
230 # do it!
231 DIRS="core $(cd $CLONEDIR ; ls)"
232 if [ "$COMMAND" = "clone" ] ; then
233 DIRS=$(cat "$COREDIR/bin/repo-list")
235 for REPO in $DIRS ; do
236 DIR="$CLONEDIR/$REPO"
237 NAME="$REPO"
238 if [ "$REPO" = "core" ] ; then
239 DIR="$COREDIR"
240 NAME="main repo"
243 if [ -d "$DIR" -a "z$PUSH_USER" != "z" ]; then
244 echo "setting up push url for $DIR"
245 (cd $DIR && git config remote.origin.pushurl "ssh://${PUSH_USER}@git.freedesktop.org/git/libreoffice/${REPO}")
246 elif [ -d "$DIR" -a "z$LAST_WORKING" != "z" ]; then
247 echo "fetching notes for $REPO ..."
248 (cd $DIR && git fetch origin 'refs/notes/*:refs/notes/*')
249 hash=`(cd $DIR && git log --pretty='%H %N' | grep 'win32 working build' | head -n1 | sed 's/ win32.*//')`
250 if test "z$hash" != "z"; then
251 echo "update to $hash"
252 (cd $DIR && git checkout $hash)
253 else
254 echo "Warning: missing known working note on repo $REPO"
256 elif [ -d "$DIR" -a "z$SET_LAST_WORKING" != "z" ]; then
257 echo "fetching notes for $REPO ..."
258 (cd $DIR && git fetch origin 'refs/notes/*:refs/notes/*')
259 (cd $DIR && git notes add -m 'win32 working build')
260 elif [ -d "$DIR" -a "z$PUSH_NOTES" != "z" ]; then
261 echo "pushing notes for $REPO ..."
262 (cd $DIR && git push origin 'refs/notes/*:refs/notes/*')
263 elif [ \( -d "$DIR" -a -d "$DIR"/.git \) -o \( "$COMMAND" = "clone" \) ] ; then
265 # executed in a subshell
266 if [ "$COMMAND" != "clone" ] ; then
267 cd "$DIR"
268 else
269 cd "$CLONEDIR"
272 # relativize the absolutized params again if we want to operate
273 # only on the files belonging to this exact repo
274 if [ "$RELATIVIZE" = "1" -a -n "$FILES" ] ; then
275 FILESNUM=0
276 INSERTNUM=0
277 PWD=$(pwd)
278 PWDLEN=$(pwd | wc -c)
279 for I in "${FILES[@]}" ; do
280 I="${I//@REPO@/${REPO}}"
281 unset FILES[$FILESNUM]
282 FILESNUM=$(($FILESNUM+1))
283 # filter out files that don't belong to this repo
284 if [ \( "${I:0:1}" = "/" \) -a \( "$COMMAND" != "clone" \) ] ; then
285 if [ "${I:0:$PWDLEN}" = "$PWD/" ] ; then
286 FILES[$INSERTNUM]="${I:$PWDLEN}"
287 INSERTNUM=$(($INSERTNUM+1))
289 else
290 FILES[$INSERTNUM]="$I"
291 INSERTNUM=$(($INSERTNUM+1))
293 done
294 [ "$INSERTNUM" = "0" ] && exit 0
297 # some extra params
298 case "$COMMAND" in
299 apply)
300 for I in * ; do
301 if [ -d "$I" ] ; then
302 EXTRA="$EXTRA --include=$I/*"
303 else
304 EXTRA="$EXTRA --include=$I"
306 done
308 commit)
309 if [ "$ALLOW_EMPTY" != "1" ] ; then
310 [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0
313 push)
314 if [ "$PUSH_ALL" != "1" ] ; then
315 [ -n "$(git rev-list origin..HEAD)" ] || exit 0
318 status)
319 LOCALCOMMITS="$(git rev-list origin..HEAD)"
320 if [ -z "$LOCALCOMMITS" ] ; then
321 [ -z "$(git diff-index --name-only HEAD --)" ] && exit 0
324 clone)
325 EXTRA="$(git config remote.origin.url)"
326 EXTRA=${EXTRA/core/${REPO}}
328 esac
330 # do it!
331 if [ "$COMMAND" != "clone" -o ! -d $DIR ] ; then
332 if [ "$REPORT_REPOS" = "1" -a "$COMMAND" != "grep" ] ; then
333 if [ "$REPORT_COMPACT" = "1" ] ; then
334 echo -n "${REPO}:"
335 else
336 echo "===== $NAME ====="
339 git $PAGER "$COMMAND" $EXTRA "${FILES[@]}"
340 RETURN=$?
343 # now we can change the dir in case of clone as well
344 if [ "$COMMAND" = "clone" ] ; then
345 cd $DIR
348 case "$COMMAND" in
349 pull|clone)
350 # update links
351 if [ "$DIR" != "$COREDIR" ]; then
352 for link in $(ls) ; do
353 if [ ! -e "$COREDIR/$link" ] ; then
354 if test -h "$COREDIR/$link"; then
355 rm "$COREDIR/$link"
356 echo -n "re-"
358 echo "creating missing link $link"
359 ln -s "$DIR/$link" "$COREDIR/$link"
361 done
364 status)
365 # git status returns error in some versions, clear that
366 RETURN=0
368 grep)
369 # git grep return an 'error' if nothing is found
370 # still we should continue grepping the other repos
371 RETURN=0
373 esac
374 if [ "$KEEP_GOING" = "1" ] ; then
375 RETURN=0
378 exit $RETURN
379 ) || postprocess $?
381 done
383 # Cleanup the broken links
384 if [ "$COMMAND" = "pull" ] ; then
385 for link in $(ls $COREDIR) ; do
386 if [ -h "$COREDIR/$link" -a ! -e "$COREDIR/$link" ]; then
387 echo "Removing broken link $link"
388 rm $COREDIR/$link
390 done
393 # warn
394 if [ "$COMMAND" = "apply" ] ; then
395 echo
396 echo "Don't forget to check the status & commit now ;-)"
397 echo
400 postprocess $?
402 # vi:set shiftwidth=4 expandtab: