1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 from __future__ import with_statement
36
37 import roslib.rospack
38 import roslib.stacks
39 import roslib.manifest
40 import roslib.os_detect
41 import os
42 import sys
43 import subprocess
44 import types
45 import tempfile
46 import yaml
47 import time
48
49
50 import rosdep.base_rosdep
51 import rosdep.debian as debian
52 import rosdep.opensuse as opensuse
53 import rosdep.redhat as redhat
54 import rosdep.gentoo as gentoo
55 import rosdep.macports as macports
56 import rosdep.arch as arch
57 import rosdep.cygwin as cygwin
58 import rosdep.freebsd as freebsd
59
60
61 yaml.add_constructor(
62 u'tag:yaml.org,2002:float',
63 yaml.constructor.Constructor.construct_yaml_str)
64
66 - def __init__(self, os_name, os_version):
67 self.os_name = os_name
68 self.os_version = os_version
69 self._yaml_cache = {}
70 self._rosstack_depends_cache = {}
71 self._expanded_rosdeps = {}
72 self.rp = roslib.packages.ROSPackages()
73
75 if path in self._yaml_cache:
76 return self._yaml_cache[path]
77
78
79 if os.path.exists(path):
80 try:
81 f = open(path)
82 yaml_text = f.read()
83 f.close()
84 self._yaml_cache[path] = yaml.load(yaml_text)
85 return self._yaml_cache[path]
86
87 except yaml.YAMLError, exc:
88 print >> sys.stderr, "Failed parsing yaml while processing %s\n"%path, exc
89
90 self._yaml_cache[path] = {}
91 return {}
92
94 if stack in self._rosstack_depends_cache:
95 return self._rosstack_depends_cache[stack]
96
97 self._rosstack_depends_cache[stack] = roslib.rospack.rosstack_depends(stack)
98 return self._rosstack_depends_cache[stack]
99
101 if path in self._expanded_rosdeps:
102 return self._expanded_rosdeps[path]
103
104 yaml_dict = self.get_yaml(path)
105 expanded_rosdeps = {}
106 if not yaml_dict:
107 return expanded_rosdeps
108 for key in yaml_dict:
109 rosdep_entry = self.get_os_from_yaml(key, yaml_dict[key], path)
110 if not rosdep_entry:
111 continue
112 expanded_rosdeps[key] = rosdep_entry
113 self._expanded_rosdeps[path] = expanded_rosdeps
114 return expanded_rosdeps
115
117 """
118 @return The os (and version specific if required) local package name
119 """
120
121 if self.os_name in yaml_map:
122 return self.get_version_from_yaml(rosdep_name, yaml_map[self.os_name], source_path)
123 else:
124
125 return False
126
128 """
129 @return The os (and version specific if required) local package name
130 """
131 if type(os_specific) == type("String"):
132 return os_specific
133 else:
134 if self.os_version in os_specific.keys():
135 return os_specific[self.os_version]
136
137 return False
138
139
140
141
142
143
146
148 """
149 This is a class for interacting with rosdep.yaml files. It will
150 load all rosdep.yaml files in the current configuration at
151 startup. It has accessors to allow lookups into the rosdep.yaml
152 from rosdep name and returns the string from the yaml file for the
153 appropriate OS/version.
154
155 It uses the OSIndex class for OS detection.
156 """
157
158 - def __init__(self, os_name, os_version, package, yaml_cache):
159 """ Read all rosdep.yaml files found at the root of stacks in
160 the current environment and build them into a map."""
161 self.os_name = os_name
162 self.os_version = os_version
163 self.rosdep_map = {}
164 self.rosdep_source = {}
165 self.package = package
166 self.yaml_cache = yaml_cache
167
168
169
170 if package:
171 self.load_for_package(package, yaml_cache.rp)
172
173
174
176 try:
177 rosdep_dependent_packages = ros_package_proxy.depends([package])[package]
178
179 except KeyError, ex:
180 print "Depends Failed on package", ex
181 print " The errors was in ", ros_package_proxy.depends([package])
182 rosdep_dependent_packages = []
183
184 rosdep_dependent_packages.append(package)
185
186
187 paths = set()
188 for p in rosdep_dependent_packages:
189 stack = None
190 try:
191 stack = roslib.stacks.stack_of(p)
192 except roslib.packages.InvalidROSPkgException, ex:
193 print >> sys.stderr, "Failed to find stack for package [%s]"%p
194 pass
195 if stack:
196 try:
197 paths.add( os.path.join(roslib.stacks.get_stack_dir(stack), "rosdep.yaml"))
198 if "ROSDEP_DEBUG" in os.environ:
199 print "loading rosdeps from", os.path.join(roslib.stacks.get_stack_dir(stack), "rosdep.yaml")
200 except AttributeError, ex:
201 print "Stack [%s] could not be found"%(stack)
202 for s in self.yaml_cache.get_rosstack_depends(stack):
203 try:
204 paths.add( os.path.join(roslib.stacks.get_stack_dir(s), "rosdep.yaml"))
205 except AttributeError, ex:
206 print "Stack [%s] dependency of [%s] could not be found"%(s, stack)
207
208 else:
209 try:
210 paths.add( os.path.join(roslib.packages.get_pkg_dir(p), "rosdep.yaml"))
211 if "ROSDEP_DEBUG" in os.environ:
212 print "Package fallback, no parent stack found for package %s: loading rosdeps from"%p, os.path.join(roslib.packages.get_pkg_dir(p), "rosdep.yaml")
213 except roslib.packages.InvalidROSPkgException, ex:
214 print >> sys.stderr, "Failed to load rosdep.yaml for package [%s]:%s"%(p, ex)
215 pass
216 for path in paths:
217 self.insert_map(self.parse_yaml(path), path)
218 if "ROSDEP_DEBUG" in os.environ:
219 print "rosdep loading from file: %s got"%path, self.parse_yaml(path)
220
221
222
223 ros_home = roslib.rosenv.get_ros_home()
224 path = os.path.join(ros_home, "rosdep.yaml")
225 self.insert_map(self.parse_yaml(path), path, override=True)
226
227
228 - def insert_map(self, yaml_dict, source_path, override=False):
229 for key in yaml_dict:
230 rosdep_entry = yaml_dict[key]
231 if not rosdep_entry:
232 continue
233 if key in self.rosdep_source:
234
235
236 if override:
237 print >>sys.stderr, "ROSDEP_OVERRIDE: %s being overridden with %s from %s"%(key, yaml_dict[key], source_path)
238 self.rosdep_source[key].append("Overriding with "+source_path)
239 self.rosdep_map[key] = rosdep_entry
240 else:
241 if self.rosdep_map[key] == rosdep_entry:
242 self.rosdep_source[key].append(source_path)
243
244 pass
245 else:
246 cache_p = self.yaml_cache.get_os_from_yaml(key, yaml_dict[key], source_path)
247 raise RosdepException("""QUITTING: due to conflicting rosdep definitions, please resolve this conflict.
248 Rules for %s do not match:
249 \t%s [%s]
250 \t%s [%s]"""%(key, self.rosdep_map[key], self.rosdep_source[key][0], rosdep_entry, source_path))
251
252 else:
253 self.rosdep_source[key] = [source_path]
254 self.rosdep_map[key] = rosdep_entry
255
256
257
260
261
262
264 """ Lookup the OS specific packages or script from the
265 prebuilt maps."""
266
267 if rosdep in self.rosdep_map:
268 return self.rosdep_map[rosdep]
269 else:
270 print >> sys.stderr, "Failed to find rosdep %s for package %s on OS:%s version:%s"%(rosdep, self.package, self.os_name, self.os_version)
271 return False
272
274 return self.rosdep_map
275
276
278 if rosdep in self.rosdep_source:
279 return self.rosdep_source[rosdep]
280 else:
281 return []
282
283
284
285
286
287
289 - def __init__(self, packages, command = "rosdep", robust = False):
290 os_list = [debian.RosdepTestOS(), debian.Debian(), debian.Ubuntu(), debian.Mint(), opensuse.OpenSuse(), redhat.Fedora(), redhat.Rhel(), arch.Arch(), macports.Macports(), gentoo.Gentoo(), cygwin.Cygwin(), freebsd.FreeBSD()]
291
292 for o in os_list:
293 if not isinstance(o, rosdep.base_rosdep.RosdepBaseOS):
294 raise RosdepException("Class [%s] not derived from RosdepBaseOS"%o.__class__.__name__)
295
296 self.osi = roslib.os_detect.OSDetect(os_list)
297 self.packages = packages
298 self.rosdeps = roslib.packages.rosdeps_of(packages)
299 rp = roslib.packages.ROSPackages()
300 self.rosdeps = rp.rosdeps(packages)
301 self.robust = robust
302
303
304
306 m = roslib.manifest.load_manifest(package)
307 return [d.name for d in m.rosdeps]
308
309
311 if len(self.packages) == 0:
312 return ([], [])
313 native_packages = []
314 scripts = []
315 failed_rosdeps = []
316 yc = YamlCache(self.osi.get_name(), self.osi.get_version())
317 start_time = time.time()
318 if "ROSDEP_DEBUG" in os.environ:
319 print "Generating package list and scripts for %d rosdeps. This may take a few seconds..."%len(self.packages)
320 for p in self.packages:
321 rdlp = RosdepLookupPackage(self.osi.get_name(), self.osi.get_version(), p, yc)
322 for r in self.rosdeps[p]:
323 specific = rdlp.lookup_rosdep(r)
324 if specific:
325 if len(specific.split('\n')) == 1:
326 for pk in specific.split():
327 native_packages.append(pk)
328 else:
329 scripts.append(specific)
330 else:
331 failed_rosdeps.append(r)
332
333 if len(failed_rosdeps) > 0:
334 if not self.robust:
335 raise RosdepException("ABORTING: Rosdeps %s could not be resolved"%failed_rosdeps)
336 else:
337 print >> sys.stderr, "WARNING: Rosdeps %s could not be resolved"%failed_rosdeps
338
339 time_delta = (time.time() - start_time)
340 if "ROSDEP_DEBUG" in os.environ:
341 print "Done loading rosdeps in %f seconds, averaging %f per rosdep."%(time_delta, time_delta/len(self.packages))
342
343 return (list(set(native_packages)), list(set(scripts)))
344
347
354
356 native_packages = []
357 scripts = []
358 try:
359 native_packages, scripts = self.get_packages_and_scripts()
360 except RosdepException, e:
361 print >> sys.stderr, e
362 pass
363 undetected = self.osi.get_os().strip_detected_packages(native_packages)
364 return_str = ""
365 return_str_scripts = ""
366 if len(undetected) > 0:
367 return_str += "Did not detect packages: %s\n"%undetected
368 if len(scripts) > 0:
369 return_str_scripts += "The following scripts were not tested:\n"
370 for s in scripts:
371 return_str_scripts += s + '\n'
372 return return_str, return_str_scripts
373
375 packages = []
376 for p in roslib.packages.list_pkgs():
377 rosdeps_needed = self.get_rosdep0(p)
378 matches = [r for r in rosdep_args if r in rosdeps_needed]
379 for r in matches:
380 packages.append(p)
381
382 return packages
383
384 - def install(self, include_duplicates, default_yes):
385 with tempfile.NamedTemporaryFile() as fh:
386 script = self.generate_script(include_duplicates, default_yes)
387 fh.write(script)
388 fh.flush()
389
390 print "rosdep executing this script:\n{{{\n%s\n}}}"%script
391 p= subprocess.Popen(['bash', fh.name], stderr=subprocess.PIPE )
392 (out, err) = p.communicate()
393 if p.returncode != 0:
394 if err:
395 return "rosdep script failed with stderr \n{{{\n%s\n}}}"%err
396 else:
397 return "rosdep script failed without stderr output"
398 else:
399 return None
400
401 - def depdb(self, packages):
411
413 output = ""
414 locations = {}
415 rdlp = RosdepLookupPackage(self.osi.get_name(), self.osi.get_version(), None, YamlCache(self.osi.get_name(), self.osi.get_version()))
416
417 for r in rosdeps:
418 locations[r] = set()
419
420 path = os.path.join(roslib.rosenv.get_ros_home(), "rosdep.yaml")
421 rosdep_dict = rdlp.parse_yaml(path)
422 for r in rosdeps:
423 if r in rosdep_dict:
424 locations[r].add("Override:"+path)
425
426
427 for p in roslib.packages.list_pkgs():
428 path = os.path.join(roslib.packages.get_pkg_dir(p), "rosdep.yaml")
429 rosdep_dict = rdlp.parse_yaml(path)
430 for r in rosdeps:
431 if r in rosdep_dict:
432 addendum = ""
433 if roslib.stacks.stack_of(p):
434 addendum = "<<Unused due to package '%s' being in a stack.]]"%p
435 locations[r].add(">>" + path + addendum)
436
437
438 for s in roslib.stacks.list_stacks():
439 path = os.path.join(roslib.stacks.get_stack_dir(s), "rosdep.yaml")
440 rosdep_dict = rdlp.parse_yaml(path)
441 for r in rosdeps:
442 if r in rosdep_dict:
443 locations[r].add(path)
444
445 for rd in locations:
446 output += "%s defined in %s"%(rd, locations[rd])
447 return output
448