autoproj 2.0.0.rc37 → 2.0.0.rc38
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.
- 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
|
+
|