Module: Rock::Bundles
- Defined in:
- lib/rock/bundles.rb
Overview
Bundle support
In Rock, bundles are the packages in which system-related scripting, modelling and tools are included. They are meant to “bind together” the different components, packages and tool configuration from rock.
In practice, the bundle implementation is a thin wrapper on top of the rest of the rock
Bundle-aware scripts should simply use Bundle.initialize / Bundle.load instead of Orocos.initialize / Orocos.load. This is in principle enough to get bundle integration. All the rock-* tools on which bundle integration makes sense should do that already.
Defined Under Namespace
Modules: Scripts Classes: Bundle, BundleNotFound, NoBundle
Class Attribute Summary collapse
-
.log_dir_created ⇒ Object
readonly
Returns the value of attribute log_dir_created.
Class Method Summary collapse
- .change_default_options(args, defaults) ⇒ Object
-
.config_dir ⇒ String
The full path to the configuration directory.
-
.current_bundle ⇒ Object
Returns the Bundle object that represents the current bundle (i.e. the bundle in which we shoul be working).
-
.discover_dependencies(root_bundle) ⇒ Object
Returns an array containing both
root_bundle
and its dependencies (recursively). -
.each_bundle ⇒ Object
Enumerates the path to every registered bundle, starting with the one that has the highest priority.
-
.find_bundle_from_current_dir ⇒ Object
Find the bundle in which we are currently, if there is one.
-
.find_bundle_from_dir(dir) ⇒ Object
Find the bundle that contains the provided directory.
- .find_dir(*args) ⇒ Object
- .find_dirs(*args) ⇒ Object
- .find_file(*args) ⇒ Object
- .find_files(*args) ⇒ Object
- .find_files_in_dirs(*args) ⇒ Object
-
.get(task_name) ⇒ Object
Returns the task context referred to by
name
. -
.has_selected_bundle? ⇒ Boolean
Returns true if we have a selected bundle.
- .has_transformer? ⇒ Boolean
-
.initialize(*args) ⇒ Object
Initializes the bundle support, and initializes the orocos layer.
-
.is_bundle_path?(path) ⇒ Boolean
Returns true if
path
is the root of a bundle. - .is_ruby_script?(file) ⇒ Boolean
-
.load(required = false) ⇒ Object
Initializes the bundle support, and load all the available orocos info.
- .log_all(*args, &block) ⇒ Object
- .log_all_configuration(*args, &block) ⇒ Object
- .log_all_ports(*args, &block) ⇒ Object
- .log_dir ⇒ Object
- .method_missing(m, *args, &block) ⇒ Object
- .parse_script_options(argv) ⇒ Object
- .public_logs=(value) ⇒ Object
-
.public_logs? ⇒ Boolean
If true, the logs are going to be kept.
- .run(*args, &block) ⇒ Object
-
.select(directory) ⇒ Object
Select the bundle pointed-to by
directory
, or the bundle that contains directory. -
.select_current ⇒ Object
Selects the current bundle, regardless of the global configuration.
- .setup_search_paths(required = false) ⇒ Object
- .transformer_config=(file_name) ⇒ Object
- .watch(*args, &block) ⇒ Object
Class Attribute Details
.log_dir_created ⇒ Object (readonly)
Returns the value of attribute log_dir_created
551 552 553 |
# File 'lib/rock/bundles.rb', line 551 def log_dir_created @log_dir_created end |
Class Method Details
.change_default_options(args, defaults) ⇒ Object
502 503 504 505 506 507 508 509 510 511 |
# File 'lib/rock/bundles.rb', line 502 def self.(args, defaults) args = args.dup if args.last.kind_of?(Hash) with_defaults, other = Kernel. args.pop, defaults args.push(with_defaults.merge(other)) else args.push(defaults) end args end |
.config_dir ⇒ String
The full path to the configuration directory
This returns the full path to the directory that contains the configuration files, given the current bundle setup. It creates this directory if it does not exist
327 328 329 330 331 332 333 |
# File 'lib/rock/bundles.rb', line 327 def self.config_dir dir = File.join(current_bundle.path, 'config') if !File.directory?(dir) FileUtils.mkdir_p dir end dir end |
.current_bundle ⇒ Object
Returns the Bundle object that represents the current bundle (i.e. the bundle in which we shoul be working).
The current bundle can be defined, in order of priority, by:
-
the ROCK_BUNDLE environment variable, which should hold the name of the currently selected bundle
-
the current directory
-
if there is only one bundle found on this system, this bundle is returned
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/rock/bundles.rb', line 208 def self.current_bundle all_bundles = each_bundle.to_a if bundle_name = ENV['ROCK_BUNDLE'] bundle_path = File.(bundle_name) if bdl = all_bundles.find { |bdl| bdl.name == bundle_name || bdl.path == bundle_path } return bdl else raise ArgumentError, "cannot find currently selected bundle #{bundle_name} (available bundles are: #{all_bundles.map(&:name).sort.join(", ")})" end elsif current = find_bundle_from_current_dir return current elsif all_bundles.size == 1 return all_bundles.first else raise NoBundle, "no bundle found" end end |
.discover_dependencies(root_bundle) ⇒ Object
Returns an array containing both root_bundle
and its
dependencies (recursively). The array is returned in order of priority.
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/rock/bundles.rb', line 236 def self.discover_dependencies(root_bundle) all_bundles = self.each_bundle.to_a result = [] queue = [root_bundle] while !queue.empty? root = queue.shift result.delete(root) next if queue.include?(root) result << root root.each_dependency do |bundle_name| bdl = all_bundles.find { |b| b.name == bundle_name } if !bdl raise BundleNotFound.new(bundle_name), "could not find bundle #{bundle_name}, listed as dependency in #{root.name} (#{root.path})" end queue << bdl end end result end |
.each_bundle ⇒ Object
Enumerates the path to every registered bundle, starting with the one that has the highest priority
A directory is considered to be a bundle if it has a config/app.yml or config/bundle.yml file (even an empty one)
The bundles are enumerated following the ROCK_BUNDLE_PATH environment variable:
-
if a directory in ROCK_BUNDLE_PATH is pointing to a bundle, it gets added
-
if a directory in ROCK_BUNDLE_PATH is a directory that contains bundles, all the included bundles are added in an unspecified order
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/rock/bundles.rb', line 148 def self.each_bundle if !block_given? return enum_for(:each_bundle) end paths = (ENV['ROCK_BUNDLE_PATH'] || '').split(":") if paths.empty? if from_pwd = find_bundle_from_current_dir paths << from_pwd.path end end current_bundle = ENV['ROCK_BUNDLE'] if current_bundle && current_bundle.empty? current_bundle = nil end if current_bundle && Bundles.is_bundle_path?(current_bundle) yield(Bundle.new(File.(current_bundle))) end paths.each do |path| if !File.directory?(path) elsif is_bundle_path?(path) yield(Bundle.new(path)) else Dir.new(path).each do |f| f = File.join(path, f) if is_bundle_path?(f) yield(Bundle.new(f)) end end end end end |
.find_bundle_from_current_dir ⇒ Object
Find the bundle in which we are currently, if there is one
Returns nil if we are outside any bundle
96 97 98 |
# File 'lib/rock/bundles.rb', line 96 def self.find_bundle_from_current_dir find_bundle_from_dir(Dir.pwd) end |
.find_bundle_from_dir(dir) ⇒ Object
Find the bundle that contains the provided directory
Returns nil if there is none
125 126 127 128 129 130 131 132 |
# File 'lib/rock/bundles.rb', line 125 def self.find_bundle_from_dir(dir) # Look for a bundle in the parents of Dir.pwd bundle_dir = Pathname.new(dir). find_matching_parent { |curdir| is_bundle_path?(curdir.to_s) } if bundle_dir return Bundle.new(bundle_dir.to_s) end end |
.find_dir(*args) ⇒ Object
516 517 518 519 |
# File 'lib/rock/bundles.rb', line 516 def self.find_dir(*args) args = (args, :order => :specific_first) Roby.app.find_dir(*args) end |
.find_dirs(*args) ⇒ Object
513 514 515 |
# File 'lib/rock/bundles.rb', line 513 def self.find_dirs(*args) Roby.app.find_dirs(*args) end |
.find_file(*args) ⇒ Object
520 521 522 523 |
# File 'lib/rock/bundles.rb', line 520 def self.find_file(*args) args = (args, :order => :specific_first) Roby.app.find_file(*args) end |
.find_files(*args) ⇒ Object
524 525 526 |
# File 'lib/rock/bundles.rb', line 524 def self.find_files(*args) Roby.app.find_files(*args) end |
.find_files_in_dirs(*args) ⇒ Object
527 528 529 |
# File 'lib/rock/bundles.rb', line 527 def self.find_files_in_dirs(*args) Roby.app.find_files_in_dirs(*args) end |
.get(task_name) ⇒ Object
Returns the task context referred to by name
. Some common
configuration is done on this task, in particular the 'default'
configuration is applied if one is defined for the task's model
446 447 448 449 450 451 452 |
# File 'lib/rock/bundles.rb', line 446 def self.get(task_name) task = Orocos.name_service.get(task_name) if !defined?(Orocos::Log::TaskContext) || !task.kind_of?(Orocos::Log::TaskContext) Orocos.conf.apply(task, ['default']) end task end |
.has_selected_bundle? ⇒ Boolean
Returns true if we have a selected bundle
227 228 229 230 231 232 |
# File 'lib/rock/bundles.rb', line 227 def self.has_selected_bundle? current_bundle true rescue NoBundle false end |
.has_transformer? ⇒ Boolean
370 371 372 |
# File 'lib/rock/bundles.rb', line 370 def self.has_transformer? Orocos.respond_to?(:transformer) end |
.initialize(*args) ⇒ Object
Initializes the bundle support, and initializes the orocos layer
428 429 430 431 432 433 434 435 436 437 438 439 440 441 |
# File 'lib/rock/bundles.rb', line 428 def self.initialize(*args) # All logs are public by default in bundle scripts. This is overriden in rock-roby Roby.app.public_logs = Bundles.public_logs? if Orocos.initialized? raise ArgumentError, "Orocos.initialize has already been called. Do not call Orocos.initialize and Bundles.initialize multiple times" end self.load if Bundles.public_logs? Bundles.info "log files are going in #{Bundles.log_dir}" end Orocos.initialize(*args) end |
.is_bundle_path?(path) ⇒ Boolean
Returns true if path
is the root of a bundle
88 89 90 91 |
# File 'lib/rock/bundles.rb', line 88 def self.is_bundle_path?(path) File.file?(File.join(path, "config", "bundle.yml")) || File.file?(File.join(path, "config", "app.yml")) end |
.is_ruby_script?(file) ⇒ Boolean
418 419 420 421 422 423 424 425 |
# File 'lib/rock/bundles.rb', line 418 def self.is_ruby_script?(file) if file =~ /\.rb$/ return true else first_line = File.open(file).each_line.find { true } return first_line =~ /^#!.*ruby/ end end |
.load(required = false) ⇒ Object
Initializes the bundle support, and load all the available orocos info
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/rock/bundles.rb', line 336 def self.load(required = false) setup_search_paths require 'orocos' dir = Bundles.log_dir while !File.directory?(dir) Bundles.log_dir_created << dir dir = File.dirname(dir) end FileUtils.mkdir_p Bundles.log_dir Orocos.default_working_directory = Bundles.log_dir ENV['ORO_LOGFILE'] = File.join(Bundles.log_dir, "orocos.orocosrb-#{::Process.pid}.txt") Orocos.load # Load configuration directories find_dirs('config', 'orogen', :order => :specific_last, :all => true).each do |dir| Orocos.conf.load_dir(dir) end # Check if the transformer is available. It if is, set it up begin require 'transformer/runtime' Transformer.use_bundle_loader @transformer_config ||= "transforms.rb" if conf_file = find_file('config', @transformer_config, :order => :specific_first) Orocos.transformer.load_conf(conf_file) end rescue LoadError end end |
.log_all(*args, &block) ⇒ Object
454 455 456 |
# File 'lib/rock/bundles.rb', line 454 def self.log_all(*args, &block) Orocos.log_all(*args, &block) end |
.log_all_configuration(*args, &block) ⇒ Object
462 463 464 |
# File 'lib/rock/bundles.rb', line 462 def self.log_all_configuration(*args, &block) Orocos.log_all_configuration(*args, &block) end |
.log_all_ports(*args, &block) ⇒ Object
458 459 460 |
# File 'lib/rock/bundles.rb', line 458 def self.log_all_ports(*args, &block) Orocos.log_all_ports(*args, &block) end |
.log_dir ⇒ Object
530 531 532 533 534 535 536 |
# File 'lib/rock/bundles.rb', line 530 def self.log_dir if Roby.app.created_log_dir? Roby.app.log_dir else Roby.app.find_and_create_log_dir end end |
.method_missing(m, *args, &block) ⇒ Object
379 380 381 382 383 384 385 |
# File 'lib/rock/bundles.rb', line 379 def self.method_missing(m, *args, &block) if Orocos.respond_to?(m) Orocos.send(m, *args, &block) else super end end |
.parse_script_options(argv) ⇒ Object
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
# File 'lib/rock/bundles.rb', line 470 def self.(argv) parser = OptionParser.new do |opt| opt.on('--gdb[=TASKS]', String, 'run the comma-separated list of deployments using gdbserver. Do all if no arguments are given.') do |gdb| Bundles::Scripts.gdb = gdb.split(',') end opt.on('--gdb-options=OPTIONS', String, 'comma-separated list of options that should be passed to the started gdbserver') do || Bundles::Scripts. = .split(',') end opt.on('--gdb-port=PORT', Integer, 'base port that should be used for gdbserver') do |gdb_port| Orocos::Process.gdb_base_port = gdb_port end opt.on('--valgrind[=TASKS]', String, 'run the comma-separated list of deployments using valgrind. Do all if no arguments are given.') do |valgrind| Bundles::Scripts.valgrind = valgrind.split(',') end opt.on('--valgrind-options=OPTIONS', String, 'comma-separated list of options that should be passed to the started valgrind') do || Bundles::Scripts. = .split(',') end opt.on('--wait=SECONDS', Integer, 'wait that many seconds before deciding that a process will not start') do |wait| Bundles::Scripts.wait = wait end opt.on("-h", "--help", "this help message") do puts opt exit 0 end if block_given? yield(opt) end end parser.parse(argv) end |
.public_logs=(value) ⇒ Object
544 545 546 |
# File 'lib/rock/bundles.rb', line 544 def self.public_logs=(value) @public_logs = value end |
.public_logs? ⇒ Boolean
If true, the logs are going to be kept. Otherwise, the log folder is going to be deleted on shutdown
540 541 542 |
# File 'lib/rock/bundles.rb', line 540 def self.public_logs? @public_logs end |
.run(*args, &block) ⇒ Object
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/rock/bundles.rb', line 387 def self.run(*args, &block) # Process the given options to override some of the defaults = if args.last.kind_of?(Hash) args.pop else Hash.new end = [:gdb, :gdb_options, :valgrind, :valgrind_options, :wait] cmdline_wrappers, = Kernel. , .each do |key| if value = Scripts.send(key) cmdline_wrappers[key] = value end end , = Kernel. , :output => "%m-%p.txt" = .merge(cmdline_wrappers) = .merge() args.push() if has_transformer? && Transformer.broadcaster_name Orocos.transformer.start_broadcaster(Transformer.broadcaster_name, ) do Orocos.run(*args, &block) end else Orocos.run(*args, &block) end end |
.select(directory) ⇒ Object
Select the bundle pointed-to by directory
, or the bundle that
contains directory
Raises ArgumentError if directory
is not part of a bundle
114 115 116 117 118 119 120 |
# File 'lib/rock/bundles.rb', line 114 def self.select(directory) if current_bundle = find_bundle_from_dir(Dir.pwd) ENV['ROCK_BUNDLE'] = current_bundle.path else raise ArgumentError, "#{directory} is not contained in a bundle" end end |
.select_current ⇒ Object
Selects the current bundle, regardless of the global configuration
Raises ArgumentError if the current directory is not a bundle, or is not contained in one
This is meant to be mostly used in test scripts
106 107 108 |
# File 'lib/rock/bundles.rb', line 106 def self.select_current select(Dir.pwd) end |
.setup_search_paths(required = false) ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
# File 'lib/rock/bundles.rb', line 259 def self.setup_search_paths(required = false) current_bundle = begin self.current_bundle rescue NoBundle if required raise end end if current_bundle selected_bundles = discover_dependencies(current_bundle) if @selected_bundles != selected_bundles Bundles.info "Active bundles: #{selected_bundles.map(&:name).join(", ")}" end else current_bundle = Bundle.new(Dir.pwd) selected_bundles = [current_bundle] if @selected_bundles != selected_bundles Bundles.info "No bundle currently selected" end end selected_bundles.reverse.each do |b| $LOAD_PATH.unshift(b.path) unless $LOAD_PATH.include?(b.path) end # Check if the current directory is in a bundle, and if it is the # case if that bundle is part of the selection. Otherwise, issue a # warning if current_dir = find_bundle_from_current_dir if !selected_bundles.any? { |b| b.path == current_dir.path } sel = each_bundle.find { |b| b.path == current_dir.path } Bundles.warn "" Bundles.warn "The bundle that contains the current directory," Bundles.warn " #{current_dir.name} (#{current_dir.path})" Bundles.warn "is not currently active" Bundles.warn "" if sel Bundles.warn "Did you mean to do bundles-sel #{sel.name} ?" else Bundles.warn "Did you mean to do bundles-sel #{current_dir.path} ?" end end end Roby.app.app_dir = current_bundle.path Roby.app.load_config_yaml rock_bundle_path = (ENV['ROCK_BUNDLE_PATH'] || "").split(":") Roby.app.search_path = selected_bundles.map(&:path) + rock_bundle_path selected_bundles.reverse.each do |b| libdir = File.join(b.path, "lib") if File.directory?(libdir) $LOAD_PATH.unshift libdir end end @selected_bundles = selected_bundles end |
.transformer_config=(file_name) ⇒ Object
374 375 376 377 |
# File 'lib/rock/bundles.rb', line 374 def self.transformer_config=(file_name) # sets the name of the transformer file found in the config folder @transformer_config = file_name end |
.watch(*args, &block) ⇒ Object
466 467 468 |
# File 'lib/rock/bundles.rb', line 466 def self.watch(*args, &block) Orocos.watch(*args, &block) end |