autoproj 2.0.0.rc37 → 2.0.0.rc38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -2
- data/Rakefile +1 -1
- data/bin/autoproj_bootstrap +34 -2
- data/bin/autoproj_bootstrap.in +4 -2
- data/bin/autoproj_install +34 -2
- data/bin/autoproj_install.in +4 -2
- data/lib/autoproj.rb +9 -2
- data/lib/autoproj/autobuild.rb +13 -742
- data/lib/autoproj/autobuild_extensions/archive_importer.rb +44 -0
- data/lib/autoproj/autobuild_extensions/dsl.rb +439 -0
- data/lib/autoproj/autobuild_extensions/git.rb +116 -0
- data/lib/autoproj/autobuild_extensions/package.rb +159 -0
- data/lib/autoproj/autobuild_extensions/svn.rb +11 -0
- data/lib/autoproj/cli/base.rb +17 -18
- data/lib/autoproj/cli/clean.rb +1 -2
- data/lib/autoproj/cli/envsh.rb +1 -2
- data/lib/autoproj/cli/inspection_tool.rb +12 -21
- data/lib/autoproj/cli/locate.rb +130 -73
- data/lib/autoproj/cli/main.rb +31 -5
- data/lib/autoproj/cli/main_plugin.rb +79 -0
- data/lib/autoproj/cli/main_test.rb +19 -5
- data/lib/autoproj/cli/osdeps.rb +1 -2
- data/lib/autoproj/cli/patcher.rb +21 -0
- data/lib/autoproj/cli/query.rb +34 -41
- data/lib/autoproj/cli/show.rb +121 -52
- data/lib/autoproj/cli/status.rb +4 -5
- data/lib/autoproj/cli/tag.rb +1 -1
- data/lib/autoproj/cli/test.rb +7 -6
- data/lib/autoproj/cli/update.rb +8 -22
- data/lib/autoproj/cli/versions.rb +1 -2
- data/lib/autoproj/configuration.rb +1 -1
- data/lib/autoproj/environment.rb +2 -7
- data/lib/autoproj/exceptions.rb +10 -8
- data/lib/autoproj/find_workspace.rb +46 -12
- data/lib/autoproj/installation_manifest.rb +34 -25
- data/lib/autoproj/local_package_set.rb +86 -0
- data/lib/autoproj/manifest.rb +448 -503
- data/lib/autoproj/metapackage.rb +31 -5
- data/lib/autoproj/ops/configuration.rb +46 -45
- data/lib/autoproj/ops/import.rb +150 -60
- data/lib/autoproj/ops/install.rb +25 -1
- data/lib/autoproj/ops/loader.rb +4 -1
- data/lib/autoproj/ops/main_config_switcher.rb +4 -4
- data/lib/autoproj/ops/snapshot.rb +4 -3
- data/lib/autoproj/os_package_installer.rb +105 -46
- data/lib/autoproj/os_package_resolver.rb +63 -36
- data/lib/autoproj/package_definition.rb +1 -0
- data/lib/autoproj/package_managers/apt_dpkg_manager.rb +30 -27
- data/lib/autoproj/package_managers/bundler_manager.rb +64 -18
- data/lib/autoproj/package_managers/gem_manager.rb +4 -2
- data/lib/autoproj/package_managers/manager.rb +26 -7
- data/lib/autoproj/package_managers/shell_script_manager.rb +4 -4
- data/lib/autoproj/package_managers/zypper_manager.rb +1 -1
- data/lib/autoproj/package_manifest.rb +154 -137
- data/lib/autoproj/package_selection.rb +16 -2
- data/lib/autoproj/package_set.rb +352 -309
- data/lib/autoproj/query.rb +13 -1
- data/lib/autoproj/system.rb +2 -2
- data/lib/autoproj/test.rb +164 -11
- data/lib/autoproj/variable_expansion.rb +15 -42
- data/lib/autoproj/vcs_definition.rb +93 -76
- data/lib/autoproj/version.rb +1 -1
- data/lib/autoproj/workspace.rb +116 -80
- metadata +10 -2
@@ -55,6 +55,16 @@ def each(&block)
|
|
55
55
|
each_source_package_name(&block)
|
56
56
|
end
|
57
57
|
|
58
|
+
def each_package_name(&block)
|
59
|
+
return enum_for(__method__) if !block
|
60
|
+
each_source_package_name(&block)
|
61
|
+
each_osdep_package_name(&block)
|
62
|
+
end
|
63
|
+
|
64
|
+
def selected_source_package?(pkg)
|
65
|
+
source_packages.include?(pkg.name)
|
66
|
+
end
|
67
|
+
|
58
68
|
def each_source_package_name(&block)
|
59
69
|
source_packages.each(&block)
|
60
70
|
end
|
@@ -106,6 +116,10 @@ def has_match_for?(sel)
|
|
106
116
|
matches.has_key?(sel)
|
107
117
|
end
|
108
118
|
|
119
|
+
def match_for(sel)
|
120
|
+
matches[sel]
|
121
|
+
end
|
122
|
+
|
109
123
|
# Remove packages that are explicitely excluded and/or ignored
|
110
124
|
#
|
111
125
|
# Raise an error if an explicit selection expands only to an
|
@@ -130,9 +144,9 @@ def filter_excluded_and_ignored_packages(manifest)
|
|
130
144
|
raise ExcludedSelection.new(sel), "#{base_msg}, but its dependency #{exclusions.map(&:first).join(", ")} is excluded from the build: #{reason}"
|
131
145
|
end
|
132
146
|
elsif weak_dependencies[sel]
|
133
|
-
raise ExcludedSelection.new(sel), "#{base_msg}, but expands to #{exclusions.map(&:first).join(", ")}, and all these packages are excluded from the build:\n #{exclusions.map { |
|
147
|
+
raise ExcludedSelection.new(sel), "#{base_msg}, but expands to #{exclusions.map(&:first).join(", ")}, and all these packages are excluded from the build:\n #{exclusions.map { |e_name, e_reason| "#{e_name}: #{e_reason}" }.join("\n ")}"
|
134
148
|
else
|
135
|
-
raise ExcludedSelection.new(sel), "#{base_msg}, but it requires #{exclusions.map(&:first).join(", ")}, and all these packages are excluded from the build:\n #{exclusions.map { |
|
149
|
+
raise ExcludedSelection.new(sel), "#{base_msg}, but it requires #{exclusions.map(&:first).join(", ")}, and all these packages are excluded from the build:\n #{exclusions.map { |e_name, e_reason| "#{e_name}: #{e_reason}" }.join("\n ")}"
|
136
150
|
end
|
137
151
|
else
|
138
152
|
self.exclusions[sel] |= excluded.to_set.dup
|
data/lib/autoproj/package_set.rb
CHANGED
@@ -27,8 +27,29 @@ def add_source_file(name)
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
#
|
31
|
-
|
30
|
+
# The underlying workspace
|
31
|
+
#
|
32
|
+
# @return [Workspace]
|
33
|
+
attr_reader :ws
|
34
|
+
|
35
|
+
# The manifest this package set is registered on
|
36
|
+
#
|
37
|
+
# @return [Manifest]
|
38
|
+
def manifest
|
39
|
+
ws.manifest
|
40
|
+
end
|
41
|
+
|
42
|
+
# The minimum autoproj version this package set requires
|
43
|
+
#
|
44
|
+
# It defaults to 0
|
45
|
+
#
|
46
|
+
# @return [String]
|
47
|
+
attr_accessor :required_autoproj_version
|
48
|
+
|
49
|
+
# The package set name
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
attr_accessor :name
|
32
53
|
|
33
54
|
# The VCSDefinition object that defines the version control holding
|
34
55
|
# information for this source. Local package sets (i.e. the ones that are not
|
@@ -38,10 +59,13 @@ def add_source_file(name)
|
|
38
59
|
|
39
60
|
# The set of OSPackageResolver object that represent the osdeps files
|
40
61
|
# available in this package set
|
62
|
+
#
|
63
|
+
# @return [Array<(String,OSPackageResolver)>] the list of osdep files
|
64
|
+
# and the corresponding OSPackageResolver object
|
41
65
|
attr_reader :all_osdeps
|
42
66
|
|
43
67
|
# The OSPackageResolver which is a merged version of all OSdeps in
|
44
|
-
# #all_osdeps
|
68
|
+
# {#all_osdeps}
|
45
69
|
attr_reader :os_package_resolver
|
46
70
|
|
47
71
|
# If this package set has been imported from another package set, this
|
@@ -53,9 +77,22 @@ def add_source_file(name)
|
|
53
77
|
def explicit?; !!@explicit end
|
54
78
|
attr_writer :explicit
|
55
79
|
|
56
|
-
|
80
|
+
# Definition of key => value mappings used to resolve e.g. $KEY values
|
81
|
+
# in the version control sections
|
57
82
|
attr_reader :constants_definitions
|
58
83
|
|
84
|
+
# The version control information defined in this package set
|
85
|
+
attr_reader :version_control
|
86
|
+
|
87
|
+
# Cached results of {#importer_definition_for}
|
88
|
+
attr_reader :importer_definitions_cache
|
89
|
+
|
90
|
+
# The importer that should be used for packages that have no explicit
|
91
|
+
# entry
|
92
|
+
#
|
93
|
+
# @return [VCSDefinition]
|
94
|
+
attr_accessor :default_importer
|
95
|
+
|
59
96
|
# The set of overrides defined in this package set
|
60
97
|
attr_reader :overrides
|
61
98
|
|
@@ -83,18 +120,43 @@ def metapackage
|
|
83
120
|
# List of the packages that are built if the package set is selected in
|
84
121
|
# the layout
|
85
122
|
def default_packages
|
86
|
-
metapackage.
|
123
|
+
metapackage.each_package
|
87
124
|
end
|
88
125
|
|
126
|
+
# Remote sources can be accessed through a hidden directory in
|
127
|
+
# {Workspace#remotes_dir}, or through a symbolic link in
|
128
|
+
# autoproj/remotes/
|
129
|
+
#
|
130
|
+
# This returns the former. See #user_local_dir for the latter.
|
131
|
+
#
|
132
|
+
# For local sources, is simply returns the path to the source directory.
|
133
|
+
attr_reader :raw_local_dir
|
134
|
+
|
89
135
|
# Create this source from a VCSDefinition object
|
90
|
-
def initialize(
|
91
|
-
|
136
|
+
def initialize(
|
137
|
+
ws, vcs,
|
138
|
+
name: self.class.name_of(ws, vcs),
|
139
|
+
raw_local_dir: self.class.raw_local_dir_of(ws, vcs))
|
140
|
+
|
141
|
+
@ws = ws
|
92
142
|
@vcs = vcs
|
93
|
-
|
143
|
+
if !vcs
|
144
|
+
raise ArgumentError, "cannot create a package set with a nil vcs, create a null VCS using VCSDefinition.none"
|
145
|
+
end
|
146
|
+
@name = name
|
147
|
+
@os_package_resolver = OSPackageResolver.new(
|
148
|
+
operating_system: ws.os_package_resolver.operating_system,
|
149
|
+
package_managers: ws.os_package_resolver.package_managers,
|
150
|
+
os_package_manager: ws.os_package_resolver.os_package_manager)
|
151
|
+
@importer_definitions_cache = Hash.new
|
94
152
|
@all_osdeps = []
|
153
|
+
@constants_definitions = Hash.new
|
154
|
+
@required_autoproj_version = '0'
|
155
|
+
@version_control = Array.new
|
95
156
|
@overrides = Array.new
|
157
|
+
@raw_local_dir = raw_local_dir
|
158
|
+
@default_importer = VCSDefinition.from_raw(type: 'none')
|
96
159
|
|
97
|
-
@provides = Set.new
|
98
160
|
@imports = Set.new
|
99
161
|
@imports_vcs = Array.new
|
100
162
|
@imported_from = Array.new
|
@@ -103,8 +165,8 @@ def initialize(manifest, vcs)
|
|
103
165
|
end
|
104
166
|
|
105
167
|
# Load a new osdeps file for this package set
|
106
|
-
def load_osdeps(file)
|
107
|
-
new_osdeps = OSPackageResolver.load(file)
|
168
|
+
def load_osdeps(file, **options)
|
169
|
+
new_osdeps = OSPackageResolver.load(file, **options)
|
108
170
|
all_osdeps << new_osdeps
|
109
171
|
os_package_resolver.merge(all_osdeps.last)
|
110
172
|
new_osdeps
|
@@ -112,7 +174,7 @@ def load_osdeps(file)
|
|
112
174
|
|
113
175
|
# Enumerate all osdeps package names from this package set
|
114
176
|
def each_osdep(&block)
|
115
|
-
os_package_resolver.
|
177
|
+
os_package_resolver.all_package_names.each(&block)
|
116
178
|
end
|
117
179
|
|
118
180
|
# True if this source has already been checked out on the local autoproj
|
@@ -125,7 +187,7 @@ def main?; false end
|
|
125
187
|
def local?; vcs.local? end
|
126
188
|
# True if this source defines nothing
|
127
189
|
def empty?
|
128
|
-
|
190
|
+
version_control.empty? && overrides.empty?
|
129
191
|
!each_package.find { true } &&
|
130
192
|
!File.exist?(File.join(raw_local_dir, "overrides.rb")) &&
|
131
193
|
!File.exist?(File.join(raw_local_dir, "init.rb"))
|
@@ -136,6 +198,8 @@ def autobuild
|
|
136
198
|
create_autobuild_package
|
137
199
|
end
|
138
200
|
|
201
|
+
# Create a stub autobuild package to handle the import of this package
|
202
|
+
# set
|
139
203
|
def create_autobuild_package
|
140
204
|
Ops::Tools.create_autobuild_package(vcs, name, raw_local_dir)
|
141
205
|
end
|
@@ -158,12 +222,12 @@ def snapshot(target_dir, options = Hash.new)
|
|
158
222
|
# checked out, and the vcs (as a string) otherwise
|
159
223
|
#
|
160
224
|
# @return [String]
|
161
|
-
def self.name_of(
|
162
|
-
|
163
|
-
|
164
|
-
|
225
|
+
def self.name_of(ws, vcs, raw_local_dir: raw_local_dir_of(ws, vcs))
|
226
|
+
if File.directory?(raw_local_dir)
|
227
|
+
raw_description_file(raw_local_dir, package_set_name: "#{vcs.type}:#{vcs.url}")['name']
|
228
|
+
else
|
229
|
+
vcs.to_s
|
165
230
|
end
|
166
|
-
name || vcs.to_s
|
167
231
|
end
|
168
232
|
|
169
233
|
# Returns the local directory in which the given package set should be
|
@@ -172,11 +236,13 @@ def self.name_of(manifest, vcs)
|
|
172
236
|
# @param [VCSDefinition] vcs the version control information for the
|
173
237
|
# package set
|
174
238
|
# @return [String]
|
175
|
-
def self.raw_local_dir_of(vcs)
|
176
|
-
if vcs.
|
239
|
+
def self.raw_local_dir_of(ws, vcs)
|
240
|
+
if vcs.needs_import?
|
241
|
+
repository_id = vcs.create_autobuild_importer.repository_id
|
242
|
+
path = File.join(ws.remotes_dir, repository_id.gsub(/[^\w]/, '_'))
|
243
|
+
File.expand_path(path)
|
244
|
+
elsif !vcs.none?
|
177
245
|
File.expand_path(vcs.url)
|
178
|
-
else
|
179
|
-
File.expand_path(File.join(Autoproj.workspace.remotes_dir, vcs.create_autobuild_importer.repository_id.gsub(/[^\w]/, '_')))
|
180
246
|
end
|
181
247
|
end
|
182
248
|
|
@@ -185,21 +251,12 @@ def self.raw_local_dir_of(vcs)
|
|
185
251
|
# This parses the information stored in the package_sets section of
|
186
252
|
# autoproj/manifest, or the imports section of the source.yml files and
|
187
253
|
# returns the corresponding VCSDefinition object
|
188
|
-
def self.resolve_definition(
|
189
|
-
|
190
|
-
|
191
|
-
if File.directory?(local_path)
|
192
|
-
raw_spec = { :type => 'local', :url => local_path }
|
193
|
-
end
|
194
|
-
end
|
195
|
-
spec = VCSDefinition.vcs_definition_to_hash(raw_spec)
|
196
|
-
options, vcs_spec = Kernel.filter_options spec, :auto_imports => true
|
254
|
+
def self.resolve_definition(ws, raw_spec, from: nil, raw: Array.new)
|
255
|
+
spec = VCSDefinition.normalize_vcs_hash(raw_spec, base_dir: ws.config_dir)
|
256
|
+
options, vcs_spec = Kernel.filter_options spec, auto_imports: true
|
197
257
|
|
198
|
-
|
199
|
-
|
200
|
-
# 'url' to be a path to a local directory
|
201
|
-
vcs_spec = Autoproj.expand(vcs_spec, manifest.constant_definitions)
|
202
|
-
return VCSDefinition.from_raw(vcs_spec, raw: [[nil, raw_spec]]), options
|
258
|
+
vcs_spec = Autoproj.expand(vcs_spec, ws.manifest.constant_definitions)
|
259
|
+
return VCSDefinition.from_raw(vcs_spec, from: from, raw: raw), options
|
203
260
|
end
|
204
261
|
|
205
262
|
# Returns a string that uniquely represents the version control
|
@@ -210,7 +267,7 @@ def self.resolve_definition(manifest, raw_spec)
|
|
210
267
|
# from exactly the same source.
|
211
268
|
def repository_id
|
212
269
|
if local?
|
213
|
-
|
270
|
+
raw_local_dir
|
214
271
|
else
|
215
272
|
importer = vcs.create_autobuild_importer
|
216
273
|
if importer.respond_to?(:repository_id)
|
@@ -221,17 +278,6 @@ def repository_id
|
|
221
278
|
end
|
222
279
|
end
|
223
280
|
|
224
|
-
# Remote sources can be accessed through a hidden directory in
|
225
|
-
# {Workspace#remotes_dir}, or through a symbolic link in
|
226
|
-
# autoproj/remotes/
|
227
|
-
#
|
228
|
-
# This returns the former. See #user_local_dir for the latter.
|
229
|
-
#
|
230
|
-
# For local sources, is simply returns the path to the source directory.
|
231
|
-
def raw_local_dir
|
232
|
-
self.class.raw_local_dir_of(vcs)
|
233
|
-
end
|
234
|
-
|
235
281
|
# Remote sources can be accessed through a hidden directory in
|
236
282
|
# {Workspace#remotes_dir}, or through a symbolic link in
|
237
283
|
# autoproj/remotes/
|
@@ -243,7 +289,7 @@ def user_local_dir
|
|
243
289
|
if local?
|
244
290
|
return vcs.url
|
245
291
|
else
|
246
|
-
File.join(
|
292
|
+
File.join(ws.config_dir, 'remotes', name)
|
247
293
|
end
|
248
294
|
end
|
249
295
|
|
@@ -251,35 +297,26 @@ def user_local_dir
|
|
251
297
|
def local_dir
|
252
298
|
ugly_dir = raw_local_dir
|
253
299
|
pretty_dir = user_local_dir
|
254
|
-
if
|
300
|
+
if ugly_dir == pretty_dir
|
301
|
+
pretty_dir
|
302
|
+
elsif File.symlink?(pretty_dir) && File.readlink(pretty_dir) == ugly_dir
|
255
303
|
pretty_dir
|
256
304
|
else
|
257
305
|
ugly_dir
|
258
306
|
end
|
259
307
|
end
|
260
308
|
|
261
|
-
|
262
|
-
definition = @source_definition || raw_description_file
|
263
|
-
definition['required_autoproj_version'] || '0'
|
264
|
-
end
|
265
|
-
|
266
|
-
# Returns the source name
|
267
|
-
def name
|
268
|
-
@name || self.class.name_of(manifest, vcs)
|
269
|
-
end
|
270
|
-
|
271
|
-
# Loads the source.yml file, validates it and returns it as a hash
|
309
|
+
# @api private
|
272
310
|
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
311
|
+
# Read the description information for a package set in a given
|
312
|
+
# directory
|
313
|
+
#
|
314
|
+
# @param [String] raw_local_dir the package set's directory
|
315
|
+
# @return [Hash] the raw description information
|
316
|
+
def self.raw_description_file(raw_local_dir, package_set_name: nil)
|
280
317
|
master_source_file = File.join(raw_local_dir, PackageSet.master_source_file)
|
281
318
|
if !File.exist?(master_source_file)
|
282
|
-
raise ConfigError.new, "
|
319
|
+
raise ConfigError.new, "package set #{package_set_name} present in #{raw_local_dir} should have a source.yml file, but does not"
|
283
320
|
end
|
284
321
|
|
285
322
|
source_definition = Hash.new
|
@@ -297,13 +334,24 @@ def raw_description_file
|
|
297
334
|
end
|
298
335
|
end
|
299
336
|
end
|
300
|
-
|
301
337
|
if !source_definition['name']
|
302
|
-
raise ConfigError.new(master_source_file), "
|
338
|
+
raise ConfigError.new(master_source_file), "#{master_source_file} does not have a 'name' field"
|
303
339
|
end
|
304
340
|
source_definition
|
305
341
|
end
|
306
342
|
|
343
|
+
# Loads the source.yml file, validates it and returns it as a hash
|
344
|
+
#
|
345
|
+
# Raises InternalError if the source has not been checked out yet (it
|
346
|
+
# should have), and ConfigError if the source.yml file is not valid.
|
347
|
+
def raw_description_file
|
348
|
+
if !present?
|
349
|
+
raise InternalError, "source #{vcs} has not been fetched yet, cannot load description for it"
|
350
|
+
end
|
351
|
+
|
352
|
+
self.class.raw_description_file(raw_local_dir, package_set_name: name)
|
353
|
+
end
|
354
|
+
|
307
355
|
# Yields the package sets imported by this package set
|
308
356
|
#
|
309
357
|
# This information is available only after the whole configuration has
|
@@ -314,23 +362,53 @@ def each_imported_set(&block)
|
|
314
362
|
@imports.each(&block)
|
315
363
|
end
|
316
364
|
|
365
|
+
# Add a new constant to be used to resolve e.g. version control entries
|
366
|
+
def add_constant_definition(key, value)
|
367
|
+
constants_definitions[key] = value
|
368
|
+
end
|
369
|
+
|
370
|
+
# Add a new VCS import to the list of imports
|
371
|
+
#
|
372
|
+
# @param [VCSDefinition] vcs the VCS specification for the import
|
373
|
+
# @return [void]
|
374
|
+
def add_raw_imported_set(vcs, auto_imports: true)
|
375
|
+
imports_vcs << [vcs, Hash[auto_imports: auto_imports]]
|
376
|
+
end
|
377
|
+
|
317
378
|
# Yields the imports raw information
|
318
379
|
#
|
319
380
|
# @yieldparam [VCSDefinition] vcs the import VCS information
|
320
381
|
# @yieldparam [Hash] options import options
|
321
382
|
def each_raw_imported_set(&block)
|
322
|
-
|
383
|
+
imports_vcs.each(&block)
|
384
|
+
end
|
385
|
+
|
386
|
+
# Add a new entry in the list of version control resolutions
|
387
|
+
def add_version_control_entry(matcher, vcs_definition)
|
388
|
+
invalidate_importer_definitions_cache
|
389
|
+
version_control << [matcher, vcs_definition]
|
390
|
+
end
|
391
|
+
|
392
|
+
# Add a new entry in the list of version control resolutions
|
393
|
+
def add_overrides_entry(matcher, vcs_definition, file: '#add_overrides_entry')
|
394
|
+
if (last_entry = overrides.last) && last_entry[0] == file
|
395
|
+
last_entry[1] << [matcher, vcs_definition]
|
396
|
+
else
|
397
|
+
overrides << [file, [[matcher, vcs_definition]]]
|
398
|
+
end
|
323
399
|
end
|
324
400
|
|
325
401
|
# Path to the source.yml file
|
326
402
|
def source_file
|
327
|
-
|
403
|
+
if local_dir
|
404
|
+
File.join(local_dir, 'source.yml')
|
405
|
+
end
|
328
406
|
end
|
329
407
|
|
330
408
|
# Load the source.yml file and resolves all information it contains.
|
331
409
|
def load_description_file
|
332
|
-
|
333
|
-
name =
|
410
|
+
source_definition = raw_description_file
|
411
|
+
name = source_definition['name']
|
334
412
|
if name !~ /^[\w\.-]+$/
|
335
413
|
raise ConfigError.new(source_file),
|
336
414
|
"in #{source_file}: invalid source name '#{@name}': source names can only contain alphanumeric characters, and .-_"
|
@@ -339,198 +417,251 @@ def load_description_file
|
|
339
417
|
"in #{source_file}: the name 'local' is a reserved name"
|
340
418
|
end
|
341
419
|
|
342
|
-
parse_source_definition
|
343
|
-
@overrides = load_overrides
|
420
|
+
parse_source_definition(source_definition)
|
344
421
|
end
|
345
422
|
|
346
|
-
def load_overrides
|
423
|
+
def load_overrides(source_definition)
|
347
424
|
if data = source_definition['overrides']
|
348
425
|
[[source_file, data]]
|
349
|
-
else
|
350
|
-
[]
|
351
426
|
end
|
352
427
|
end
|
353
428
|
|
354
|
-
def parse_source_definition
|
355
|
-
@name = source_definition['name']
|
356
|
-
@
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
429
|
+
def parse_source_definition(source_definition)
|
430
|
+
@name = source_definition['name'] || self.name
|
431
|
+
@required_autoproj_version = source_definition.fetch('required_autoproj_version', self.required_autoproj_version)
|
432
|
+
if new_imports = source_definition['imports']
|
433
|
+
@imports_vcs = Array(new_imports).map do |set_def|
|
434
|
+
if !set_def.kind_of?(Hash) && !set_def.respond_to?(:to_str)
|
435
|
+
raise ConfigError.new(source_file),
|
436
|
+
"in #{source_file}: wrong format for 'imports' section. Expected an array of maps or strings (e.g. - github: my/url)."
|
437
|
+
end
|
438
|
+
|
439
|
+
Autoproj.in_file(source_file) do
|
440
|
+
PackageSet.resolve_definition(ws, set_def, from: self, raw: [VCSDefinition::RawEntry.new(self, source_file, set_def)])
|
441
|
+
end
|
361
442
|
end
|
443
|
+
end
|
362
444
|
|
445
|
+
# Compute the definition of constants
|
446
|
+
if new_constants = source_definition['constants']
|
363
447
|
Autoproj.in_file(source_file) do
|
364
|
-
|
448
|
+
variables = inject_constants_and_config_for_expansion(Hash.new)
|
449
|
+
@constants_definitions = Autoproj.resolve_constant_definitions(new_constants, variables)
|
365
450
|
end
|
366
451
|
end
|
367
452
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
453
|
+
if new_version_control = source_definition['version_control']
|
454
|
+
invalidate_importer_definitions_cache
|
455
|
+
@version_control = normalize_vcs_list('version_control', source_file, new_version_control)
|
456
|
+
|
457
|
+
Autoproj.in_file(source_file) do
|
458
|
+
default_vcs_spec, raw = version_control_field('default', version_control, file: source_file)
|
459
|
+
if default_vcs_spec
|
460
|
+
@default_importer = VCSDefinition.from_raw(default_vcs_spec, raw: raw, from: self)
|
461
|
+
end
|
462
|
+
end
|
372
463
|
end
|
464
|
+
if new_overrides = load_overrides(source_definition)
|
465
|
+
@overrides = new_overrides.map do |file, entries|
|
466
|
+
[file, normalize_vcs_list('overrides', file, entries)]
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
# @api private
|
472
|
+
#
|
473
|
+
# Injects the values of {#constants_definitions} and
|
474
|
+
# {#manifest}.constant_definitions, as well as the available
|
475
|
+
# configuration variables, into a hash suitable to be used for variable
|
476
|
+
# expansion using {Autoproj.expand} and {Autoproj.single_expansion}
|
477
|
+
def inject_constants_and_config_for_expansion(additional_expansions)
|
478
|
+
defs = Hash[
|
479
|
+
"AUTOPROJ_ROOT" => ws.root_dir,
|
480
|
+
"AUTOPROJ_CONFIG" => ws.config_dir,
|
481
|
+
"AUTOPROJ_SOURCE_DIR" => local_dir].
|
482
|
+
merge(manifest.constant_definitions).
|
483
|
+
merge(constants_definitions).
|
484
|
+
merge(additional_expansions)
|
485
|
+
|
486
|
+
config = ws.config
|
487
|
+
Hash.new do |h, k|
|
488
|
+
if config.has_value_for?(k) || config.declared?(k)
|
489
|
+
config.get(k)
|
490
|
+
end
|
491
|
+
end.merge(defs)
|
373
492
|
end
|
374
493
|
|
375
494
|
def single_expansion(data, additional_expansions = Hash.new)
|
376
|
-
|
377
|
-
|
378
|
-
end
|
379
|
-
Autoproj.single_expansion(data, additional_expansions.merge(constants_definitions))
|
495
|
+
defs = inject_constants_and_config_for_expansion(additional_expansions)
|
496
|
+
Autoproj.single_expansion(data, defs)
|
380
497
|
end
|
381
498
|
|
382
499
|
# Expands the given string as much as possible using the expansions
|
383
500
|
# listed in the source.yml file, and returns it. Raises if not all
|
384
501
|
# variables can be expanded.
|
385
502
|
def expand(data, additional_expansions = Hash.new)
|
386
|
-
|
387
|
-
|
388
|
-
end
|
389
|
-
Autoproj.expand(data, additional_expansions.merge(constants_definitions))
|
390
|
-
end
|
391
|
-
|
392
|
-
# Returns the default importer definition for this package set, as a
|
393
|
-
# VCSDefinition instance
|
394
|
-
def default_importer
|
395
|
-
importer_definition_for('default')
|
503
|
+
defs = inject_constants_and_config_for_expansion(additional_expansions)
|
504
|
+
Autoproj.expand(data, defs)
|
396
505
|
end
|
397
506
|
|
398
|
-
#
|
399
|
-
# available. Otherwise returns nil.
|
507
|
+
# @api private
|
400
508
|
#
|
401
|
-
#
|
402
|
-
def
|
403
|
-
|
509
|
+
# Converts a number to an ordinal string representation (i.e. 1st, 25th)
|
510
|
+
def number_to_nth(number)
|
511
|
+
Hash[1 => '1st', 2 => '2nd', 3 => '3rd'].fetch(number, "#{number}th")
|
404
512
|
end
|
405
513
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
elsif !all_vcs.kind_of?(Array)
|
415
|
-
raise ConfigError.new, "wrong format for the #{section_name} section"
|
416
|
-
end
|
514
|
+
# @api private
|
515
|
+
#
|
516
|
+
# Validate the format of a VCS list field (formatted in array-of-hashes)
|
517
|
+
def normalize_vcs_list(section_name, file, list)
|
518
|
+
if list.kind_of?(Hash)
|
519
|
+
raise InvalidYAMLFormatting, "wrong format for the #{section_name} section of #{file}, you forgot the '-' in front of the package names"
|
520
|
+
elsif !list.kind_of?(Array)
|
521
|
+
raise InvalidYAMLFormatting, "wrong format for the #{section_name} section of #{file}"
|
417
522
|
end
|
418
523
|
|
419
|
-
|
420
|
-
|
524
|
+
list.each_with_index.map do |spec, spec_idx|
|
525
|
+
spec_nth = number_to_nth(spec_idx + 1)
|
526
|
+
if !spec.kind_of?(Hash)
|
527
|
+
raise InvalidYAMLFormatting, "wrong format for the #{spec_nth} entry (#{spec.inspect}) of the #{section_name} section of #{file}, expected a package name, followed by a colon, and one importer option per following line"
|
528
|
+
end
|
421
529
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
530
|
+
spec = spec.dup
|
531
|
+
if spec.values.size != 1
|
532
|
+
# Maybe the user wrote the spec like
|
533
|
+
# - package_name:
|
534
|
+
# type: git
|
535
|
+
# url: blah
|
536
|
+
#
|
537
|
+
# In that case, we should have the package name as
|
538
|
+
# "name => nil". Check that.
|
539
|
+
name, _ = spec.find { |n, v| v.nil? }
|
540
|
+
if name
|
541
|
+
spec.delete(name)
|
542
|
+
else
|
543
|
+
raise InvalidYAMLFormatting, "cannot make sense of the #{spec_nth} entry in the #{section_name} section of #{file}: #{spec}"
|
427
544
|
end
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
# url: blah
|
434
|
-
#
|
435
|
-
# or as
|
436
|
-
# - package_name
|
437
|
-
# type: git
|
438
|
-
# url: blah
|
439
|
-
#
|
440
|
-
# In that case, we should have the package name as
|
441
|
-
# "name => nil". Check that.
|
442
|
-
name, _ = spec.find { |n, v| v.nil? }
|
443
|
-
if name
|
444
|
-
spec.delete(name)
|
545
|
+
else
|
546
|
+
name, spec = spec.to_a.first
|
547
|
+
if spec.respond_to?(:to_str)
|
548
|
+
if spec == "none"
|
549
|
+
spec = Hash['type' => "none"]
|
445
550
|
else
|
446
|
-
|
447
|
-
name =~ / (\w+)$/
|
448
|
-
spec[$1] = spec.delete(name)
|
449
|
-
name = name.gsub(/ \w+$/, '')
|
450
|
-
end
|
451
|
-
else
|
452
|
-
name, spec = spec.to_a.first
|
453
|
-
if name =~ / (\w+)/
|
454
|
-
spec = { $1 => spec }
|
455
|
-
name = name.gsub(/ \w+$/, '')
|
456
|
-
end
|
457
|
-
|
458
|
-
if spec.respond_to?(:to_str)
|
459
|
-
if spec == "none"
|
460
|
-
spec = { :type => "none" }
|
461
|
-
else
|
462
|
-
raise ConfigError.new, "invalid VCS specification in the #{section_name} section '#{name}: #{spec}'"
|
463
|
-
end
|
551
|
+
raise ConfigError.new, "invalid VCS specification in the #{section_name} section of #{file}: '#{name}: #{spec}'. One can only use this shorthand to declare the absence of a VCS with the 'none' keyword"
|
464
552
|
end
|
553
|
+
elsif !spec.kind_of?(Hash)
|
554
|
+
raise InvalidYAMLFormatting, "expected '#{name}:' followed by version control options, but got nothing, in the #{spec_nth} entry of the #{section_name} section of #{file}"
|
465
555
|
end
|
556
|
+
end
|
466
557
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
end
|
471
|
-
if name_match === package_name
|
472
|
-
raw << [self, spec]
|
473
|
-
vcs_spec =
|
474
|
-
begin
|
475
|
-
VCSDefinition.update_raw_vcs_spec(vcs_spec, spec)
|
476
|
-
rescue ConfigError => e
|
477
|
-
raise ConfigError.new, "invalid VCS definition in the #{section_name} section for '#{name}': #{e.message}", e.backtrace
|
478
|
-
end
|
479
|
-
end
|
558
|
+
name_match = name
|
559
|
+
if name_match =~ /[^\w\/-]/
|
560
|
+
name_match = Regexp.new("^" + name_match)
|
480
561
|
end
|
562
|
+
|
563
|
+
[name_match, spec]
|
481
564
|
end
|
565
|
+
end
|
482
566
|
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
567
|
+
# Returns a VCS definition for the given package, if one is
|
568
|
+
# available. Otherwise returns nil.
|
569
|
+
#
|
570
|
+
# @return [[(Hash,nil),Array]] the resolved VCS definition, as well
|
571
|
+
# as the "history" of it, that is the list of entries that matched the
|
572
|
+
# package in the form (PackageSet,Hash), where PackageSet is self.
|
573
|
+
# The Hash part is nil if there are no matching entries. Hash keys are
|
574
|
+
# normalized to symbols
|
575
|
+
def version_control_field(package_name, entry_list, validate: true, file: source_file)
|
576
|
+
raw = []
|
577
|
+
vcs_spec = Hash.new
|
489
578
|
|
490
|
-
|
491
|
-
|
492
|
-
|
579
|
+
entry_list.each do |name_match, spec|
|
580
|
+
if name_match === package_name
|
581
|
+
raw << VCSDefinition::RawEntry.new(self, file, spec)
|
582
|
+
vcs_spec =
|
583
|
+
begin
|
584
|
+
VCSDefinition.update_raw_vcs_spec(vcs_spec, spec)
|
585
|
+
rescue ConfigError => e
|
586
|
+
raise ConfigError.new, "invalid VCS definition in the #{section_name} section for '#{name}': #{e.message}", e.backtrace
|
587
|
+
end
|
493
588
|
end
|
589
|
+
end
|
494
590
|
|
495
|
-
|
496
|
-
# configuration
|
497
|
-
if validate
|
498
|
-
begin
|
499
|
-
VCSDefinition.from_raw(vcs_spec)
|
500
|
-
rescue ConfigError => e
|
501
|
-
raise ConfigError.new, "invalid resulting VCS definition for package #{package_name}: #{e.message}", e.backtrace
|
502
|
-
end
|
503
|
-
end
|
504
|
-
return vcs_spec, raw
|
505
|
-
else
|
591
|
+
if vcs_spec.empty?
|
506
592
|
return nil, []
|
507
593
|
end
|
594
|
+
|
595
|
+
expansions = Hash["PACKAGE" => package_name,
|
596
|
+
"PACKAGE_BASENAME" => File.basename(package_name)]
|
597
|
+
|
598
|
+
vcs_spec = expand(vcs_spec, expansions)
|
599
|
+
vcs_spec.dup.each do |name, value|
|
600
|
+
vcs_spec[name] = expand(value, expansions)
|
601
|
+
end
|
602
|
+
|
603
|
+
# Resolve relative paths w.r.t. the workspace root dir
|
604
|
+
if url = (vcs_spec.delete('url') || vcs_spec.delete(:url))
|
605
|
+
vcs_spec[:url] = VCSDefinition.to_absolute_url(url, ws.root_dir)
|
606
|
+
end
|
607
|
+
|
608
|
+
# If required, verify that the configuration is a valid VCS
|
609
|
+
# configuration
|
610
|
+
if validate
|
611
|
+
begin
|
612
|
+
VCSDefinition.from_raw(vcs_spec)
|
613
|
+
rescue ConfigError => e
|
614
|
+
raise ConfigError.new, "invalid resulting VCS definition for package #{package_name}: #{e.message}", e.backtrace
|
615
|
+
end
|
616
|
+
end
|
617
|
+
return vcs_spec, raw
|
618
|
+
end
|
619
|
+
|
620
|
+
# @api private
|
621
|
+
#
|
622
|
+
# Invalidate {#importer_definitions_cache}
|
623
|
+
def invalidate_importer_definitions_cache
|
624
|
+
@importer_definitions_cache.clear
|
508
625
|
end
|
509
626
|
|
510
627
|
# Returns the VCS definition for +package_name+ as defined in this
|
511
628
|
# source, or nil if the source does not have any.
|
512
629
|
#
|
513
|
-
#
|
514
|
-
|
515
|
-
|
516
|
-
|
630
|
+
# @param [PackageDefinition] package
|
631
|
+
# @return [VCSDefinition] the importer definition, or nil if none
|
632
|
+
# could be found
|
633
|
+
def importer_definition_for(package, default: default_importer, require_existing: true)
|
634
|
+
package_name = manifest.validate_package_name_argument(package, require_existing: require_existing)
|
635
|
+
importer_definitions_cache[package_name] ||= Autoproj.in_file source_file do
|
636
|
+
vcs_spec, raw = version_control_field(package_name, version_control, file: source_file)
|
517
637
|
if vcs_spec
|
518
638
|
VCSDefinition.from_raw(vcs_spec, raw: raw, from: self)
|
639
|
+
else
|
640
|
+
default
|
519
641
|
end
|
520
642
|
end
|
521
643
|
end
|
522
644
|
|
523
645
|
# Update a VCS object using the overrides defined in this package set
|
524
646
|
#
|
525
|
-
# @param [
|
647
|
+
# @param [PackageDefinition] package the package
|
526
648
|
# @param [VCSDefinition] the vcs to be updated
|
527
649
|
# @return [VCSDefinition] the new, updated vcs object
|
528
|
-
def overrides_for(
|
529
|
-
|
650
|
+
def overrides_for(package, vcs, require_existing: true)
|
651
|
+
package_name = manifest.validate_package_name_argument(package, require_existing: require_existing)
|
652
|
+
resolve_overrides(package_name, vcs)
|
653
|
+
end
|
654
|
+
|
655
|
+
# @api private
|
656
|
+
#
|
657
|
+
# Apply overrides on a VCS object from its (string) key
|
658
|
+
#
|
659
|
+
# This is a helper for {#overrides_for}
|
660
|
+
def resolve_overrides(key, vcs)
|
661
|
+
overrides.each do |file, file_overrides|
|
530
662
|
new_spec, new_raw_entry =
|
531
663
|
Autoproj.in_file file do
|
532
|
-
|
533
|
-
package_name, 'overrides', false)
|
664
|
+
version_control_field(key, file_overrides, validate: false, file: file)
|
534
665
|
end
|
535
666
|
|
536
667
|
if new_spec
|
@@ -538,7 +669,7 @@ def overrides_for(package_name, vcs)
|
|
538
669
|
begin
|
539
670
|
vcs = vcs.update(new_spec, raw: new_raw_entry, from: self)
|
540
671
|
rescue ConfigError => e
|
541
|
-
raise ConfigError.new, "invalid resulting VCS specification in the overrides section for
|
672
|
+
raise ConfigError.new, "invalid resulting VCS specification in the overrides section for #{key}: #{e.message}"
|
542
673
|
end
|
543
674
|
end
|
544
675
|
end
|
@@ -553,117 +684,29 @@ def each_package
|
|
553
684
|
return enum_for(:each_package)
|
554
685
|
end
|
555
686
|
|
556
|
-
manifest.
|
557
|
-
if pkg.package_set
|
687
|
+
manifest.each_package_definition do |pkg|
|
688
|
+
if pkg.package_set == self
|
558
689
|
yield(pkg.autobuild)
|
559
690
|
end
|
560
691
|
end
|
561
692
|
end
|
562
693
|
|
563
|
-
#
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
provides.include?(name)
|
569
|
-
end
|
570
|
-
end
|
571
|
-
|
572
|
-
# Specialization of the PackageSet class for the overrides listed in autoproj/
|
573
|
-
class LocalPackageSet < PackageSet
|
574
|
-
def initialize(manifest, local_dir = nil)
|
575
|
-
super(manifest, manifest.vcs)
|
576
|
-
@local_dir = local_dir
|
577
|
-
end
|
578
|
-
|
579
|
-
def name
|
580
|
-
'main configuration'
|
581
|
-
end
|
582
|
-
|
583
|
-
def vcs
|
584
|
-
manifest.vcs
|
585
|
-
end
|
586
|
-
|
587
|
-
def main?
|
588
|
-
true
|
589
|
-
end
|
590
|
-
|
591
|
-
def local?
|
592
|
-
true
|
593
|
-
end
|
594
|
-
|
595
|
-
def local_dir
|
596
|
-
@local_dir || (File.dirname(manifest.file) if manifest.file)
|
597
|
-
end
|
598
|
-
|
599
|
-
def raw_local_dir; local_dir end
|
600
|
-
|
601
|
-
def manifest_path
|
602
|
-
manifest.file
|
603
|
-
end
|
604
|
-
|
605
|
-
def overrides_file_path
|
606
|
-
if d = local_dir
|
607
|
-
File.join(d, "overrides.yml")
|
608
|
-
end
|
609
|
-
end
|
610
|
-
|
611
|
-
def source_file
|
612
|
-
manifest_path
|
613
|
-
end
|
614
|
-
|
615
|
-
# Returns the default importer for this package set
|
616
|
-
def default_importer
|
617
|
-
importer_definition_for('default') ||
|
618
|
-
VCSDefinition.from_raw(:type => 'none')
|
619
|
-
end
|
620
|
-
|
621
|
-
def load_description_file
|
622
|
-
@source_definition = raw_description_file
|
623
|
-
parse_source_definition
|
624
|
-
@overrides = load_overrides
|
625
|
-
end
|
626
|
-
|
627
|
-
def load_overrides
|
628
|
-
files = Dir.glob(File.join( Autoproj.workspace.overrides_dir, "*.yml" ) ).sort
|
629
|
-
overrides = files.map do |file|
|
630
|
-
source_data = Autoproj.in_file(file, Autoproj::YAML_LOAD_ERROR) do
|
631
|
-
YAML.load(File.read(file)) || Array.new
|
632
|
-
end
|
633
|
-
source_data =
|
634
|
-
if source_data.respond_to?(:to_ary)
|
635
|
-
source_data
|
636
|
-
else source_data['overrides'] || Array.new
|
637
|
-
end
|
638
|
-
[file, source_data]
|
694
|
+
# List the autobuild files that are part of this package set
|
695
|
+
def each_autobuild_file
|
696
|
+
return enum_for(__method__) if !block_given?
|
697
|
+
Dir.glob(File.join(local_dir, "*.autobuild")).sort.each do |file|
|
698
|
+
yield(file)
|
639
699
|
end
|
640
|
-
overrides + super
|
641
700
|
end
|
642
701
|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
overrides_data = Autoproj.in_file(overrides_file_path, Autoproj::YAML_LOAD_ERROR) do
|
650
|
-
YAML.load(File.read(overrides_file_path)) || Hash.new
|
651
|
-
end
|
652
|
-
description = description.merge(overrides_data)
|
653
|
-
end
|
654
|
-
|
655
|
-
manifest_data = Autoproj.in_file(manifest_path, Autoproj::YAML_LOAD_ERROR) do
|
656
|
-
YAML.load(File.read(manifest_path)) || Hash.new
|
702
|
+
# Yields each osdeps definition files that are present in this package
|
703
|
+
# set
|
704
|
+
def each_osdeps_file
|
705
|
+
return enum_for(__method__) if !block_given?
|
706
|
+
Dir.glob(File.join(local_dir, "*.osdeps")).each do |file|
|
707
|
+
yield(file)
|
657
708
|
end
|
658
|
-
description['imports'] = description['imports'].
|
659
|
-
concat(manifest_data['package_sets'] || Array.new)
|
660
|
-
description['name'] = name
|
661
|
-
description
|
662
709
|
end
|
663
710
|
end
|
664
|
-
|
665
|
-
# DEPRECATED. For backward-compatibility only.
|
666
|
-
Source = PackageSet
|
667
|
-
# DEPRECATED. For backward-compatibility only.
|
668
|
-
LocalSource = LocalPackageSet
|
669
711
|
end
|
712
|
+
|