autoproj 1.6.2 → 1.7.0.b1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +22 -1
- data/Rakefile +1 -1
- data/bin/autoproj +19 -6
- data/doc/guide/src/autoproj_bootstrap +68 -64
- data/lib/autoproj/autobuild.rb +38 -2
- data/lib/autoproj/base.rb +23 -1
- data/lib/autoproj/cmdline.rb +135 -61
- data/lib/autoproj/manifest.rb +441 -188
- data/lib/autoproj/options.rb +2 -2
- data/lib/autoproj/osdeps.rb +11 -10
- data/lib/autoproj/version.rb +1 -1
- metadata +19 -16
data/lib/autoproj/manifest.rb
CHANGED
@@ -86,7 +86,7 @@ module Autoproj
|
|
86
86
|
def initialize(type, url, options)
|
87
87
|
@type, @url, @options = type, url, options
|
88
88
|
if type != "none" && type != "local" && !Autobuild.respond_to?(type)
|
89
|
-
raise ConfigError, "version control #{type} is unknown to autoproj"
|
89
|
+
raise ConfigError.new, "version control #{type} is unknown to autoproj"
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -94,6 +94,17 @@ module Autoproj
|
|
94
94
|
@type == 'local'
|
95
95
|
end
|
96
96
|
|
97
|
+
def ==(other_vcs)
|
98
|
+
return false if !other_vcs.kind_of?(VCSDefinition)
|
99
|
+
if local?
|
100
|
+
other_vcs.local? && url == other.url
|
101
|
+
elsif !other_vcs.local?
|
102
|
+
this_importer = create_autobuild_importer
|
103
|
+
other_importer = other_vcs.create_autobuild_importer
|
104
|
+
this_importer.repository_id == other_importer.repository_id
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
97
108
|
def self.to_absolute_url(url, root_dir = nil)
|
98
109
|
# NOTE: we MUST use nil as default argument of root_dir as we don't
|
99
110
|
# want to call Autoproj.root_dir unless completely necessary
|
@@ -119,7 +130,7 @@ module Autoproj
|
|
119
130
|
else
|
120
131
|
desc = "#{type}:#{url}"
|
121
132
|
if !options.empty?
|
122
|
-
desc = "#{desc} #{options.map { |key, value| "#{key}=#{value}" }.join(" ")}"
|
133
|
+
desc = "#{desc} #{options.to_a.sort_by { |key, _| key.to_s }.map { |key, value| "#{key}=#{value}" }.join(" ")}"
|
123
134
|
end
|
124
135
|
desc
|
125
136
|
end
|
@@ -127,12 +138,21 @@ module Autoproj
|
|
127
138
|
end
|
128
139
|
|
129
140
|
def self.vcs_definition_to_hash(spec)
|
141
|
+
options = Hash.new
|
142
|
+
if spec.size == 1 && spec.keys.first =~ /auto_imports$/
|
143
|
+
# The user probably wrote
|
144
|
+
# - string
|
145
|
+
# auto_imports: false
|
146
|
+
options['auto_imports'] = spec.values.first
|
147
|
+
spec = spec.keys.first.split(" ").first
|
148
|
+
end
|
149
|
+
|
130
150
|
if spec.respond_to?(:to_str)
|
131
151
|
vcs, *url = spec.to_str.split ':'
|
132
152
|
spec = if url.empty?
|
133
153
|
source_dir = File.expand_path(File.join(Autoproj.config_dir, spec))
|
134
154
|
if !File.directory?(source_dir)
|
135
|
-
raise ConfigError, "'#{spec.inspect}' is neither a remote source specification, nor a local source definition"
|
155
|
+
raise ConfigError.new, "'#{spec.inspect}' is neither a remote source specification, nor a local source definition"
|
136
156
|
end
|
137
157
|
|
138
158
|
Hash[:type => 'local', :url => source_dir]
|
@@ -143,7 +163,7 @@ module Autoproj
|
|
143
163
|
|
144
164
|
spec, vcs_options = Kernel.filter_options spec, :type => nil, :url => nil
|
145
165
|
|
146
|
-
return spec.merge(vcs_options)
|
166
|
+
return spec.merge(vcs_options).merge(options)
|
147
167
|
end
|
148
168
|
|
149
169
|
# Autoproj configuration files accept VCS definitions in three forms:
|
@@ -155,7 +175,7 @@ module Autoproj
|
|
155
175
|
def self.normalize_vcs_definition(spec)
|
156
176
|
spec = vcs_definition_to_hash(spec)
|
157
177
|
if !(spec[:type] && (spec[:type] == 'none' || spec[:url]))
|
158
|
-
raise ConfigError, "the source specification #{spec.inspect} misses either the VCS type or an URL"
|
178
|
+
raise ConfigError.new, "the source specification #{spec.inspect} misses either the VCS type or an URL"
|
159
179
|
end
|
160
180
|
|
161
181
|
spec, vcs_options = Kernel.filter_options spec, :type => nil, :url => nil
|
@@ -191,7 +211,7 @@ module Autoproj
|
|
191
211
|
else
|
192
212
|
value = single_expansion(value, definitions)
|
193
213
|
if contains_expansion?(value)
|
194
|
-
raise ConfigError, "some expansions are not defined in #{value.inspect}"
|
214
|
+
raise ConfigError.new, "some expansions are not defined in #{value.inspect}"
|
195
215
|
end
|
196
216
|
value
|
197
217
|
end
|
@@ -219,22 +239,43 @@ module Autoproj
|
|
219
239
|
result
|
220
240
|
end
|
221
241
|
|
222
|
-
# A
|
242
|
+
# A package set is a version control repository which contains general
|
223
243
|
# information with package version control information (source.yml file),
|
224
244
|
# package definitions (.autobuild files), and finally definition of
|
225
245
|
# dependencies that are provided by the operating system (.osdeps file).
|
226
|
-
class
|
246
|
+
class PackageSet
|
247
|
+
attr_reader :manifest
|
227
248
|
# The VCSDefinition object that defines the version control holding
|
228
249
|
# information for this source. Local package sets (i.e. the ones that are not
|
229
250
|
# under version control) use the 'local' version control name. For them,
|
230
251
|
# local? returns true.
|
231
252
|
attr_accessor :vcs
|
253
|
+
|
254
|
+
# If this package set has been imported from another package set, this
|
255
|
+
# is the other package set object
|
256
|
+
attr_accessor :imported_from
|
257
|
+
|
258
|
+
# If true, this package set has been loaded because another set imports
|
259
|
+
# it. If false, it is loaded explicitely by the user
|
260
|
+
def explicit?; !@imported_from end
|
261
|
+
|
232
262
|
attr_reader :source_definition
|
233
263
|
attr_reader :constants_definitions
|
234
264
|
|
265
|
+
# Sets the auto_imports flag. See #auto_imports?
|
266
|
+
attr_writer :auto_imports
|
267
|
+
# If true (the default), imports listed in this package set will be
|
268
|
+
# automatically loaded by autoproj
|
269
|
+
def auto_imports?; !!@auto_imports end
|
270
|
+
|
235
271
|
# Create this source from a VCSDefinition object
|
236
|
-
def initialize(vcs)
|
272
|
+
def initialize(manifest, vcs)
|
273
|
+
@manifest = manifest
|
237
274
|
@vcs = vcs
|
275
|
+
|
276
|
+
@provides = Set.new
|
277
|
+
@imports = Array.new
|
278
|
+
@auto_imports = true
|
238
279
|
end
|
239
280
|
|
240
281
|
# True if this source has already been checked out on the local autoproj
|
@@ -250,6 +291,47 @@ module Autoproj
|
|
250
291
|
!File.exists?(File.join(raw_local_dir, "init.rb"))
|
251
292
|
end
|
252
293
|
|
294
|
+
# Create a PackageSet instance from its description as found in YAML
|
295
|
+
# configuration files
|
296
|
+
def self.from_spec(manifest, spec, load_description)
|
297
|
+
spec = Autoproj.vcs_definition_to_hash(spec)
|
298
|
+
options, vcs_spec = Kernel.filter_options spec, :auto_imports => true
|
299
|
+
|
300
|
+
# Look up for short notation (i.e. not an explicit hash). It is
|
301
|
+
# either vcs_type:url or just url. In the latter case, we expect
|
302
|
+
# 'url' to be a path to a local directory
|
303
|
+
vcs_spec = Autoproj.expand(vcs_spec, manifest.constant_definitions)
|
304
|
+
vcs_def = Autoproj.normalize_vcs_definition(vcs_spec)
|
305
|
+
|
306
|
+
source = PackageSet.new(manifest, vcs_def)
|
307
|
+
source.auto_imports = options[:auto_imports]
|
308
|
+
if load_description
|
309
|
+
if source.present?
|
310
|
+
source.load_description_file
|
311
|
+
else
|
312
|
+
raise InternalError, "cannot load description file as it has not been checked out yet"
|
313
|
+
end
|
314
|
+
else
|
315
|
+
# Try to load just the name from the source.yml file
|
316
|
+
source.load_minimal
|
317
|
+
end
|
318
|
+
|
319
|
+
source
|
320
|
+
end
|
321
|
+
|
322
|
+
def repository_id
|
323
|
+
if local?
|
324
|
+
local_dir
|
325
|
+
else
|
326
|
+
importer = vcs.create_autobuild_importer
|
327
|
+
if importer.respond_to?(:repository_id)
|
328
|
+
importer.repository_id
|
329
|
+
else
|
330
|
+
vcs.to_s
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
253
335
|
# Remote sources can be accessed through a hidden directory in
|
254
336
|
# $AUTOPROJ_ROOT/.remotes, or through a symbolic link in
|
255
337
|
# autoproj/remotes/
|
@@ -259,9 +341,9 @@ module Autoproj
|
|
259
341
|
# For local sources, is simply returns the path to the source directory.
|
260
342
|
def raw_local_dir
|
261
343
|
if local?
|
262
|
-
|
344
|
+
File.expand_path(vcs.url)
|
263
345
|
else
|
264
|
-
File.join(Autoproj.remotes_dir,
|
346
|
+
File.expand_path(File.join(Autoproj.remotes_dir, vcs.to_s.gsub(/[^\w]/, '_')))
|
265
347
|
end
|
266
348
|
end
|
267
349
|
|
@@ -291,19 +373,12 @@ module Autoproj
|
|
291
373
|
end
|
292
374
|
end
|
293
375
|
|
294
|
-
# A name generated from the VCS url
|
295
|
-
def automatic_name
|
296
|
-
vcs.to_s.gsub(/[^\w]/, '_')
|
297
|
-
end
|
298
|
-
|
299
376
|
# Returns the source name
|
300
377
|
def name
|
301
|
-
if @
|
302
|
-
@source_definition['name'] || automatic_name
|
303
|
-
elsif @name
|
378
|
+
if @name
|
304
379
|
@name
|
305
380
|
else
|
306
|
-
|
381
|
+
vcs.to_s
|
307
382
|
end
|
308
383
|
end
|
309
384
|
|
@@ -318,34 +393,54 @@ module Autoproj
|
|
318
393
|
|
319
394
|
source_file = File.join(raw_local_dir, "source.yml")
|
320
395
|
if !File.exists?(source_file)
|
321
|
-
raise ConfigError, "source #{vcs.type}:#{vcs.url} should have a source.yml file, but does not"
|
396
|
+
raise ConfigError.new, "source #{vcs.type}:#{vcs.url} should have a source.yml file, but does not"
|
322
397
|
end
|
323
398
|
|
324
|
-
|
325
|
-
|
326
|
-
rescue ArgumentError => e
|
327
|
-
raise ConfigError, "error in #{source_file}: #{e.message}"
|
399
|
+
source_definition = Autoproj.in_file(source_file, ArgumentError) do
|
400
|
+
YAML.load(File.read(source_file))
|
328
401
|
end
|
329
402
|
|
330
403
|
if !source_definition || !source_definition['name']
|
331
|
-
raise ConfigError, "#{source_file}
|
404
|
+
raise ConfigError.new(source_file), "in #{source_file}: missing a 'name' field"
|
332
405
|
end
|
333
406
|
|
334
407
|
source_definition
|
335
408
|
end
|
336
409
|
|
337
|
-
# Load and validate the
|
338
|
-
def
|
410
|
+
# Load and validate the self-contained information from the YAML hash
|
411
|
+
def load_minimal
|
412
|
+
# If @source_definition is set, it means that load_description_file
|
413
|
+
# has been called and that therefore all information has already
|
414
|
+
# been parsed
|
339
415
|
definition = @source_definition || raw_description_file
|
340
416
|
@name = definition['name']
|
341
417
|
|
342
418
|
if @name !~ /^[\w_\.-]+$/
|
343
|
-
raise ConfigError,
|
419
|
+
raise ConfigError.new(source_file),
|
420
|
+
"in #{source_file}: invalid source name '#{@name}': source names can only contain alphanumeric characters, and .-_"
|
344
421
|
elsif @name == "local"
|
345
|
-
raise ConfigError,
|
422
|
+
raise ConfigError.new(source_file),
|
423
|
+
"in #{source_file}: the name 'local' is a reserved name"
|
424
|
+
end
|
425
|
+
|
426
|
+
@provides = (definition['provides'] || Set.new).to_set
|
427
|
+
@imports = (definition['imports'] || Array.new).map do |set_def|
|
428
|
+
pkg_set = Autoproj.in_file(source_file) do
|
429
|
+
PackageSet.from_spec(manifest, set_def, false)
|
430
|
+
end
|
431
|
+
|
432
|
+
pkg_set.imported_from = self
|
433
|
+
pkg_set
|
346
434
|
end
|
347
435
|
|
348
436
|
rescue InternalError
|
437
|
+
# This ignores raw_description_file error if the package set is not
|
438
|
+
# checked out yet
|
439
|
+
end
|
440
|
+
|
441
|
+
# Yields the imports this package set declares, as PackageSet instances
|
442
|
+
def each_imported_set(&block)
|
443
|
+
@imports.each(&block)
|
349
444
|
end
|
350
445
|
|
351
446
|
# Path to the source.yml file
|
@@ -353,21 +448,22 @@ module Autoproj
|
|
353
448
|
File.join(local_dir, 'source.yml')
|
354
449
|
end
|
355
450
|
|
356
|
-
# Load the source.yml file
|
357
|
-
#
|
358
|
-
#
|
451
|
+
# Load the source.yml file and resolves all information it contains.
|
452
|
+
#
|
453
|
+
# This for instance requires configuration options to be defined. Use
|
454
|
+
# PackageSet#load_minimal to load only self-contained information
|
359
455
|
def load_description_file
|
456
|
+
if @source_definition
|
457
|
+
return
|
458
|
+
end
|
459
|
+
|
360
460
|
@source_definition = raw_description_file
|
361
|
-
|
461
|
+
load_minimal
|
362
462
|
|
363
|
-
|
364
463
|
# Compute the definition of constants
|
365
|
-
|
464
|
+
Autoproj.in_file(source_file) do
|
366
465
|
constants = source_definition['constants'] || Hash.new
|
367
466
|
@constants_definitions = Autoproj.resolve_constant_definitions(constants)
|
368
|
-
|
369
|
-
rescue ConfigError => e
|
370
|
-
raise ConfigError, "#{File.join(local_dir, "source.yml")}: #{e.message}", e.backtrace
|
371
467
|
end
|
372
468
|
end
|
373
469
|
|
@@ -399,15 +495,19 @@ module Autoproj
|
|
399
495
|
#
|
400
496
|
# The returned value is a VCSDefinition object.
|
401
497
|
def version_control_field(package_name, section_name, validate = true)
|
498
|
+
if !source_definition
|
499
|
+
raise InternalError, "source #{name} has not been loaded"
|
500
|
+
end
|
501
|
+
|
402
502
|
urls = source_definition['urls'] || Hash.new
|
403
503
|
urls['HOME'] = ENV['HOME']
|
404
504
|
|
405
505
|
all_vcs = source_definition[section_name]
|
406
506
|
if all_vcs
|
407
507
|
if all_vcs.kind_of?(Hash)
|
408
|
-
raise ConfigError, "wrong format for the #{section_name} section, you forgot the '-' in front of the package names"
|
508
|
+
raise ConfigError.new, "wrong format for the #{section_name} section, you forgot the '-' in front of the package names"
|
409
509
|
elsif !all_vcs.kind_of?(Array)
|
410
|
-
raise ConfigError, "wrong format for the #{section_name} section"
|
510
|
+
raise ConfigError.new, "wrong format for the #{section_name} section"
|
411
511
|
end
|
412
512
|
end
|
413
513
|
|
@@ -449,7 +549,7 @@ module Autoproj
|
|
449
549
|
if spec == "none"
|
450
550
|
spec = { :type => "none" }
|
451
551
|
else
|
452
|
-
raise ConfigError, "invalid VCS specification '#{name}: #{spec}'"
|
552
|
+
raise ConfigError.new, "invalid VCS specification '#{name}: #{spec}'"
|
453
553
|
end
|
454
554
|
end
|
455
555
|
end
|
@@ -480,8 +580,6 @@ module Autoproj
|
|
480
580
|
end
|
481
581
|
vcs_spec
|
482
582
|
end
|
483
|
-
rescue ConfigError => e
|
484
|
-
raise ConfigError, "#{e.message} in #{source_file}", e.backtrace
|
485
583
|
end
|
486
584
|
|
487
585
|
# Returns the VCS definition for +package_name+ as defined in this
|
@@ -508,18 +606,29 @@ module Autoproj
|
|
508
606
|
end
|
509
607
|
end
|
510
608
|
end
|
609
|
+
|
610
|
+
# True if this package set provides the given package set name. I.e. if
|
611
|
+
# it has this name or the name is listed in the "replaces" field of
|
612
|
+
# source.yml
|
613
|
+
def provides?(name)
|
614
|
+
name == self.name ||
|
615
|
+
provides.include?(name)
|
616
|
+
end
|
511
617
|
end
|
512
618
|
|
513
|
-
# Specialization of the
|
514
|
-
class
|
515
|
-
def initialize
|
516
|
-
super(Autoproj.normalize_vcs_definition(:type => 'local', :url => Autoproj.config_dir))
|
619
|
+
# Specialization of the PackageSet class for the overrides listed in autoproj/
|
620
|
+
class LocalPackageSet < PackageSet
|
621
|
+
def initialize(manifest)
|
622
|
+
super(manifest, Autoproj.normalize_vcs_definition(:type => 'local', :url => Autoproj.config_dir))
|
517
623
|
end
|
518
624
|
|
519
625
|
def name
|
520
626
|
'local'
|
521
627
|
end
|
522
|
-
def
|
628
|
+
def load_minimal
|
629
|
+
end
|
630
|
+
def repository_id
|
631
|
+
'local'
|
523
632
|
end
|
524
633
|
|
525
634
|
def source_file
|
@@ -535,10 +644,8 @@ module Autoproj
|
|
535
644
|
def raw_description_file
|
536
645
|
path = source_file
|
537
646
|
if File.file?(path)
|
538
|
-
|
539
|
-
|
540
|
-
rescue ArgumentError => e
|
541
|
-
raise ConfigError, "error in #{source_file}: #{e.message}"
|
647
|
+
data = Autoproj.in_file(path, ArgumentError) do
|
648
|
+
YAML.load(File.read(path)) || Hash.new
|
542
649
|
end
|
543
650
|
data['name'] = 'local'
|
544
651
|
data
|
@@ -548,12 +655,16 @@ module Autoproj
|
|
548
655
|
end
|
549
656
|
end
|
550
657
|
|
658
|
+
# DEPRECATED. For backward-compatibility only.
|
659
|
+
Source = PackageSet
|
660
|
+
# DEPRECATED. For backward-compatibility only.
|
661
|
+
LocalSource = LocalPackageSet
|
662
|
+
|
551
663
|
PackageDefinition = Struct.new :autobuild, :user_block, :package_set, :file
|
552
664
|
|
553
665
|
# The Manifest class represents the information included in the main
|
554
666
|
# manifest file, and allows to manipulate it
|
555
667
|
class Manifest
|
556
|
-
FakePackage = Struct.new :text_name, :name, :srcdir, :importer, :updated
|
557
668
|
|
558
669
|
# Data structure used to use autobuild importers without a package, to
|
559
670
|
# import configuration data.
|
@@ -561,7 +672,21 @@ module Autoproj
|
|
561
672
|
# It has to match the interface of Autobuild::Package that is relevant
|
562
673
|
# for importers
|
563
674
|
class FakePackage
|
564
|
-
|
675
|
+
attr_reader :text_name
|
676
|
+
attr_reader :name
|
677
|
+
attr_reader :srcdir
|
678
|
+
attr_reader :importer
|
679
|
+
|
680
|
+
# Used by the autobuild importers
|
681
|
+
attr_accessor :updated
|
682
|
+
|
683
|
+
def initialize(text_name, srcdir, importer = nil)
|
684
|
+
@text_name = text_name
|
685
|
+
@name = text_name.gsub /[^\w]/, '_'
|
686
|
+
@srcdir = srcdir
|
687
|
+
@importer = importer
|
688
|
+
end
|
689
|
+
|
565
690
|
def import
|
566
691
|
importer.import(self)
|
567
692
|
end
|
@@ -593,21 +718,34 @@ module Autoproj
|
|
593
718
|
# Loads the manifest file located at +file+ and returns the Manifest
|
594
719
|
# instance that represents it
|
595
720
|
def self.load(file)
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
raise ConfigError, "expected an autoproj configuration in #{File.expand_path(File.dirname(file))}, but #{file} does not exist"
|
600
|
-
rescue ArgumentError => e
|
601
|
-
raise ConfigError, "error in #{file}: #{e.message}"
|
602
|
-
end
|
603
|
-
Manifest.new(file, data)
|
721
|
+
manifest = Manifest.new
|
722
|
+
manifest.load(file)
|
723
|
+
manifest
|
604
724
|
end
|
605
725
|
|
726
|
+
# Load the manifest data contained in +file+
|
727
|
+
def load(file)
|
728
|
+
if !File.exists?(file)
|
729
|
+
raise ConfigError.new(dirname), "expected an autoproj configuration in #{dirname}, but #{file} does not exist"
|
730
|
+
end
|
731
|
+
|
732
|
+
data = Autoproj.in_file(file, ArgumentError) do
|
733
|
+
YAML.load(File.read(file))
|
734
|
+
end
|
735
|
+
|
736
|
+
@file = file
|
737
|
+
@data = data
|
738
|
+
|
739
|
+
if data['constants']
|
740
|
+
@constant_definitions = Autoproj.resolve_constant_definitions(data['constants'])
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
606
744
|
# The manifest data as a Hash
|
607
745
|
attr_reader :data
|
608
746
|
|
609
747
|
# The set of packages defined so far as a mapping from package name to
|
610
|
-
# [Autobuild::Package,
|
748
|
+
# [Autobuild::Package, package_set, file] tuple
|
611
749
|
attr_reader :packages
|
612
750
|
|
613
751
|
# A mapping from package names into PackageManifest objects
|
@@ -633,22 +771,19 @@ module Autoproj
|
|
633
771
|
|
634
772
|
attr_reader :constant_definitions
|
635
773
|
|
636
|
-
def initialize
|
637
|
-
@file =
|
638
|
-
@data =
|
774
|
+
def initialize
|
775
|
+
@file = nil
|
776
|
+
@data = nil
|
639
777
|
@packages = Hash.new
|
640
778
|
@package_manifests = Hash.new
|
641
779
|
@automatic_exclusions = Hash.new
|
642
780
|
@constants_definitions = Hash.new
|
781
|
+
@disabled_imports = Set.new
|
643
782
|
|
783
|
+
@constant_definitions = Hash.new
|
644
784
|
if Autoproj.has_config_key?('manifest_source')
|
645
785
|
@vcs = Autoproj.normalize_vcs_definition(Autoproj.user_config('manifest_source'))
|
646
786
|
end
|
647
|
-
if data['constants']
|
648
|
-
@constant_definitions = Autoproj.resolve_constant_definitions(data['constants'])
|
649
|
-
else
|
650
|
-
@constant_definitions = Hash.new
|
651
|
-
end
|
652
787
|
end
|
653
788
|
|
654
789
|
# True if the given package should not be built, with the packages that
|
@@ -730,7 +865,7 @@ module Autoproj
|
|
730
865
|
end
|
731
866
|
|
732
867
|
if source_name && !done_something
|
733
|
-
raise ConfigError, "in #{file}: source '#{source_name}' does not exist"
|
868
|
+
raise ConfigError.new(file), "in #{file}: source '#{source_name}' does not exist"
|
734
869
|
end
|
735
870
|
end
|
736
871
|
|
@@ -767,11 +902,11 @@ module Autoproj
|
|
767
902
|
end
|
768
903
|
|
769
904
|
# Like #each_source, but filters out local package sets
|
770
|
-
def
|
905
|
+
def each_remote_package_set(load_description = true)
|
771
906
|
if !block_given?
|
772
|
-
enum_for(:
|
907
|
+
enum_for(:each_remote_package_set, load_description)
|
773
908
|
else
|
774
|
-
|
909
|
+
each_package_set(load_description) do |source|
|
775
910
|
if !source.local?
|
776
911
|
yield(source)
|
777
912
|
end
|
@@ -779,73 +914,95 @@ module Autoproj
|
|
779
914
|
end
|
780
915
|
end
|
781
916
|
|
782
|
-
def
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
raise ConfigError, "in #{file}: #{e.message}"
|
791
|
-
end
|
792
|
-
|
793
|
-
source = Source.new(vcs_def)
|
794
|
-
if load_description
|
795
|
-
if source.present?
|
796
|
-
source.load_description_file
|
797
|
-
else
|
798
|
-
raise InternalError, "cannot load description file as it has not been checked out yet"
|
799
|
-
end
|
800
|
-
else
|
801
|
-
# Try to load just the name from the source.yml file
|
802
|
-
source.load_name
|
917
|
+
def each_remote_source(*args, &block)
|
918
|
+
each_remote_package_set(*args, &block)
|
919
|
+
end
|
920
|
+
|
921
|
+
# Helper method for #each_package_set
|
922
|
+
def enumerate_package_set(pkg_set, explicit_sets, all_sets) # :nodoc:
|
923
|
+
if @disabled_imports.include?(pkg_set.name)
|
924
|
+
pkg_set.auto_imports = false
|
803
925
|
end
|
804
926
|
|
805
|
-
|
806
|
-
|
927
|
+
result = []
|
928
|
+
if pkg_set.auto_imports?
|
929
|
+
pkg_set.each_imported_set do |imported_set|
|
930
|
+
if explicit_sets.any? { |src| src.vcs == imported_set.vcs } ||
|
931
|
+
all_sets.any? { |src| src.vcs == imported_set.vcs }
|
932
|
+
next
|
933
|
+
end
|
807
934
|
|
935
|
+
all_sets << imported_set
|
936
|
+
result.concat(enumerate_package_set(imported_set, explicit_sets, all_sets))
|
937
|
+
end
|
938
|
+
end
|
939
|
+
result << pkg_set
|
940
|
+
result
|
941
|
+
end
|
808
942
|
|
809
943
|
# call-seq:
|
810
|
-
#
|
944
|
+
# each_package_set { |pkg_set| ... }
|
811
945
|
#
|
812
|
-
# Lists all package sets defined in this manifest, by yielding a
|
813
|
-
# object that describes it.
|
814
|
-
def
|
946
|
+
# Lists all package sets defined in this manifest, by yielding a
|
947
|
+
# PackageSet object that describes it.
|
948
|
+
def each_package_set(load_description = true, &block)
|
815
949
|
if !block_given?
|
816
|
-
return enum_for(:
|
950
|
+
return enum_for(:each_package_set, load_description)
|
817
951
|
end
|
818
952
|
|
819
|
-
if @
|
953
|
+
if @package_sets
|
820
954
|
if load_description
|
821
|
-
@
|
955
|
+
@package_sets.each do |src|
|
822
956
|
if !src.source_definition
|
823
957
|
src.load_description_file
|
824
958
|
end
|
825
959
|
end
|
826
960
|
end
|
827
|
-
return @
|
961
|
+
return @package_sets.each(&block)
|
828
962
|
end
|
829
963
|
|
830
|
-
|
964
|
+
explicit_sets = (data['package_sets'] || []).map do |spec|
|
965
|
+
Autoproj.in_file(self.file) do
|
966
|
+
PackageSet.from_spec(self, spec, load_description)
|
967
|
+
end
|
968
|
+
end
|
831
969
|
|
832
|
-
|
833
|
-
|
970
|
+
all_sets = Array.new
|
971
|
+
explicit_sets.each do |pkg_set|
|
972
|
+
all_sets.concat(enumerate_package_set(pkg_set, explicit_sets, all_sets + [pkg_set]))
|
834
973
|
end
|
835
974
|
|
836
975
|
# Now load the local source
|
837
|
-
local =
|
976
|
+
local = LocalPackageSet.new(self)
|
838
977
|
if load_description
|
839
978
|
local.load_description_file
|
840
979
|
else
|
841
|
-
local.
|
980
|
+
local.load_minimal
|
842
981
|
end
|
843
982
|
if !load_description || !local.empty?
|
844
|
-
|
983
|
+
all_sets << local
|
984
|
+
end
|
985
|
+
|
986
|
+
if load_description
|
987
|
+
all_sets.each(&:load_description_file)
|
988
|
+
else
|
989
|
+
all_sets.each(&:load_minimal)
|
845
990
|
end
|
991
|
+
all_sets.each(&block)
|
992
|
+
end
|
993
|
+
|
994
|
+
# DEPRECATED. For backward-compatibility only
|
995
|
+
#
|
996
|
+
# use #each_package_set instead
|
997
|
+
def each_source(*args, &block)
|
998
|
+
each_package_set(*args, &block)
|
999
|
+
end
|
846
1000
|
|
847
|
-
|
848
|
-
|
1001
|
+
# Save the currently known package sets. After this call,
|
1002
|
+
# #each_package_set will always return the same set regardless of
|
1003
|
+
# changes on the manifest's data structures
|
1004
|
+
def cache_package_sets
|
1005
|
+
@package_sets = each_package_set(false).to_a
|
849
1006
|
end
|
850
1007
|
|
851
1008
|
# Register a new package
|
@@ -860,6 +1017,10 @@ module Autoproj
|
|
860
1017
|
@packages[package_name].file
|
861
1018
|
end
|
862
1019
|
|
1020
|
+
def package(name)
|
1021
|
+
packages[name]
|
1022
|
+
end
|
1023
|
+
|
863
1024
|
# Lists all defined packages and where they have been defined
|
864
1025
|
def each_package
|
865
1026
|
if !block_given?
|
@@ -877,11 +1038,11 @@ module Autoproj
|
|
877
1038
|
end
|
878
1039
|
|
879
1040
|
if vcs
|
880
|
-
yield(vcs, "autoproj main configuration",
|
1041
|
+
yield(vcs, "autoproj main configuration", Autoproj.config_dir)
|
881
1042
|
end
|
882
1043
|
|
883
1044
|
each_remote_source(false) do |source|
|
884
|
-
yield(source.vcs, source.name || source.vcs.url, source.
|
1045
|
+
yield(source.vcs, source.name || source.vcs.url, source.local_dir)
|
885
1046
|
end
|
886
1047
|
self
|
887
1048
|
end
|
@@ -893,81 +1054,108 @@ module Autoproj
|
|
893
1054
|
# the name used when displaying the import progress, +pkg_name+ the
|
894
1055
|
# internal name used to represent the package and +into+ the directory
|
895
1056
|
# in which the package should be checked out.
|
896
|
-
def self.create_autobuild_package(vcs, text_name,
|
1057
|
+
def self.create_autobuild_package(vcs, text_name, into)
|
1058
|
+
if !into
|
1059
|
+
raise
|
1060
|
+
end
|
897
1061
|
importer = vcs.create_autobuild_importer
|
898
1062
|
return if !importer # updates have been disabled by using the 'none' type
|
899
1063
|
|
900
|
-
|
901
|
-
fake_package.importer = importer
|
902
|
-
fake_package
|
1064
|
+
FakePackage.new(text_name, into, importer)
|
903
1065
|
|
904
1066
|
rescue Autobuild::ConfigException => e
|
905
|
-
raise ConfigError, "cannot import #{name}: #{e.message}", e.backtrace
|
1067
|
+
raise ConfigError.new, "cannot import #{name}: #{e.message}", e.backtrace
|
906
1068
|
end
|
907
1069
|
|
908
1070
|
# Imports or updates a source (remote or otherwise).
|
909
1071
|
#
|
910
1072
|
# See create_autobuild_package for informations about the arguments.
|
911
|
-
def self.
|
912
|
-
|
1073
|
+
def self.update_package_set(vcs, text_name, into)
|
1074
|
+
if !into
|
1075
|
+
raise
|
1076
|
+
end
|
1077
|
+
fake_package = create_autobuild_package(vcs, text_name, into)
|
913
1078
|
fake_package.import
|
914
1079
|
|
915
1080
|
rescue Autobuild::ConfigException => e
|
916
|
-
raise ConfigError, "cannot import #{name}: #{e.message}", e.backtrace
|
1081
|
+
raise ConfigError.new, "cannot import #{name}: #{e.message}", e.backtrace
|
917
1082
|
end
|
918
1083
|
|
919
1084
|
# Updates the main autoproj configuration
|
920
1085
|
def update_yourself
|
921
|
-
Manifest.
|
1086
|
+
Manifest.update_package_set(vcs, "autoproj main configuration", Autoproj.config_dir)
|
922
1087
|
end
|
923
1088
|
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
sources = []
|
930
|
-
each_remote_source(false) do |source|
|
931
|
-
name = if source.present? then source.name
|
932
|
-
else source.vcs.url
|
933
|
-
end
|
934
|
-
Manifest.update_source(source.vcs, name, source.automatic_name, source.raw_local_dir)
|
935
|
-
sources << source
|
936
|
-
end
|
1089
|
+
def update_remote_set(pkg_set, remotes_symlinks_dir = nil)
|
1090
|
+
Manifest.update_package_set(
|
1091
|
+
pkg_set.vcs,
|
1092
|
+
pkg_set.name,
|
1093
|
+
pkg_set.raw_local_dir)
|
937
1094
|
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
dir = File.expand_path(dir)
|
942
|
-
if File.directory?(dir) && !sources.any? { |s| s.raw_local_dir == dir }
|
943
|
-
FileUtils.rm_rf dir
|
944
|
-
end
|
945
|
-
end
|
946
|
-
|
947
|
-
remotes_symlinks_dir = File.join(Autoproj.config_dir, 'remotes')
|
948
|
-
FileUtils.mkdir_p remotes_symlinks_dir
|
949
|
-
known_remotes = []
|
950
|
-
|
951
|
-
# Create symbolic links from .remotes/weird_url to
|
952
|
-
# autoproj/remotes/name. Explicitely load the source name first
|
953
|
-
each_remote_source(false) do |source|
|
954
|
-
source.load_name
|
955
|
-
symlink_dest = File.join(remotes_symlinks_dir, source.name)
|
1095
|
+
if remotes_symlinks_dir
|
1096
|
+
pkg_set.load_minimal
|
1097
|
+
symlink_dest = File.join(remotes_symlinks_dir, pkg_set.name)
|
956
1098
|
|
957
1099
|
# Check if the current symlink is valid, and recreate it if it
|
958
1100
|
# is not
|
959
1101
|
if File.symlink?(symlink_dest)
|
960
1102
|
dest = File.readlink(symlink_dest)
|
961
|
-
if dest !=
|
1103
|
+
if dest != pkg_set.raw_local_dir
|
962
1104
|
FileUtils.rm_f symlink_dest
|
963
|
-
FileUtils.ln_sf
|
1105
|
+
FileUtils.ln_sf pkg_set.raw_local_dir, symlink_dest
|
964
1106
|
end
|
965
1107
|
else
|
966
1108
|
FileUtils.rm_f symlink_dest
|
967
|
-
FileUtils.ln_sf
|
1109
|
+
FileUtils.ln_sf pkg_set.raw_local_dir, symlink_dest
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
symlink_dest
|
1113
|
+
end
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
# Updates all the remote sources in ROOT_DIR/.remotes, as well as the
|
1117
|
+
# symbolic links in ROOT_DIR/autoproj/remotes
|
1118
|
+
def update_remote_package_sets
|
1119
|
+
remotes_symlinks_dir = File.join(Autoproj.config_dir, 'remotes')
|
1120
|
+
FileUtils.mkdir_p remotes_symlinks_dir
|
1121
|
+
|
1122
|
+
# Iterate on the remote sources, without loading the source.yml
|
1123
|
+
# file (we're not ready for that yet)
|
1124
|
+
#
|
1125
|
+
# Do it iteratively to properly take imports into account, but we
|
1126
|
+
# first unconditionally update all the existing sets to properly
|
1127
|
+
# handle imports that have been removed
|
1128
|
+
updated_sets = Hash.new
|
1129
|
+
known_remotes = []
|
1130
|
+
each_remote_package_set(false) do |pkg_set|
|
1131
|
+
next if !pkg_set.explicit?
|
1132
|
+
if pkg_set.present?
|
1133
|
+
known_remotes << update_remote_set(pkg_set, remotes_symlinks_dir)
|
1134
|
+
updated_sets[pkg_set.repository_id] = pkg_set
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
old_updated_sets = nil
|
1139
|
+
while old_updated_sets != updated_sets
|
1140
|
+
old_updated_sets = updated_sets.dup
|
1141
|
+
each_remote_package_set(false) do |pkg_set|
|
1142
|
+
next if updated_sets.has_key?(pkg_set.repository_id)
|
1143
|
+
|
1144
|
+
if !pkg_set.explicit?
|
1145
|
+
Autoproj.progress " #{pkg_set.imported_from.name}: auto-importing #{pkg_set.name}"
|
1146
|
+
end
|
1147
|
+
known_remotes << update_remote_set(pkg_set, remotes_symlinks_dir)
|
1148
|
+
updated_sets[pkg_set.repository_id] = pkg_set
|
968
1149
|
end
|
1150
|
+
end
|
969
1151
|
|
970
|
-
|
1152
|
+
# Check for directories in ROOT_DIR/.remotes that do not map to a
|
1153
|
+
# source repository, and remove them
|
1154
|
+
Dir.glob(File.join(Autoproj.remotes_dir, '*')).each do |dir|
|
1155
|
+
dir = File.expand_path(dir)
|
1156
|
+
if File.directory?(dir) && !updated_sets.values.find { |pkg| pkg.raw_local_dir == dir }
|
1157
|
+
FileUtils.rm_rf dir
|
1158
|
+
end
|
971
1159
|
end
|
972
1160
|
|
973
1161
|
# Now remove obsolete symlinks
|
@@ -978,6 +1166,11 @@ module Autoproj
|
|
978
1166
|
end
|
979
1167
|
end
|
980
1168
|
|
1169
|
+
# DEPRECATED. For backward-compatibility only
|
1170
|
+
def update_remote_sources(*args, &block)
|
1171
|
+
update_remote_package_sets(*args, &block)
|
1172
|
+
end
|
1173
|
+
|
981
1174
|
def importer_definition_for(package_name, package_source = nil)
|
982
1175
|
if !package_source
|
983
1176
|
package_source = packages.values.
|
@@ -985,13 +1178,16 @@ module Autoproj
|
|
985
1178
|
package_set
|
986
1179
|
end
|
987
1180
|
|
988
|
-
sources = each_source.to_a
|
1181
|
+
sources = each_source.to_a.dup
|
989
1182
|
|
990
1183
|
# Remove sources listed before the package source
|
991
1184
|
while !sources.empty? && sources[0].name != package_source.name
|
992
1185
|
sources.shift
|
993
1186
|
end
|
994
1187
|
package_source = sources.shift
|
1188
|
+
if !package_source
|
1189
|
+
raise InternalError, "cannot find the package set that defines #{package_name}"
|
1190
|
+
end
|
995
1191
|
|
996
1192
|
# Get the version control information from the package source. There
|
997
1193
|
# must be one
|
@@ -1032,7 +1228,7 @@ module Autoproj
|
|
1032
1228
|
Autoproj.add_build_system_dependency vcs.type
|
1033
1229
|
pkg.autobuild.importer = vcs.create_autobuild_importer
|
1034
1230
|
else
|
1035
|
-
raise ConfigError, "source #{pkg.package_set.name} defines #{pkg.autobuild.name}, but does not provide a version control definition for it"
|
1231
|
+
raise ConfigError.new, "source #{pkg.package_set.name} defines #{pkg.autobuild.name}, but does not provide a version control definition for it"
|
1036
1232
|
end
|
1037
1233
|
end
|
1038
1234
|
end
|
@@ -1044,12 +1240,12 @@ module Autoproj
|
|
1044
1240
|
if Autobuild::Package[name]
|
1045
1241
|
[name]
|
1046
1242
|
else
|
1047
|
-
|
1048
|
-
if !
|
1049
|
-
raise ConfigError, "
|
1243
|
+
pkg_set = each_package_set(false).find { |set| set.name == name }
|
1244
|
+
if !pkg_set
|
1245
|
+
raise ConfigError.new, "#{name} is neither a package nor a source"
|
1050
1246
|
end
|
1051
1247
|
packages.values.
|
1052
|
-
find_all { |pkg| pkg.package_set.name ==
|
1248
|
+
find_all { |pkg| pkg.package_set.name == pkg_set.name }.
|
1053
1249
|
map { |pkg| pkg.autobuild.name }.
|
1054
1250
|
find_all { |pkg_name| !Autoproj.osdeps || !Autoproj.osdeps.has?(pkg_name) }
|
1055
1251
|
end
|
@@ -1059,11 +1255,15 @@ module Autoproj
|
|
1059
1255
|
#
|
1060
1256
|
# If recursive is false, yields only the packages at this level.
|
1061
1257
|
# Otherwise, return all packages.
|
1062
|
-
def layout_packages(layout_def, recursive)
|
1258
|
+
def layout_packages(layout_def, recursive, validate = true)
|
1063
1259
|
result = []
|
1064
1260
|
layout_def.each do |value|
|
1065
1261
|
if !value.kind_of?(Hash) # sublayout
|
1066
|
-
|
1262
|
+
begin
|
1263
|
+
result.concat(resolve_package_set(value))
|
1264
|
+
rescue ConfigError
|
1265
|
+
raise if validate
|
1266
|
+
end
|
1067
1267
|
end
|
1068
1268
|
end
|
1069
1269
|
|
@@ -1088,7 +1288,7 @@ module Autoproj
|
|
1088
1288
|
|
1089
1289
|
# Looks into the layout setup in the manifest, and yields each layout
|
1090
1290
|
# and sublayout in order
|
1091
|
-
def
|
1291
|
+
def each_layout_level(selection = nil, layout_name = '/', layout_def = data['layout'], &block)
|
1092
1292
|
if !layout_def
|
1093
1293
|
yield(layout_name, default_packages, default_packages)
|
1094
1294
|
return nil
|
@@ -1112,14 +1312,14 @@ module Autoproj
|
|
1112
1312
|
|
1113
1313
|
# Now, enumerate the sublayouts
|
1114
1314
|
each_sublayout(layout_def) do |subname, sublayout|
|
1115
|
-
|
1315
|
+
each_layout_level(selection, "#{layout_name}#{subname}/", sublayout, &block)
|
1116
1316
|
end
|
1117
1317
|
end
|
1118
1318
|
|
1119
1319
|
# Returns the set of package names that are explicitely listed in the
|
1120
1320
|
# layout, minus the excluded and ignored ones
|
1121
|
-
def all_layout_packages
|
1122
|
-
default_packages
|
1321
|
+
def all_layout_packages(validate = true)
|
1322
|
+
default_packages(validate)
|
1123
1323
|
end
|
1124
1324
|
|
1125
1325
|
# Returns all defined package names, minus the excluded and ignored ones
|
@@ -1134,11 +1334,30 @@ module Autoproj
|
|
1134
1334
|
find_all { |pkg_name| !Autoproj.osdeps || !Autoproj.osdeps.has?(pkg_name) }
|
1135
1335
|
end
|
1136
1336
|
|
1337
|
+
# Returns true if +name+ is a valid package and is included in the build
|
1338
|
+
#
|
1339
|
+
# If +validate+ is true, the layout will have to be well-defined. It can
|
1340
|
+
# therefore be used only after all sources have been successfully
|
1341
|
+
# loaded.
|
1342
|
+
#
|
1343
|
+
# If it is false, non-defined packages/package sets in the layout will
|
1344
|
+
# simply be ignored
|
1345
|
+
def package_enabled?(name, validate = true)
|
1346
|
+
if !Autobuild::Package[name]
|
1347
|
+
if validate
|
1348
|
+
raise ArgumentError, "package #{name} does not exist"
|
1349
|
+
end
|
1350
|
+
return false
|
1351
|
+
end
|
1352
|
+
|
1353
|
+
!excluded?(name)
|
1354
|
+
end
|
1355
|
+
|
1137
1356
|
# Returns the set of packages that should be built if the user does not
|
1138
1357
|
# specify any on the command line
|
1139
|
-
def default_packages
|
1358
|
+
def default_packages(validate = true)
|
1140
1359
|
names = if layout = data['layout']
|
1141
|
-
layout_packages(layout, true)
|
1360
|
+
layout_packages(layout, true, validate)
|
1142
1361
|
else
|
1143
1362
|
# No layout, all packages are selected
|
1144
1363
|
all_packages
|
@@ -1150,12 +1369,20 @@ module Autoproj
|
|
1150
1369
|
|
1151
1370
|
# Returns the package directory for the given package name
|
1152
1371
|
def whereis(package_name)
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1372
|
+
Autoproj.in_file(self.file) do
|
1373
|
+
each_layout_level do |layout_name, packages, _|
|
1374
|
+
if packages.include?(package_name)
|
1375
|
+
return layout_name
|
1376
|
+
end
|
1156
1377
|
end
|
1378
|
+
raise ArgumentError, "cannot find #{package_name} in the layout section"
|
1379
|
+
end
|
1380
|
+
end
|
1381
|
+
|
1382
|
+
def resolve_optional_dependencies
|
1383
|
+
packages.each_value do |pkg|
|
1384
|
+
pkg.autobuild.resolve_optional_dependencies
|
1157
1385
|
end
|
1158
|
-
raise ArgumentError, "cannot find #{package_name} in the current layout"
|
1159
1386
|
end
|
1160
1387
|
|
1161
1388
|
# Loads the package's manifest.xml file for the current package
|
@@ -1180,13 +1407,19 @@ module Autoproj
|
|
1180
1407
|
manifest = PackageManifest.load(package, manifest_path)
|
1181
1408
|
package_manifests[package.name] = manifest
|
1182
1409
|
|
1183
|
-
manifest.each_dependency do |name|
|
1410
|
+
manifest.each_dependency do |name, is_optional|
|
1184
1411
|
begin
|
1185
|
-
|
1412
|
+
if is_optional
|
1413
|
+
package.optional_dependency name
|
1414
|
+
else
|
1415
|
+
package.depends_on name
|
1416
|
+
end
|
1186
1417
|
rescue Autobuild::ConfigException => e
|
1187
|
-
raise ConfigError
|
1418
|
+
raise ConfigError.new(manifest_path),
|
1419
|
+
"manifest #{manifest_path} of #{package.name} from #{source.name} lists '#{name}' as dependency, which is listed in the layout of #{file} but has no autobuild definition", e.backtrace
|
1188
1420
|
rescue ConfigError => e
|
1189
|
-
raise ConfigError
|
1421
|
+
raise ConfigError.new(manifest_path),
|
1422
|
+
"manifest #{manifest_path} of #{package.name} from #{source.name} lists '#{name}' as dependency, but it is neither a normal package nor an osdeps package. osdeps reports: #{e.message}", e.backtrace
|
1190
1423
|
end
|
1191
1424
|
end
|
1192
1425
|
end
|
@@ -1198,6 +1431,11 @@ module Autoproj
|
|
1198
1431
|
selected_packages.each(&:load_package_manifest)
|
1199
1432
|
end
|
1200
1433
|
|
1434
|
+
# Disable all automatic imports from the given package set name
|
1435
|
+
def disable_imports_from(pkg_set_name)
|
1436
|
+
@disabled_imports << pkg_set_name
|
1437
|
+
end
|
1438
|
+
|
1201
1439
|
# call-seq:
|
1202
1440
|
# list_os_dependencies(packages) => required_packages, ospkg_to_pkg
|
1203
1441
|
#
|
@@ -1264,7 +1502,7 @@ module Autoproj
|
|
1264
1502
|
end
|
1265
1503
|
|
1266
1504
|
# Now, search for layout names
|
1267
|
-
|
1505
|
+
each_layout_level(nil) do |layout_name, packages, _|
|
1268
1506
|
selected_packages.each do |sel|
|
1269
1507
|
if layout_name[0..-1] =~ Regexp.new("#{sel}\/?$")
|
1270
1508
|
expanded_packages |= packages.to_set
|
@@ -1325,6 +1563,15 @@ module Autoproj
|
|
1325
1563
|
# The raw XML data as a Nokogiri document
|
1326
1564
|
attr_reader :xml
|
1327
1565
|
|
1566
|
+
def short_documentation
|
1567
|
+
xml.xpath('//description').each do |node|
|
1568
|
+
if doc = node['brief']
|
1569
|
+
return doc.to_s
|
1570
|
+
end
|
1571
|
+
end
|
1572
|
+
nil
|
1573
|
+
end
|
1574
|
+
|
1328
1575
|
def initialize(package, doc)
|
1329
1576
|
@package = package
|
1330
1577
|
@xml = doc
|
@@ -1342,10 +1589,10 @@ module Autoproj
|
|
1342
1589
|
def each_os_dependency
|
1343
1590
|
if block_given?
|
1344
1591
|
xml.xpath('//rosdep').each do |node|
|
1345
|
-
yield(node['name'])
|
1592
|
+
yield(node['name'], false)
|
1346
1593
|
end
|
1347
1594
|
package.os_packages.each do |name|
|
1348
|
-
yield(name)
|
1595
|
+
yield(name, false)
|
1349
1596
|
end
|
1350
1597
|
else
|
1351
1598
|
enum_for :each_os_dependency
|
@@ -1356,10 +1603,16 @@ module Autoproj
|
|
1356
1603
|
if block_given?
|
1357
1604
|
xml.xpath('//depend').each do |node|
|
1358
1605
|
dependency = node['package']
|
1606
|
+
optional =
|
1607
|
+
if node['optional'].to_s == '1'
|
1608
|
+
true
|
1609
|
+
else false
|
1610
|
+
end
|
1611
|
+
|
1359
1612
|
if dependency
|
1360
|
-
yield(dependency)
|
1613
|
+
yield(dependency, optional)
|
1361
1614
|
else
|
1362
|
-
raise ConfigError, "manifest of #{package.name} has a <depend> tag without a 'package' attribute"
|
1615
|
+
raise ConfigError.new, "manifest of #{package.name} has a <depend> tag without a 'package' attribute"
|
1363
1616
|
end
|
1364
1617
|
end
|
1365
1618
|
else
|