autoproj 1.6.2 → 1.7.0.b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|