00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import os
00036 import sys
00037 import yaml
00038
00039 import rospkg
00040 from rospkg.distro import DistroStack
00041
00042 def load_distro_index(filename):
00043 """
00044 Load the distro index file, which is necessary for stacks that are installed in
00045 binary form instead of with the extra rosinstall meta fields
00046 """
00047 with open(filename, 'r') as f:
00048 return yaml.load(f)
00049
00050 def repo_stacks(repo, checkout_dir):
00051 if repo.is_released_stack:
00052
00053
00054 return [repo.name]
00055 else:
00056
00057 repo_dir = os.path.join(checkout_dir, repo.local_path)
00058 if not os.path.exists(repo_dir):
00059 sys.stderr.write("checkout [%s] doesn't exist\n"%(repo_dir))
00060 return []
00061
00062 stacks = rospkg.list_by_path('stack.xml', repo_dir, {})
00063 if repo.name == 'ros':
00064 stacks.append('ros')
00065 return stacks
00066
00067 def repo_packages(repo, checkout_dir):
00068 rosstack = rospkg.RosStack()
00069 if repo.is_released_stack:
00070
00071
00072 try:
00073 packages = rosstack.packages_of(repo.name)
00074 except:
00075 packages = []
00076 else:
00077
00078 repo_dir = os.path.join(checkout_dir, repo.local_path)
00079 packages = rospkg.list_by_path('manifest.xml', repo_dir, {})
00080 return packages
00081
00082 def load_repos_distro(distro_index_filename):
00083 """
00084 Load repository index for stacks that were installed via the
00085 distribution/debian. We have to fake repository data for these as
00086 we are not actually retrieving from the repository itself.
00087 """
00088 repos = []
00089
00090
00091
00092
00093 distro_index = load_distro_index(distro_index_filename)
00094 distro_name = distro_index['distro_name']
00095 for stack_name in distro_index['stacks']:
00096 stack_data= distro_index['stacks'][stack_name]
00097
00098
00099 if stack_name == 'ros':
00100 local_path = '/opt/ros/%s/ros'%(distro_name)
00101 else:
00102 local_path = '/opt/ros/%s/stacks/%s'%(distro_name, stack_name)
00103
00104 distro_stack = DistroStack(stack_name, stack_data['version'],
00105 distro_name, stack_data['rules'])
00106
00107
00108
00109 rosinstalls = {}
00110 vcs_config = distro_stack.vcs_config
00111 for branch_name in ['release', 'devel', 'distro']:
00112 rosinstalls[branch_name] = vcs_config.to_rosinstall(stack_name, branch_name, anonymous=True)[0]
00113 rosinstall = rosinstalls['release']
00114
00115
00116 vcs_type = rosinstall.keys()[0]
00117 vcs_uri = rosinstall[vcs_type]['uri']
00118
00119 print "loaded released stack repo: %s %s %s"%(stack_name, vcs_type, vcs_uri)
00120 print "released stack repo rosinstall: %s \n%s"%(stack_name, rosinstall)
00121
00122 r = Repo(stack_name, vcs_type, vcs_uri, rosinstall, local_path)
00123 r.aggregate_name = stack_data['repo']
00124 r.is_released_stack = True
00125 r.rosinstalls = rosinstalls.copy()
00126
00127 repos.append((stack_name, r))
00128 return repos
00129
00130 def load_repos(repos_filename, distro_index_filename):
00131 repos = load_repos_rosinstall(repos_filename)
00132 if distro_index_filename is not None:
00133 repos.extend(load_repos_distro(distro_index_filename))
00134 return repos
00135
00136 def load_repos_rosinstall(filename):
00137 """
00138 Load repository file, which is a rosinstall file with particular semantics
00139
00140 @return: ordered list of repositories
00141 @rtype: [(str, Repo)]
00142 """
00143 with open(filename) as f:
00144 data = yaml.load(f.read())
00145
00146 repos = []
00147
00148 for d in reversed(data):
00149 type_ = d.keys()[0]
00150 if type_ == 'other':
00151 continue
00152 config = d[type_]
00153
00154 if not 'uri' in config:
00155 continue
00156
00157 local_name = local_path = config['local-name']
00158 r = Repo(local_name, type_, config['uri'], d, local_path)
00159 if 'meta' in config and 'repo-name' in config['meta']:
00160 r.aggregate_name = config['meta']['repo-name']
00161 repos.append((local_name, r))
00162 return repos
00163
00164 class Repo(object):
00165
00166 def __init__(self, name, type_, uri, rosinstall, local_path):
00167 """
00168 @param name: repository name
00169 @param type_: repository VCS type
00170 @param uri: repository VCS uri
00171 @param rosinstall: default rosinstall dictionary configuration data
00172 @param local_path: checkout-relative path for repository
00173 @param aggregate_name: (optional) aggregate name if we are
00174 grouping several repositories under a single name.
00175 Defaults to name.
00176 """
00177 self.name = name
00178 self.type = type_
00179 self.uri = uri
00180
00181 self.rosinstall = rosinstall
00182 self.local_path = local_path
00183
00184
00185
00186 self.aggregate_name = None
00187 self.is_released_stack = False
00188
00189
00190
00191
00192 self.rosinstalls = None
00193
00194 _api_url = "http://ros.org/doc/api/"
00195 def package_link(package):
00196 return _api_url + package + "/html/"
00197 def stack_link(stack):
00198 return _api_url + stack + "/html/"
00199
00200 def safe_encode(d):
00201 d_copy = d.copy()
00202 for k, v in d_copy.iteritems():
00203 if isinstance(v, basestring):
00204 try:
00205 d[k] = v.encode("utf-8")
00206 except UnicodeDecodeError, e:
00207 print >> sys.stderr, "error: cannot encode value for key", k
00208 d[k] = ''
00209 elif type(v) == list:
00210 try:
00211 d[k] = [x.encode("utf-8") for x in v]
00212 except UnicodeDecodeError, e:
00213 print >> sys.stderr, "error: cannot encode value for key", k
00214 d[k] = []
00215 return d
00216