3
############################################################################
6
# AUTHOR(S): Markus Neteler, Hamish Bowman, and Martin Landa
7
# PURPOSE: Tool to download and install extensions from GRASS Addons SVN into
8
# local GRASS installation
9
# COPYRIGHT: (C) 2009-2012 by Markus Neteler, and the GRASS Development Team
11
# This program is free software under the GNU General Public
12
# License (>=v2). Read the file COPYING that comes with GRASS
15
#############################################################################
18
#% label: Tool to maintain GRASS extensions in local GRASS installation.
19
#% description: Downloads, installs extensions from GRASS Addons SVN repository into local GRASS installation or removes installed extensions.
20
#% keywords: general, extensions
26
#% description: Name of extension to install/remove
33
#% description: Operation to be performed
35
#% options: add,remove
42
#% description: SVN Addons repository URL
44
#% answer: http://svn.osgeo.org/grass/grass-addons/grass6
50
#% description: Prefix where to install extension
51
#% answer: $GRASS_ADDON_PATH
56
#% description: List available modules in the GRASS Addons SVN repository
61
#% description: Install system-wide (may need system administrator rights)
65
#% description: Install system-wide using sudo
69
if [ -z "$GISBASE" ] ; then
70
echo "You must be in GRASS GIS to run this program." >&2
74
if [ "$1" != "@ARGS_PARSED@" ] ; then
75
exec g.parser "$0" "$@"
79
# check if we have the grass include and Make files
80
dpkg-query -l grass-dev | grep '^ii' > /dev/null 2> /dev/null
81
if [ $? -ne 0 ] ; then
82
g.message -w "This module requires the \"grass-dev\" package"
88
SVNURL_ADDONS="$GIS_OPT_SVNURL"
89
MODULE="$GIS_OPT_EXTENSION"
90
PREFIX="$GIS_OPT_PREFIX"
93
#make a temporary directory
94
TMPDIR="`g.tempfile pid=$$`"
95
if [ $? -ne 0 ] || [ -z "$TMPDIR" ] ; then
96
g.message -e "Unable to create temporary files"
102
#TODO: combine all these checks into a single for loop
104
# check if we have the svn client
105
if [ ! -x "`which svn`" ] ; then
106
g.message -e "svn client required. Please install Subversion first."
110
# check if we have the make program
111
if [ ! -x "`which make`" ] ; then
112
g.message -e "The 'make' program is required. Please install first."
116
# check if we have the "install" program
117
if [ ! -x "`which install`" ] ; then
118
g.message -e "The 'install' program is required. Please install first."
122
# check if we have wget or curl
123
if [ ! -x "`which wget`" ] ; then
124
if [ ! -x "`which curl`" ] ; then
125
g.message -e "Either 'wget' or 'curl' is required, please install one first"
128
g.message -v "Using CURL for downloading data."
132
g.message -v "Using WGET for downloading data."
136
expand_module_class_name()
139
if [ "$1" = "d" ] ; then
141
elif [ "$1" = "db" ] ; then
143
elif [ "$1" = "g" ] ; then
145
elif [ "$1" = "i" ] ; then
147
elif [ "$1" = "m" ] ; then
149
elif [ "$1" = "ps" ] ; then
151
# elif [ "$1" = "p" ] ; then
153
elif [ "$1" = "r" ] ; then
155
elif [ "$1" = "r3" ] ; then
157
# elif [ "$1" = "s" ] ; then
159
elif [ "$1" = "v" ] ; then
166
if [ `echo "$MODULE" | grep -c '/'` -eq 0 ] ; then
167
CLASSCHAR=`echo $MODULE | cut -d'.' -f1`
168
MODULECLASS=`expand_module_class_name $CLASSCHAR`
170
# handle vector/adehabitat/ or just vector/v.module ...
171
TOPLEVEL=`echo $MODULE | cut -d'/' -f1`
172
MODULECLASS="$TOPLEVEL"
173
MODULE=`echo "$MODULE" | sed -e "s+^$MODULECLASS/++"`
177
list_available_modules()
180
g.message message="Fetching list of modules from GRASS-Addons SVN (be patient)..."
181
for d in d db g i m ps p r r3 v ; do
182
MODCLASS=`expand_module_class_name $d`
185
if [ "$USE_WGET" ] ; then
186
wget --quiet -nv "$SVNURL_ADDONS/$MODCLASS" -O index.html
188
curl -silent --location "$SVNURL_ADDONS/$MODCLASS" -o index.html
190
grep '<li>' index.html 2> /dev/null | grep -v '\.\.' | \
191
cut -d'"' -f2 | sed 's+/$++g' >> list_$$.txt
194
grep -v 'Makefile' list_$$.txt
196
# so why save to a file at all instead of cat'ing directly?
201
if [ -n "$TMPDIR" ] ; then
206
if [ $GIS_FLAG_L -eq 1 ] ; then
207
list_available_modules
212
if [ -z "$GIS_OPT_EXTENSION" -a $GIS_FLAG_L -eq 0 ] ; then
213
g.message message="You need to define an extension name or use -l"
218
if [ "$PREFIX" = '$GISBASE' ] || [ $GIS_FLAG_S -eq 1 ] || [ $GIS_FLAG_U -eq 1 ] ; then
222
# just to make later tests happy
223
if [ $GIS_FLAG_S -eq 0 ] && [ $GIS_FLAG_U -eq 1 ] ; then
227
elif [ "$PREFIX" = '$GRASS_ADDON_PATH' ] ; then
228
if [ -z "$GRASS_ADDON_PATH" ] ; then
229
g.message -w message="GRASS_ADDON_PATH is not defined, installing to ~/.grass6/addons/"
230
ADDON_PATH_EMPTY=true
231
#g.message message="Suggest you set GRASS_ADDON_PATH and GRASS_ADDON_ETC to ..."
232
## will GRASS_ADDON_ETC help for man/ and docs/ ?
233
## maybe have g.manual search in GRASS_ADDON_ETC/../ ? :-/
234
mkdir -p ~/.grass6/addons
235
GRASS_ADDON_PATH1=~/.grass6/addons
237
GRASS_ADDON_PATH1=`echo "$GRASS_ADDON_PATH" | cut -f1 -d:`
239
PREFIX="$GRASS_ADDON_PATH1"
243
if [ -d "$PREFIX" ] ; then
246
g.message -w "'$PREFIX' does not exist. Creating ..."
248
if [ $? -ne 0 ] || [ ! -d "$PREFIX" ] ; then
249
g.message -e "Unable to create '$PREFIX' directory"
255
if [ ! -w "$PREFIX" -a "$SYSADMIN" -ne 1 ] ; then
256
g.message -e "'$PREFIX' is not writable (do you have suitable file-system permissions?)"
260
# make doesn't like spaces in path names, issue a warning if we see one:
261
GLOOM="The build which follows will likely fail."
262
if [ `echo "$GISBASE" | grep -c ' '` -gt 0 ] ; then
263
g.message -w "The GRASS program path: [$GISBASE] contains a space. $GLOOM"
265
if [ `echo "$PREFIX" | grep -c ' '` -gt 0 ] ; then
266
g.message -w "The specified install path: [$PREFIX] contains a space. $GLOOM"
268
if [ `echo "$TMPDIR" | grep -c ' '` -gt 0 ] ; then
269
# a problem because $MAPSET/.tmp/ is used as the compile dir
270
g.message -w "The path to your GIS data: [`g.gisenv GISDBASE`] may contain a space. $GLOOM"
274
if [ "$GIS_OPT_OPERATION" = "remove" ] ; then
275
g.message message="Removing <$MODULE>..."
277
if test -f "$MYINST_DIR/bin/$MODULE" ; then
278
rm -f "$MYINST_DIR/bin/$MODULE"
280
if test -f "$MYINST_DIR/scripts/$MODULE" ; then
281
rm -f "$MYINST_DIR/scripts/$MODULE"
283
if test -e "$MYINST_DIR/$MODULE" ; then
284
rm -f "$MYINST_DIR/$MODULE"
286
if test -f "$MYINST_DIR/docs/html/$MODULE.html" ; then
287
rm -f "$MYINST_DIR/docs/html/$MODULE.html"
288
#also html/$MODULE*.jpg, html/$MODULE*.png
290
if test -f "$MYINST_DIR/man/man1/$MODULE.1" ; then
291
rm -f "$MYINST_DIR/man/man1/$MODULE.1"
293
if test -f "$MYINST_DIR/docs/man/man1/$MODULE.1" ; then
294
rm -f "$MYINST_DIR/docs/man/man1/$MODULE.1"
301
g.message -d "svn co [$SVNURL_ADDONS]/[$MODULECLASS]/[$MODULE]"
304
g.message message="Fetching <$MODULE> from GRASS-Addons SVN (be patient)..."
305
svn co "$SVNURL_ADDONS/$MODULECLASS/$MODULE"
307
if [ $? -ne 0 ] ; then
308
g.message -e message="GRASS Add-on $MODULE not found in repository or no network connection or another problem"
313
g.message message="Compiling <$MODULE>..."
315
if [ -n "$MACHTYPE" ] ; then
316
DIST_DIR="dist.$MACHTYPE"
317
elif [ -x "`which arch`" ] ; then
318
DIST_DIR="dist.`arch`"
320
DIST_DIR="dist.unknown"
323
# set up a demolocation so --html-description works
324
GVER=`echo "$GRASS_VERSION" | cut -f1,2 -d'.' | sed -e 's/\.//'`
325
mkdir -p "$TMPDIR/$DIST_DIR/demolocation/PERMANENT"
326
cat << EOF > "$TMPDIR/$DIST_DIR/demolocation/.grassrc$GVER"
327
GISDBASE: $TMPDIR/$DIST_DIR
328
LOCATION_NAME: demolocation
330
GRASS_DB_ENCODING: utf-8
335
# $INST_NOW helps compile and install modules directly into $(INST_DIR)
336
# without having to install whole distribution even after modifying only
337
# one module. It will update both $(GRASS_HOME)/dist.$(ARCH) and $(INST_DIR).
338
# see $GISBASE/include/Make/Grass.make
339
### actually this may not be needed anymore ###
343
make MODULE_TOPDIR="$GISBASE" \
344
ARCH_INC="'-I$GISBASE/include' '-I$MYINST_DIR/include' '-I$TMPDIR/$DIST_DIR/include'" \
345
ARCH_LIBPATH="'-L$GISBASE/lib' '-L$MYINST_DIR/lib' '-L$TMPDIR/$DIST_DIR/lib'" \
346
ARCH_LIBDIR="$GISBASE/lib" \
347
ARCH_DISTDIR="$TMPDIR/$DIST_DIR" \
348
ARCH_BINDIR="$TMPDIR/$DIST_DIR/bin"
350
if [ $? -ne 0 ] ; then
351
g.message -e message="Compilation failed, sorry. Please check above error messages."
355
g.message message="Installing <$MODULE>..."
358
if [ `grep -c 'default: script' "$TMPDIR/$MODULE/Makefile"` -eq 1 ] ; then
363
# can we write? Install dir present?
364
if test ! -d "$MYINST_DIR" ; then
365
mkdir -p "$MYINST_DIR"
367
if test ! -d "$MYINST_DIR/$PROGTYPE" ; then
368
mkdir -p "$MYINST_DIR/$PROGTYPE"
370
if test ! -d "$MYINST_DIR/docs/html" ; then
371
mkdir -p "$MYINST_DIR/docs/html"
373
if test ! -d "$MYINST_DIR/man/man1" ; then
374
mkdir -p "$MYINST_DIR/man/man1"
377
if [ $SYSADMIN -eq 1 ] ; then
378
if test -f "$MYINST_DIR/$PROGTYPE/$MODULE" ; then
379
if [ "$GIS_FLAG_U" -eq 1 ] ; then
380
g.message "You may need to enter your password to remove an earlier copy of $MODULE:"
381
sudo rm -f "$MYINST_DIR/$PROGTYPE/$MODULE"
383
rm -f "$MYINST_DIR/$PROGTYPE/$MODULE"
384
if [ $? -ne 0 ] ; then
385
g.message -w "Removal failed. Do you have suitable file-system permissions?"
389
if [ $GIS_FLAG_U -eq 1 ] ; then
390
g.message "You may need to enter your password to install $MODULE:"
392
sudo make MODULE_TOPDIR="$GISBASE" \
393
ARCH_DISTDIR="$TMPDIR/$DIST_DIR" \
394
INST_DIR="$MYINST_DIR" install
396
make MODULE_TOPDIR="$GISBASE" \
397
ARCH_DISTDIR="$TMPDIR/$DIST_DIR" \
398
INST_DIR="$MYINST_DIR" \
402
if test -f "$MYINST_DIR/$PROGTYPE/$MODULE" ; then
403
g.message -w "Replacing previously built <$MODULE>"
404
rm -f "$MYINST_DIR/$PROGTYPE/$MODULE"
407
# ? ETC="$MYINST_DIR/etc"
408
make MODULE_TOPDIR="$GISBASE" \
409
ARCH_DISTDIR="$TMPDIR/$DIST_DIR" \
410
INST_DIR="$MYINST_DIR" install
413
if [ $? -ne 0 ] ; then
414
g.message -e message="Installation failed, sorry. Please check above error messages."
419
# clean up python installs, since PythonScript.make doesn't exist yet
420
if [ -e "$MYINST_DIR/$PROGTYPE/$MODULE.py" ] ; then
421
# drop the .py from python scripts
422
mv "$MYINST_DIR/$PROGTYPE/$MODULE.py" "$MYINST_DIR/$PROGTYPE/$MODULE"
423
mv "$MYINST_DIR/man/man1/$MODULE.py.1" "$MYINST_DIR/man/man1/$MODULE.1"
424
mv "$MYINST_DIR/docs/html/$MODULE.py.html" "$MYINST_DIR/docs/html/$MODULE.html"
427
if [ ! -x "$MYINST_DIR/$PROGTYPE/$MODULE" ] ; then
428
g.message -e "Module did not install properly"
433
if [ "$MYINST_DIR" = "$GRASS_ADDON_PATH1" ] || [ "$MYINST_DIR" = ~/.grass6/addons ] ; then
434
# move bin/ and script/ into ../, then rmdir if they are empty
435
mv "$MYINST_DIR/$PROGTYPE/$MODULE" "$MYINST_DIR/"
436
if [ `ls -a "$MYINST_DIR/$PROGTYPE" | wc -l` -le 2 ] ; then
437
rmdir "$MYINST_DIR/$PROGTYPE"
439
# and move the man page into docs/
440
if [ -e "$MYINST_DIR/man/man1/$MODULE.1" ] ; then
441
mkdir -p "$MYINST_DIR/docs/man/man1"
442
mv "$MYINST_DIR/man/man1/$MODULE.1" "$MYINST_DIR/docs/man/man1/"
443
if [ `ls -a "$MYINST_DIR/man/man1" | wc -l` -le 2 ] ; then
444
rmdir "$MYINST_DIR/man/man1"
445
if [ `ls -a "$MYINST_DIR/man" | wc -l` -le 2 ] ; then
446
rmdir "$MYINST_DIR/man"
456
g.message message="Installation of <$MODULE> in <$MYINST_DIR> complete."
458
if [ -n "$ADDON_PATH_EMPTY" ] && [ "$GIS_FLAG_S" -eq 0 ] ; then
460
g.message -w message='This add-on module will not function until you set the GRASS_ADDON_PATH environment variable (see "g.manual variables")'