[GRASS-SVN] r49720 - grass/branches/develbranch_6/gui/scripts
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Dec 13 13:11:33 EST 2011
Author: martinl
Date: 2011-12-13 10:11:33 -0800 (Tue, 13 Dec 2011)
New Revision: 49720
Modified:
grass/branches/develbranch_6/gui/scripts/g.extension.py
Log:
g.extensions.py: sync with trunk (store local xml files + list installed extensions) - r49716
Modified: grass/branches/develbranch_6/gui/scripts/g.extension.py
===================================================================
--- grass/branches/develbranch_6/gui/scripts/g.extension.py 2011-12-13 18:10:58 UTC (rev 49719)
+++ grass/branches/develbranch_6/gui/scripts/g.extension.py 2011-12-13 18:11:33 UTC (rev 49720)
@@ -56,20 +56,25 @@
#%flag
#% key: l
-#% description: List available modules in the GRASS Addons SVN repository
+#% description: List available extensions in the GRASS Addons SVN repository
#% guisection: Print
#%end
#%flag
#% key: c
-#% description: List available modules in the GRASS Addons SVN repository including module description
+#% description: List available extensions in the GRASS Addons SVN repository including module description
#% guisection: Print
#%end
#%flag
#% key: g
-#% description: List available modules in the GRASS Addons SVN repository (shell script style)
+#% description: List available extensions in the GRASS Addons SVN repository (shell script style)
#% guisection: Print
#%end
#%flag
+#% key: a
+#% description: List locally installed extension
+#% guisection: Print
+#%end
+#%flag
#% key: s
#% description: Install system-wide (may need system administrator rights)
#%end
@@ -135,8 +140,35 @@
return c
-# list modules (read XML file from grass.osgeo.org/addons)
-def list_available_modules():
+
+# list installed extensions
+def get_installed_extensions(force = False):
+ fXML = os.path.join(options['prefix'], 'modules.xml')
+ if not os.path.exists(fXML):
+ if force:
+ write_xml_modules(fXML)
+ else:
+ grass.warning(_("No metadata file available"))
+ return []
+
+ # read XML file
+ fo = open(fXML, 'r')
+ try:
+ tree = etree.fromstring(fo.read())
+ except:
+ os.remove(fXML)
+ write_xml_modules(fXML)
+ return []
+ fo.close()
+
+ ret = list()
+ for tnode in tree.findall('task'):
+ ret.append(tnode.get('name'))
+
+ return ret
+
+# list extensions (read XML file from grass.osgeo.org/addons)
+def list_available_extensions():
mlist = list()
# try to download XML metadata file first
@@ -163,14 +195,14 @@
else:
print name
except HTTPError:
- return list_available_modules_svn()
+ return list_available_extensions_svn()
return mlist
-# list modules (scan SVN repo)
-def list_available_modules_svn():
+# list extensions (scan SVN repo)
+def list_available_extensions_svn():
mlist = list()
- grass.message(_('Fetching list of modules from GRASS-Addons SVN (be patient)...'))
+ grass.message(_('Fetching list of extensions from GRASS-Addons SVN (be patient)...'))
pattern = re.compile(r'(<li><a href=".+">)(.+)(</a></li>)', re.IGNORECASE)
if flags['c']:
@@ -194,7 +226,7 @@
continue
for line in f.readlines():
- # list modules
+ # list extensions
sline = pattern.search(line)
if not sline:
continue
@@ -222,7 +254,7 @@
return
for line in f.readlines():
- # list modules
+ # list extensions
sline = pattern.search(line)
if not sline:
continue
@@ -241,6 +273,147 @@
grass.message(_("Path to the source code:"))
sys.stderr.write('%s\n' % os.path.join(tmpdir, options['extension']))
+# write out meta-file
+def write_xml_modules(name, tree = None):
+ fo = open(name, 'w')
+ version = grass.version()['version'].split('.')[0]
+ fo.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+ fo.write('<!DOCTYPE task SYSTEM "grass-addons.dtd">\n')
+ fo.write('<addons version="%s">\n' % version)
+
+ if tree is not None:
+ for tnode in tree.findall('task'):
+ indent = 4
+ fo.write('%s<task name="%s">\n' % (' ' * indent, tnode.get('name')))
+ indent += 4
+ fo.write('%s<description>%s</description>\n' % \
+ (' ' * indent, tnode.find('description').text))
+ fo.write('%s<keywords>%s</keywords>\n' % \
+ (' ' * indent, tnode.find('keywords').text))
+ bnode = tnode.find('binary')
+ if bnode is not None:
+ fo.write('%s<binary>\n' % (' ' * indent))
+ indent += 4
+ for fnode in bnode.findall('file'):
+ fpath = fnode.text.split(os.path.sep)
+ if not flags['s']: # tidy citizen hacks
+ if fpath[0] in ('bin', 'scripts'):
+ del fpath[0]
+ if fpath[0] == 'man':
+ fpath.insert(0, 'docs')
+
+ fo.write('%s<file>%s</file>\n' % \
+ (' ' * indent, os.path.join(options['prefix'],
+ os.path.sep.join(fpath))))
+ indent -= 4
+ fo.write('%s</binary>\n' % (' ' * indent))
+ libgisRev = grass.version()['libgis_revision']
+ fo.write('%s<libgis revision="%s" />\n' % \
+ (' ' * indent, libgisRev))
+ indent -= 4
+ fo.write('%s</task>\n' % (' ' * indent))
+
+ fo.write('</addons>\n')
+ fo.close()
+
+# update local meta-file when installing new extension
+def install_extension_xml():
+ # read metadata from remote server
+ url = "http://grass.osgeo.org/addons/grass%s.xml" % grass.version()['version'].split('.')[0]
+ data = None
+ try:
+ f = urlopen(url)
+ tree = etree.fromstring(f.read())
+ for mnode in tree.findall('task'):
+ name = mnode.get('name')
+ if name != options['extension']:
+ continue
+
+ fList = list()
+ bnode = mnode.find('binary')
+ windows = sys.platform == 'win32'
+ if bnode is not None:
+ for fnode in bnode.findall('file'):
+ path = fnode.text.split('/')
+ if windows:
+ if path[0] == 'bin':
+ path[-1] += '.exe'
+ if path[0] == 'scripts':
+ path[-1] += '.py'
+ fList.append(os.path.sep.join(path))
+
+ desc = mnode.find('description').text
+ if not desc:
+ desc = ''
+ keyw = mnode.find('keywords').text
+ if not keyw:
+ keyw = ''
+
+ data = { 'name' : name,
+ 'desc' : desc,
+ 'keyw' : keyw,
+ 'files' : fList,
+ }
+ except HTTPError:
+ grass.error(_("Unable to read metadata file from the remote server"))
+
+ if not data:
+ grass.warning(_("No metadata available"))
+ return
+
+ fXML = os.path.join(options['prefix'], 'modules.xml')
+ # create an empty file if not exists
+ if not os.path.exists(fXML):
+ write_xml_modules(fXML)
+
+ # read XML file
+ fo = open(fXML, 'r')
+ tree = etree.fromstring(fo.read())
+ fo.close()
+
+ # update tree
+ tnode = None
+ for node in tree.findall('task'):
+ if node.get('name') == options['extension']:
+ tnode = node
+ break
+
+ if tnode is not None:
+ # update existing node
+ dnode = tnode.find('description')
+ if dnode is not None:
+ dnode.text = data['desc']
+ knode = tnode.find('keywords')
+ if knode is not None:
+ knode.text = data['keyw']
+ bnode = tnode.find('binary')
+ if bnode is not None:
+ tnode.remove(bnode)
+ bnode = etree.Element('binary')
+ for f in data['files']:
+ fnode = etree.Element('file')
+ fnode.text = f
+ bnode.append(fnode)
+ tnode.append(bnode)
+ else:
+ # create new node for task
+ tnode = etree.Element('task', attrib = { 'name' : data['name'] })
+ dnode = etree.Element('description')
+ dnode.text = data['desc']
+ tnode.append(dnode)
+ knode = etree.Element('keywords')
+ knode.text = data['keyw']
+ tnode.append(knode)
+ bnode = etree.Element('binary')
+ for f in data['files']:
+ fnode = etree.Element('file')
+ fnode.text = f
+ bnode.append(fnode)
+ tnode.append(bnode)
+ tree.append(tnode)
+
+ write_xml_modules(fXML, tree)
+
# install extension on MS Windows
def install_extension_win():
### TODO: do not use hardcoded url
@@ -280,8 +453,8 @@
if not gisbase:
grass.fatal(_('$GISBASE not defined'))
- if grass.find_program(options['extension'], ['--help']):
- grass.warning(_("Extension <%s> already installed. Will be updated...") % options['extension'])
+ if options['extension'] in get_installed_extensions(force = True):
+ grass.warning(_("Extension <%s> already installed. Re-installing...") % options['extension'])
if sys.platform == "win32":
ret = install_extension_win()
@@ -291,6 +464,8 @@
if ret != 0:
grass.warning(_('Installation failed, sorry. Please check above error messages.'))
else:
+ grass.message(_("Updating metadata file..."))
+ install_extension_xml()
grass.message(_("Installation of <%s> successfully finished") % options['extension'])
# cleanup build cruft
@@ -420,41 +595,56 @@
# if empty, rmdir bin, etc, man, scripts
for d in ('bin', 'etc', os.path.join('man', 'man1'), 'man', 'scripts'):
remove_empty_dir(os.path.join(options['prefix'], d))
+
+# update local meta-file when removing existing extension
+def remove_extension_xml():
+ fXML = os.path.join(options['prefix'], 'modules.xml')
+ if not os.path.exists(fXML):
+ return
+ # read XML file
+ fo = open(fXML, 'r')
+ tree = etree.fromstring(fo.read())
+ fo.close()
+
+ tnode = None
+ for node in tree.findall('task'):
+ if node.get('name') == options['extension']:
+ tnode = node
+ break
+
+ if tnode is not None:
+ tree.remove(tnode)
+
+ write_xml_modules(fXML, tree)
+
# remove existing extension (reading XML file)
def remove_extension(force = False):
- # try to download XML metadata file first
- url = "http://grass.osgeo.org/addons/grass%s.xml" % grass.version()['version'].split('.')[0]
+ # try to read XML metadata file first
+ fXML = os.path.join(options['prefix'], 'modules.xml')
name = options['extension']
+ if name not in get_installed_extensions():
+ grass.warning(_("Extension <%s> not found") % name)
+
if force:
grass.verbose(_("List of removed files:"))
else:
grass.info(_("Files to be removed (use flag 'f' to force removal):"))
- try:
- f = urlopen(url)
+ if os.path.exists(fXML):
+ f = open(fXML, 'r')
tree = etree.fromstring(f.read())
flist = []
for task in tree.findall('task'):
if name == task.get('name', default = '') and \
task.find('binary') is not None:
for f in task.find('binary').findall('file'):
- fname = f.text
- if fname:
- fpath = fname.split('/')
- if sys.platform == 'win32':
- if fpath[0] == 'bin':
- fpath[-1] += '.exe'
- if fpath[0] == 'scripts':
- fpath[-1] += '.py'
-
- flist.append(fpath)
+ flist.append(f.text)
if flist:
removed = False
err = list()
- for f in flist:
- fpath = os.path.join(options['prefix'], os.path.sep.join(f))
+ for fpath in flist:
try:
if force:
grass.verbose(fpath)
@@ -472,13 +662,15 @@
grass.error(e)
else:
remove_extension_std(force)
- except HTTPError:
+ else:
remove_extension_std(force)
if force:
+ grass.message(_("Updating metadata file..."))
+ remove_extension_xml()
grass.message(_("Extension <%s> successfully uninstalled.") % options['extension'])
else:
- grass.warning(_("Extension <%s> not removed. "
+ grass.warning(_("Extension <%s> not removed.\n"
"Re-run '%s' with 'f' flag to force removal") % (options['extension'], 'g.extension'))
# remove exising extension (using standard files layout)
@@ -537,14 +729,6 @@
if sys.platform != "win32":
check_progs()
- # list available modules
- if flags['l'] or flags['c'] or flags['g']:
- list_available_modules()
- return 0
- else:
- if not options['extension']:
- grass.fatal(_('You need to define an extension name or use -l'))
-
# define path
if flags['s']:
options['prefix'] = os.environ['GISBASE']
@@ -563,6 +747,18 @@
grass.warning(_("GRASS_ADDON_PATH has more items, using first defined - '%s'") % path_list[0])
options['prefix'] = path_list[0]
+ # list available modules
+ if flags['l'] or flags['c'] or flags['g']:
+ list_available_modules()
+ return 0
+ elif flags['a']:
+ grass.message(_("List of installed extensions:"))
+ print os.linesep.join(get_installed_extensions())
+ return 0
+ else:
+ if not options['extension']:
+ grass.fatal(_('You need to define an extension name or use -l'))
+
if flags['d']:
if options['operation'] != 'add':
grass.warning(_("Flag 'd' is relevant only to 'operation=add'. Ignoring this flag."))
More information about the grass-commit
mailing list