[GRASS-SVN] r49716 - grass/trunk/scripts/g.extension
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue Dec 13 12:07:49 EST 2011
Author: martinl
Date: 2011-12-13 09:07:49 -0800 (Tue, 13 Dec 2011)
New Revision: 49716
Modified:
grass/trunk/scripts/g.extension/g.extension.py
Log:
g.extension: store modules.xml locally
update removal to read local XML file
add flag to list installed extensions (a)
Modified: grass/trunk/scripts/g.extension/g.extension.py
===================================================================
--- grass/trunk/scripts/g.extension/g.extension.py 2011-12-13 13:52:25 UTC (rev 49715)
+++ grass/trunk/scripts/g.extension/g.extension.py 2011-12-13 17:07:49 UTC (rev 49716)
@@ -59,23 +59,29 @@
#%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
#% suppress_required: yes
#%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
#% suppress_required: yes
#%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
#% suppress_required: yes
#%end
#%flag
+#% key: a
+#% description: List locally installed extension
+#% guisection: Print
+#% suppress_required: yes
+#%end
+#%flag
#% key: s
#% description: Install system-wide (may need system administrator rights)
#%end
@@ -140,10 +146,31 @@
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')
+ tree = etree.fromstring(fo.read())
+ 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
url = "http://grass.osgeo.org/addons/grass%s.xml" % grass.version()['version'].split('.')[0]
try:
@@ -168,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']:
@@ -199,7 +226,7 @@
continue
for line in f.readlines():
- # list modules
+ # list extensions
sline = pattern.search(line)
if not sline:
continue
@@ -227,7 +254,7 @@
return
for line in f.readlines():
- # list modules
+ # list extensions
sline = pattern.search(line)
if not sline:
continue
@@ -246,6 +273,132 @@
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'):
+ fo.write('%s<file>%s</file>\n' % \
+ (' ' * indent, fnode.text))
+ 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))
+
+ data = { 'name' : name,
+ 'desc' : mnode.find('description').text,
+ 'keyw' : mnode.find('keywords').text,
+ '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
@@ -285,8 +438,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()
@@ -296,6 +449,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'])
if not os.environ.has_key('GRASS_ADDON_PATH') or \
@@ -383,40 +538,56 @@
return grass.call(installCmd,
stdout = outdev)
+# 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))
+ fpath = os.path.join(options['prefix'], f)
try:
if force:
grass.verbose(fpath)
@@ -432,15 +603,15 @@
if err:
for e in err:
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)
@@ -498,14 +669,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']
@@ -523,6 +686,18 @@
if len(path_list) > 1:
grass.warning(_("GRASS_ADDON_PATH has more items, using first defined - '%s'") % path_list[0])
options['prefix'] = path_list[0]
+
+ # list available extensions
+ if flags['l'] or flags['c'] or flags['g']:
+ list_available_extensions()
+ 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':
More information about the grass-commit
mailing list