230 lines
7.3 KiB
Python
Executable File
230 lines
7.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
#
|
|
# Software License Agreement (BSD License)
|
|
#
|
|
# Copyright (c) 2009 Morgan Quigley
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
#
|
|
# * Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# * Redistributions in binary form must reproduce the above
|
|
# copyright notice, this list of conditions and the following
|
|
# disclaimer in the documentation and/or other materials provided
|
|
# with the distribution.
|
|
# * Neither the name of Stanford University nor the names of its
|
|
# contributors may be used to endorse or promote products derived
|
|
# from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
"""
|
|
usage: roslocate COMMAND PARAMS
|
|
|
|
currently supported commands:
|
|
|
|
roslocate describe PACKAGE-OR-STACK
|
|
roslocate svn PACKAGE-OR-STACK
|
|
roslocate repo PACKAGE-OR-STACK
|
|
roslocate type PACKAGE-OR-STACK
|
|
roslocate list
|
|
roslocate list-stacks
|
|
roslocate search KEYWORD
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import itertools
|
|
import time
|
|
import datetime
|
|
from xml.dom.minidom import parse
|
|
|
|
def get_text(nodes):
|
|
s = ""
|
|
for node in nodes:
|
|
for n2 in node.childNodes:
|
|
if n2.nodeType == n2.TEXT_NODE:
|
|
s = s + n2.data
|
|
return s
|
|
|
|
def get_cache_path():
|
|
try:
|
|
cpath = "%s/.roslocate_megamanifest.xml" % os.environ['ROS_ROOT']
|
|
f = open(cpath, 'a')
|
|
f.close()
|
|
return cpath
|
|
except IOError:
|
|
return "%s/.ros/roslocate_megamanifest.xml" % os.environ['HOME']
|
|
|
|
def download_megamanifest(cpath):
|
|
#print "downloading megamanifest to %s" % cpath
|
|
uris = ['http://ros.org/browse/megamanifest.xml']
|
|
for uri in uris:
|
|
#print "trying %s" % uri
|
|
if (os.system("wget %s -q -O %s" % (uri, cpath)) != 0):
|
|
#print "couldn't download from %s" % uri
|
|
continue
|
|
else:
|
|
os.utime(cpath, None)
|
|
return True
|
|
return False
|
|
|
|
def get_stack_cache_path():
|
|
try:
|
|
cpath = "%s/.roslocate_megastack.xml" % os.environ['ROS_ROOT']
|
|
f = open(cpath, 'a')
|
|
f.close()
|
|
return cpath
|
|
except IOError:
|
|
return "%s/.ros/roslocate_megastack.xml" % os.environ['HOME']
|
|
|
|
def download_megastack(cpath):
|
|
#print "downloading megastack to %s" % cpath
|
|
uris = ['http://ros.org/browse/megastack.xml']
|
|
for uri in uris:
|
|
#print "trying %s" % uri
|
|
if (os.system("wget %s -q -O %s" % (uri, cpath)) != 0):
|
|
#print "couldn't download from %s" % uri
|
|
continue
|
|
else:
|
|
os.utime(cpath, None)
|
|
return True
|
|
return False
|
|
|
|
def load_megamanifest():
|
|
cpath = get_cache_path()
|
|
if not os.path.exists(cpath) or os.path.getsize(cpath) == 0:
|
|
if not download_megamanifest(cpath):
|
|
print "couldn't download megamanifest..."
|
|
exit(1)
|
|
cache_age = datetime.datetime.now() - \
|
|
datetime.datetime.fromtimestamp(os.path.getmtime(cpath))
|
|
cache_age_secs = cache_age.seconds + cache_age.days * 3600 * 24
|
|
#print "cache is %d seconds old" % cache_age_secs
|
|
if cache_age_secs > 3600 * 8:
|
|
download_megamanifest(cpath)
|
|
return parse(cpath) # megamanifest
|
|
|
|
def load_megastack():
|
|
cpath = get_stack_cache_path()
|
|
if not os.path.exists(cpath) or os.path.getsize(cpath) == 0:
|
|
if not download_megastack(cpath):
|
|
print "couldn't download megastack..."
|
|
exit(1)
|
|
cache_age = datetime.datetime.now() - \
|
|
datetime.datetime.fromtimestamp(os.path.getmtime(cpath))
|
|
cache_age_secs = cache_age.seconds + cache_age.days * 3600 * 24
|
|
#print "cache is %d seconds old" % cache_age_secs
|
|
if cache_age_secs > 3600 * 8:
|
|
download_megastack(cpath)
|
|
return parse(cpath) # megastack
|
|
|
|
def usage():
|
|
print __doc__ % vars()
|
|
exit(1)
|
|
|
|
def describe(pkgs, stacks, name):
|
|
for pkg in pkgs:
|
|
if pkg.attributes['name'].value == name:
|
|
print ""
|
|
print "Package: %s"%name
|
|
print "Repository: %s " % pkg.attributes['repo_host'].value
|
|
print "License: %s" % get_text(pkg.getElementsByTagName('license')).strip()
|
|
print ""
|
|
print "Author(s): %s" % get_text(pkg.getElementsByTagName('author'))
|
|
print "Description: %s" % get_text(pkg.getElementsByTagName('description'))
|
|
print "ROS dependencies: %s" % (", ".join([dep.attributes['package'].value for dep in pkg.getElementsByTagName('depend')]))
|
|
print ""
|
|
return
|
|
|
|
for s in stacks:
|
|
if s.attributes['name'].value == name:
|
|
print ""
|
|
print "Stack: %s"%name
|
|
print "Repository: %s " % s.attributes['repo_host'].value
|
|
print "License: %s" % get_text(s.getElementsByTagName('license')).strip()
|
|
print ""
|
|
print "Author(s): %s" % get_text(s.getElementsByTagName('author'))
|
|
print "Description: %s" % get_text(s.getElementsByTagName('description'))
|
|
print "ROS dependencies: %s" % (", ".join([dep.attributes['stack'].value for dep in s.getElementsByTagName('depend')]))
|
|
print ""
|
|
return
|
|
|
|
print "No package or stack named %s found in the (known) public ROS repositories" % name
|
|
|
|
def type_(pkgs, stacks, name):
|
|
for e in pkgs:
|
|
if e.attributes['name'].value == name:
|
|
print "package"
|
|
return
|
|
for e in stacks:
|
|
if e.attributes['name'].value == name:
|
|
print "stack"
|
|
return
|
|
print "unknown"
|
|
|
|
def svn(pkgs, stacks, name):
|
|
for e in itertools.chain(pkgs, stacks):
|
|
if e.attributes['name'].value == name:
|
|
print "%s%s" % (e.attributes['repo_host'].value, e.attributes['path'].value)
|
|
return
|
|
|
|
def repo(pkgs, stacks, name):
|
|
for e in itertools.chain(pkgs, stacks):
|
|
if e.attributes['name'].value == name:
|
|
print "%s" % e.attributes['repo_host'].value
|
|
return
|
|
|
|
def list_all(elements):
|
|
for e in elements:
|
|
print e.attributes['name'].value
|
|
|
|
def search(pkgs, stacks, keyword):
|
|
for e in itertools.chain(pkgs, stacks):
|
|
desc = e.getElementsByTagName('description')
|
|
if get_text(desc).lower().find(keyword.lower()) > 0:
|
|
print e.attributes['name'].value
|
|
|
|
def roslocate_main():
|
|
if len(sys.argv) < 2:
|
|
usage()
|
|
mm = load_megamanifest()
|
|
pkgs = mm.getElementsByTagName('package')
|
|
|
|
ms = load_megastack()
|
|
stacks = ms.getElementsByTagName('stack')
|
|
|
|
if sys.argv[1] == "describe":
|
|
describe(pkgs, stacks, sys.argv[2])
|
|
elif sys.argv[1] == "svn":
|
|
svn(pkgs, stacks, sys.argv[2])
|
|
elif sys.argv[1] == "repo":
|
|
repo(pkgs, stacks, sys.argv[2])
|
|
elif sys.argv[1] == "list":
|
|
list_all(pkgs)
|
|
elif sys.argv[1] == "list-stacks":
|
|
list_all(stacks)
|
|
elif sys.argv[1] == "search":
|
|
search(pkgs, stacks, sys.argv[2])
|
|
elif sys.argv[1] == "type":
|
|
type_(pkgs, stacks, sys.argv[2])
|
|
else:
|
|
usage()
|
|
|
|
roslocate_main()
|
|
|