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
data/lib/autoproj/query.rb
CHANGED
@@ -54,6 +54,14 @@ class Query
|
|
54
54
|
attr_predicate :use_dir_prefix?
|
55
55
|
attr_predicate :partial?
|
56
56
|
|
57
|
+
class All
|
58
|
+
def match(pkg); true end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.all
|
62
|
+
All.new
|
63
|
+
end
|
64
|
+
|
57
65
|
def initialize(fields, value, partial)
|
58
66
|
@fields = fields
|
59
67
|
@value = value
|
@@ -158,7 +166,11 @@ def self.parse_query(query)
|
|
158
166
|
Query.parse(str)
|
159
167
|
end
|
160
168
|
end
|
161
|
-
|
169
|
+
if query.size == 1
|
170
|
+
query.first
|
171
|
+
else
|
172
|
+
And.new(query)
|
173
|
+
end
|
162
174
|
end
|
163
175
|
|
164
176
|
# Match object that combines multiple matches using a logical OR
|
data/lib/autoproj/system.rb
CHANGED
@@ -112,8 +112,8 @@ def self.run_as_user(*args)
|
|
112
112
|
end
|
113
113
|
end
|
114
114
|
# Run the provided command as root, using sudo to gain root access
|
115
|
-
def self.run_as_root(*args)
|
116
|
-
if !system(Autobuild.tool_in_path('sudo'), *args)
|
115
|
+
def self.run_as_root(*args, env: self.workspace.env)
|
116
|
+
if !system(Autobuild.tool_in_path('sudo', env: env), *args)
|
117
117
|
raise "failed to run #{args.join(" ")} as root"
|
118
118
|
end
|
119
119
|
end
|
data/lib/autoproj/test.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
begin
|
5
5
|
require 'simplecov'
|
6
6
|
SimpleCov.start do
|
7
|
+
command_name 'master'
|
7
8
|
add_filter "/test/"
|
8
9
|
end
|
9
10
|
rescue LoadError
|
@@ -18,6 +19,7 @@
|
|
18
19
|
require 'minitest/autorun'
|
19
20
|
require 'autoproj'
|
20
21
|
require 'flexmock/minitest'
|
22
|
+
FlexMock.partials_are_based = true
|
21
23
|
require 'minitest/spec'
|
22
24
|
|
23
25
|
if ENV['TEST_ENABLE_PRY'] != '0'
|
@@ -40,15 +42,27 @@ module Autoproj
|
|
40
42
|
# end
|
41
43
|
#
|
42
44
|
module SelfTest
|
45
|
+
# Define package managers for the next workspace created by {#ws_create}
|
46
|
+
#
|
47
|
+
# Use {#ws_define_package_manager}
|
48
|
+
#
|
49
|
+
# Two package managers called 'os' and 'os_indep' are always created,
|
50
|
+
# 'os' is used as the os package manager.
|
51
|
+
#
|
52
|
+
# @return [Hash<String,PackageManagers::Manager>]
|
53
|
+
attr_reader :ws_package_managers
|
54
|
+
# The workspace created by the last call to #ws_create
|
43
55
|
attr_reader :ws
|
44
56
|
|
45
57
|
def setup
|
58
|
+
FileUtils.rm_rf fixture_gem_home
|
46
59
|
@gem_server_pid = nil
|
47
60
|
@tmpdir = Array.new
|
48
|
-
@ws =
|
49
|
-
|
50
|
-
|
51
|
-
|
61
|
+
@ws = nil
|
62
|
+
@ws_package_managers = Hash.new
|
63
|
+
Autobuild.logdir = make_tmpdir
|
64
|
+
ws_define_package_manager 'os'
|
65
|
+
ws_define_package_manager 'os_indep'
|
52
66
|
|
53
67
|
super
|
54
68
|
end
|
@@ -59,6 +73,7 @@ def teardown
|
|
59
73
|
FileUtils.remove_entry_secure dir
|
60
74
|
end
|
61
75
|
Autobuild::Package.clear
|
76
|
+
Autoproj.silent = false
|
62
77
|
|
63
78
|
if @gem_server_pid
|
64
79
|
stop_gem_server
|
@@ -68,12 +83,11 @@ def teardown
|
|
68
83
|
end
|
69
84
|
|
70
85
|
def create_bootstrap
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
Workspace.new(dir)
|
86
|
+
ws_create
|
87
|
+
end
|
88
|
+
|
89
|
+
def skip_long_tests?
|
90
|
+
ENV['AUTOPROJ_SKIP_LONG_TESTS'] == '1'
|
77
91
|
end
|
78
92
|
|
79
93
|
def make_tmpdir
|
@@ -140,8 +154,13 @@ def invoke_test_script(name, *arguments,
|
|
140
154
|
end
|
141
155
|
result = nil
|
142
156
|
stdout, stderr = capture_subprocess_io do
|
157
|
+
default_env = Hash[
|
158
|
+
'TEST_COMMAND_NAME' => self.to_s.gsub(/[^\w]/, '_'),
|
159
|
+
'PACKAGE_BASE_DIR' => package_base_dir,
|
160
|
+
'RUBY' => Gem.ruby
|
161
|
+
]
|
143
162
|
result = Bundler.clean_system(
|
144
|
-
|
163
|
+
default_env.merge(env),
|
145
164
|
script, *arguments, in: :close, **Hash[chdir: dir].merge(system_options))
|
146
165
|
end
|
147
166
|
|
@@ -200,6 +219,16 @@ def stop_gem_server
|
|
200
219
|
@gem_server_pid = nil
|
201
220
|
end
|
202
221
|
|
222
|
+
def capture_deprecation_message(&block)
|
223
|
+
level = Autoproj.warn_deprecated_level
|
224
|
+
Autoproj.warn_deprecated_level = -1
|
225
|
+
capture_subprocess_io do
|
226
|
+
yield
|
227
|
+
end
|
228
|
+
ensure
|
229
|
+
Autoproj.warn_deprecated_level = level
|
230
|
+
end
|
231
|
+
|
203
232
|
def find_bundled_gem_path(bundler, gem_name, gemfile)
|
204
233
|
out_r, out_w = IO.pipe
|
205
234
|
result = Bundler.clean_system(
|
@@ -217,6 +246,130 @@ def workspace_env(varname)
|
|
217
246
|
stdout.chomp
|
218
247
|
end
|
219
248
|
|
249
|
+
attr_reader :ws_os_package_resolver
|
250
|
+
|
251
|
+
def ws_define_package_manager(name, strict: false, call_while_empty: false)
|
252
|
+
manager = Class.new(PackageManagers::Manager)
|
253
|
+
manager.class_eval do
|
254
|
+
define_method(:strict?) { strict }
|
255
|
+
define_method(:call_while_empty?) { call_while_empty }
|
256
|
+
end
|
257
|
+
manager = flexmock(manager),
|
258
|
+
ws_package_managers[name] = manager
|
259
|
+
end
|
260
|
+
|
261
|
+
def ws_create_os_package_resolver
|
262
|
+
@ws_os_package_resolver = OSPackageResolver.new(
|
263
|
+
operating_system: [['test_os_family'], ['test_os_version']],
|
264
|
+
package_managers: ws_package_managers.keys,
|
265
|
+
os_package_manager: 'os')
|
266
|
+
end
|
267
|
+
|
268
|
+
def ws_create
|
269
|
+
dir = make_tmpdir
|
270
|
+
require 'autoproj/ops/main_config_switcher'
|
271
|
+
FileUtils.cp_r Ops::MainConfigSwitcher::MAIN_CONFIGURATION_TEMPLATE, File.join(dir, 'autoproj')
|
272
|
+
FileUtils.mkdir_p File.join(dir, '.autoproj')
|
273
|
+
|
274
|
+
ws_create_os_package_resolver
|
275
|
+
@ws = Workspace.new(
|
276
|
+
dir, os_package_resolver: ws_os_package_resolver,
|
277
|
+
package_managers: ws_package_managers)
|
278
|
+
ws.config.set 'osdeps_mode', 'all'
|
279
|
+
ws.config.set 'gems_install_path', File.join(dir, 'gems')
|
280
|
+
ws.config.save
|
281
|
+
ws.prefix_dir = make_tmpdir
|
282
|
+
ws
|
283
|
+
end
|
284
|
+
|
285
|
+
def ws_clear_layout
|
286
|
+
ws.manifest.clear_layout
|
287
|
+
end
|
288
|
+
|
289
|
+
def ws_define_package_set(name, vcs = VCSDefinition.from_raw(type: 'none'), **options)
|
290
|
+
package_set = PackageSet.new(ws, vcs, name: name, **options)
|
291
|
+
ws.manifest.register_package_set(package_set)
|
292
|
+
package_set
|
293
|
+
end
|
294
|
+
|
295
|
+
def ws_add_package_set_to_layout(name, vcs = VCSDefinition.from_raw(type: 'none'), **options)
|
296
|
+
package_set = ws_define_package_set(name, vcs, **options)
|
297
|
+
ws.manifest.add_package_set_to_layout(package_set)
|
298
|
+
package_set
|
299
|
+
end
|
300
|
+
|
301
|
+
def ws_define_osdep_entries(entries)
|
302
|
+
ws_os_package_resolver.add_entries(entries)
|
303
|
+
end
|
304
|
+
|
305
|
+
def ws_add_osdep_entries_to_layout(entries)
|
306
|
+
ws_os_package_resolver.add_entries(entries)
|
307
|
+
entries.each_key do |pkg_name|
|
308
|
+
ws.manifest.add_package_to_layout(pkg_name)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
def ws_define_package(package_type, package_name, package_set: ws.manifest.main_package_set, create: true)
|
313
|
+
package = Autobuild.send(package_type, package_name)
|
314
|
+
package.srcdir = File.join(ws.root_dir, package_name.to_s)
|
315
|
+
if create
|
316
|
+
FileUtils.mkdir_p package.srcdir
|
317
|
+
end
|
318
|
+
autoproj_package = ws.register_package(package, nil, package_set)
|
319
|
+
yield(package) if block_given?
|
320
|
+
autoproj_package
|
321
|
+
end
|
322
|
+
|
323
|
+
def ws_define_package_vcs(package, vcs_spec)
|
324
|
+
package.package_set.add_version_control_entry(package.name, vcs_spec)
|
325
|
+
end
|
326
|
+
|
327
|
+
def ws_define_package_overrides(package, package_set, vcs_spec)
|
328
|
+
package_set.add_overrides_entry(package.name, vcs_spec)
|
329
|
+
end
|
330
|
+
|
331
|
+
def ws_add_package_to_layout(package_type, package_name, package_set: ws.manifest.main_package_set, &block)
|
332
|
+
pkg = ws_define_package(package_type, package_name, package_set: package_set, &block)
|
333
|
+
ws.manifest.add_package_to_layout(pkg)
|
334
|
+
pkg
|
335
|
+
end
|
336
|
+
|
337
|
+
def ws_set_version_control_entry(package, entry)
|
338
|
+
package.package_set.add_version_control_entry(package.name, entry)
|
339
|
+
end
|
340
|
+
|
341
|
+
def ws_set_overrides_entry(package, package_set, entry)
|
342
|
+
package_set.add_overrides_entry(package.name, entry)
|
343
|
+
end
|
344
|
+
|
345
|
+
def ws_setup_package_dirs(package, create_srcdir: true)
|
346
|
+
package.autobuild.srcdir = srcdir = File.join(ws.root_dir, package.name)
|
347
|
+
if create_srcdir
|
348
|
+
FileUtils.mkdir_p srcdir
|
349
|
+
elsif File.directory?(srcdir)
|
350
|
+
FileUtils.rm_rf srcdir
|
351
|
+
end
|
352
|
+
package.autobuild.builddir = builddir = File.join(ws.root_dir, 'build', package.name)
|
353
|
+
package.autobuild.prefix = prefix = File.join(ws.root_dir, 'prefix', package.name)
|
354
|
+
return srcdir, builddir, prefix
|
355
|
+
end
|
356
|
+
|
357
|
+
def ws_create_git_package_set(name, source_data = Hash.new)
|
358
|
+
dir = make_tmpdir
|
359
|
+
if !system('git', 'init', chdir: dir, out: :close)
|
360
|
+
raise "failed to run git init"
|
361
|
+
end
|
362
|
+
File.open(File.join(dir, 'source.yml'), 'w') do |io|
|
363
|
+
YAML.dump(Hash['name' => name].merge(source_data), io)
|
364
|
+
end
|
365
|
+
if !system('git', 'add', 'source.yml', chdir: dir, out: :close)
|
366
|
+
raise "failed to add the source.yml"
|
367
|
+
end
|
368
|
+
if !system('git', 'commit', '-m', 'add source.yml', chdir: dir, out: :close)
|
369
|
+
raise "failed to commit the source.yml"
|
370
|
+
end
|
371
|
+
dir
|
372
|
+
end
|
220
373
|
end
|
221
374
|
end
|
222
375
|
|
@@ -26,40 +26,15 @@ def self.flatten_recursive_hash(hash, prefix = "")
|
|
26
26
|
result
|
27
27
|
end
|
28
28
|
|
29
|
-
# Expand build options in +value+.
|
30
|
-
#
|
31
|
-
# The method will expand in +value+ patterns of the form $NAME, replacing
|
32
|
-
# them with the corresponding build option.
|
33
|
-
def self.expand_environment(value)
|
34
|
-
return value if !contains_expansion?(value)
|
35
|
-
|
36
|
-
# Perform constant expansion on the defined environment variables,
|
37
|
-
# including the option set
|
38
|
-
options = flatten_recursive_hash(config.validated_values)
|
39
|
-
|
40
|
-
loop do
|
41
|
-
new_value = single_expansion(value, options)
|
42
|
-
if new_value == value
|
43
|
-
break
|
44
|
-
else
|
45
|
-
value = new_value
|
46
|
-
end
|
47
|
-
end
|
48
|
-
value
|
49
|
-
end
|
50
|
-
|
51
29
|
# Does a non-recursive expansion in +data+ of configuration variables
|
52
30
|
# ($VAR_NAME) listed in +definitions+
|
53
31
|
#
|
54
32
|
# If the values listed in +definitions+ also contain configuration
|
55
33
|
# variables, they do not get expanded
|
56
|
-
def self.single_expansion(data, definitions
|
57
|
-
options = Kernel.validate_options options, config: Autoproj.config
|
58
|
-
|
34
|
+
def self.single_expansion(data, definitions)
|
59
35
|
if !data.respond_to?(:to_str)
|
60
36
|
return data
|
61
37
|
end
|
62
|
-
definitions = { 'HOME' => ENV['HOME'] }.merge(definitions)
|
63
38
|
|
64
39
|
data = data.gsub(/(.|^)\$(\w+)/) do |constant_name|
|
65
40
|
prefix = constant_name[0, 1]
|
@@ -72,11 +47,10 @@ def self.single_expansion(data, definitions, options = Hash.new)
|
|
72
47
|
constant_name = constant_name[2..-1]
|
73
48
|
end
|
74
49
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
50
|
+
value = definitions[constant_name]
|
51
|
+
if value.nil?
|
52
|
+
if !block_given? || !(value = yield(constant_name))
|
53
|
+
raise ArgumentError, "cannot find a definition for $#{constant_name}"
|
80
54
|
end
|
81
55
|
end
|
82
56
|
"#{prefix}#{value}"
|
@@ -109,8 +83,9 @@ def self.expand(value, definitions = Hash.new)
|
|
109
83
|
def self.contains_expansion?(string); string =~ /\$/ end
|
110
84
|
|
111
85
|
def self.resolve_one_constant(name, value, result, definitions)
|
112
|
-
result[name]
|
113
|
-
result[missing_name] =
|
86
|
+
result[name] ||= single_expansion(value, result) do |missing_name|
|
87
|
+
result[missing_name] =
|
88
|
+
resolve_one_constant(missing_name, definitions[missing_name], result, definitions)
|
114
89
|
end
|
115
90
|
end
|
116
91
|
|
@@ -118,17 +93,15 @@ def self.resolve_one_constant(name, value, result, definitions)
|
|
118
93
|
#
|
119
94
|
# I.e. replaces variables by their values, so that no value in +constants+
|
120
95
|
# refers to variables defined in +constants+
|
121
|
-
def self.resolve_constant_definitions(constants)
|
122
|
-
|
123
|
-
constants['HOME'] = ENV['HOME']
|
96
|
+
def self.resolve_constant_definitions(constants, definitions = Hash.new)
|
97
|
+
definitions = definitions.merge(constants)
|
124
98
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
resolve_one_constant(name, value, result, constants)
|
99
|
+
all_resolutions = Hash.new
|
100
|
+
resolution_cache = Hash.new
|
101
|
+
constants.each do |key, value|
|
102
|
+
all_resolutions[key] = resolve_one_constant(key, value, resolution_cache, definitions)
|
130
103
|
end
|
131
|
-
|
104
|
+
all_resolutions
|
132
105
|
end
|
133
106
|
end
|
134
107
|
|
@@ -22,36 +22,39 @@ class VCSDefinition
|
|
22
22
|
# i.e. the list of VCSDefinition objects that led to this one by means
|
23
23
|
# of calls to {#update}
|
24
24
|
#
|
25
|
-
# @return [Array<
|
25
|
+
# @return [Array<HistoryEntry>]
|
26
26
|
attr_reader :history
|
27
27
|
|
28
28
|
# The original spec in hash form
|
29
29
|
#
|
30
|
-
#
|
31
|
-
# VCSDefinition.from_raw
|
32
|
-
#
|
33
|
-
# @return [nil,Hash]
|
30
|
+
# @return [Array<RawEntry>]
|
34
31
|
attr_reader :raw
|
35
32
|
|
36
|
-
|
37
|
-
|
33
|
+
HistoryEntry = Struct.new :package_set, :vcs
|
34
|
+
RawEntry = Struct.new :package_set, :file, :vcs
|
35
|
+
|
36
|
+
def initialize(type, url, vcs_options, from: nil, raw: Array.new, history: Array.new)
|
37
|
+
if !raw.respond_to?(:to_ary)
|
38
38
|
raise ArgumentError, "wrong format for the raw field (#{raw.inspect})"
|
39
39
|
end
|
40
|
-
if !options.kind_of?(Hash)
|
41
|
-
options = Hash[raw: options]
|
42
|
-
end
|
43
|
-
if vcs_options[:raw]
|
44
|
-
raise
|
45
|
-
end
|
46
|
-
options = validate_options options, from: nil, raw: nil, history: nil
|
47
40
|
|
48
41
|
@type, @url, @options = type, url, vcs_options
|
49
42
|
if type != "none" && type != "local" && !Autobuild.respond_to?(type)
|
50
43
|
raise ConfigError.new, "version control #{type} is unknown to autoproj"
|
51
44
|
end
|
52
45
|
|
53
|
-
@history =
|
54
|
-
@raw
|
46
|
+
@history = history + [HistoryEntry.new(from, self)]
|
47
|
+
@raw = raw
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create a null VCS object
|
51
|
+
def self.none
|
52
|
+
from_raw(type: 'none')
|
53
|
+
end
|
54
|
+
|
55
|
+
# Whether there is actually a version control definition
|
56
|
+
def none?
|
57
|
+
@type == 'none'
|
55
58
|
end
|
56
59
|
|
57
60
|
# Whether this points to a local directory
|
@@ -70,21 +73,16 @@ def to_hash
|
|
70
73
|
# the updated definition
|
71
74
|
#
|
72
75
|
# @return [VCSDefinition]
|
73
|
-
def update(spec,
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
from, options = filter_options options, from: nil, raw: nil
|
78
|
-
from = from[:from]
|
79
|
-
new = self.class.vcs_definition_to_hash(spec)
|
80
|
-
new_raw = options[:raw] || [[from, spec]]
|
76
|
+
def update(spec, from: nil, raw: Array.new)
|
77
|
+
new = self.class.normalize_vcs_hash(spec)
|
78
|
+
new_raw = Array.new
|
81
79
|
new_history = Array.new
|
82
80
|
|
83
81
|
# If the type changed, we replace the old definition by the new one
|
84
82
|
# completely. Otherwise, we append it to the current one
|
85
83
|
if !new.has_key?(:type) || (type == new[:type])
|
86
84
|
new = to_hash.merge(new)
|
87
|
-
new_raw = self.raw +
|
85
|
+
new_raw = self.raw + raw
|
88
86
|
new_history = self.history
|
89
87
|
end
|
90
88
|
self.class.from_raw(new, from: from, history: new_history, raw: new_raw)
|
@@ -95,9 +93,9 @@ def update(spec, options = Hash.new)
|
|
95
93
|
#
|
96
94
|
# Both +old+ and +new+ are supposed to be in hash form. It is assumed
|
97
95
|
# that +old+ has already been normalized by a call to
|
98
|
-
# {.
|
96
|
+
# {.normalize_vcs_hash}. +new+ can be in "raw" form.
|
99
97
|
def self.update_raw_vcs_spec(old, new)
|
100
|
-
new =
|
98
|
+
new = normalize_vcs_hash(new)
|
101
99
|
if new.has_key?(:type) && (old[:type] != new[:type])
|
102
100
|
# The type changed. We replace the old definition by the new one
|
103
101
|
# completely, and we make sure that the new definition is valid
|
@@ -115,7 +113,7 @@ def self.update_raw_vcs_spec(old, new)
|
|
115
113
|
#
|
116
114
|
# - package_name
|
117
115
|
# branch: value
|
118
|
-
def self.
|
116
|
+
def self.normalize_vcs_hash(spec, base_dir: nil)
|
119
117
|
plain = Array.new
|
120
118
|
filtered_spec = Hash.new
|
121
119
|
|
@@ -141,24 +139,26 @@ def self.vcs_definition_to_hash(spec)
|
|
141
139
|
# shortcut. If it is not, look for a local directory called
|
142
140
|
# short_url
|
143
141
|
if Autobuild.respond_to?(vcs)
|
144
|
-
spec.merge!(:
|
142
|
+
spec.merge!(type: vcs, url: url.join(':'))
|
145
143
|
elsif Autoproj.has_source_handler?(vcs)
|
146
144
|
spec = Autoproj.call_source_handler(vcs, url.join(':'), spec)
|
147
145
|
else
|
148
146
|
source_dir =
|
149
147
|
if Pathname.new(short_url).absolute?
|
150
148
|
File.expand_path(short_url)
|
149
|
+
elsif base_dir
|
150
|
+
File.expand_path(short_url, base_dir)
|
151
151
|
else
|
152
|
-
|
152
|
+
raise ArgumentError, "VCS path '#{short_url}' is relative and no base_dir was given"
|
153
153
|
end
|
154
154
|
if !File.directory?(source_dir)
|
155
|
-
raise
|
155
|
+
raise ArgumentError, "'#{short_url}' is neither a remote source specification, nor an existing local directory"
|
156
156
|
end
|
157
|
-
spec.merge!(:
|
157
|
+
spec.merge!(type: 'local', url: source_dir)
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
-
spec, vcs_options = Kernel.filter_options spec, :
|
161
|
+
spec, vcs_options = Kernel.filter_options spec, type: nil, url: nil
|
162
162
|
spec.merge!(vcs_options)
|
163
163
|
if !spec[:url]
|
164
164
|
# Verify that none of the keys are source handlers. If it is the
|
@@ -176,6 +176,13 @@ def self.vcs_definition_to_hash(spec)
|
|
176
176
|
spec
|
177
177
|
end
|
178
178
|
|
179
|
+
# @api private
|
180
|
+
#
|
181
|
+
# Converts a raw spec (a hash, really) into a nicely formatted string
|
182
|
+
def self.raw_spec_to_s(spec)
|
183
|
+
"{ #{spec.sort_by(&:first).map { |k, v| "#{k}: #{v}" }.join(", ")} }"
|
184
|
+
end
|
185
|
+
|
179
186
|
# Converts a 'raw' VCS representation to a normalized hash.
|
180
187
|
#
|
181
188
|
# The raw definition can have three forms:
|
@@ -186,29 +193,30 @@ def self.vcs_definition_to_hash(spec)
|
|
186
193
|
# @return [VCSDefinition]
|
187
194
|
# @raise ArgumentError if the raw specification does not match an
|
188
195
|
# expected format
|
189
|
-
def self.from_raw(spec,
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
spec = vcs_definition_to_hash(spec)
|
199
|
-
if !(spec[:type] && (spec[:type] == 'none' || spec[:url]))
|
200
|
-
raise ConfigError.new, "the source specification #{spec.inspect} misses either the VCS type or an URL"
|
196
|
+
def self.from_raw(spec, from: nil, raw: Array.new, history: Array.new)
|
197
|
+
normalized_spec = normalize_vcs_hash(spec)
|
198
|
+
if !(type = normalized_spec.delete(:type))
|
199
|
+
raise ArgumentError, "the source specification #{raw_spec_to_s(spec)} normalizes into #{raw_spec_to_s(normalized_spec)}, which does not have a VCS type"
|
200
|
+
elsif !(url = normalized_spec.delete(:url))
|
201
|
+
if type != 'none'
|
202
|
+
raise ArgumentError, "the source specification #{raw_spec_to_s(spec)} normalizes into #{raw_spec_to_s(normalized_spec)}, which does not have a URL. Only VCS of type 'none' do not require one"
|
203
|
+
end
|
201
204
|
end
|
202
205
|
|
203
|
-
|
204
|
-
return VCSDefinition.new(spec[:type], spec[:url], vcs_options, from: from, history: history, raw: raw)
|
206
|
+
VCSDefinition.new(type, url, normalized_spec, from: from, history: history, raw: raw)
|
205
207
|
end
|
206
208
|
|
207
209
|
def ==(other_vcs)
|
208
210
|
return false if !other_vcs.kind_of?(VCSDefinition)
|
209
211
|
if local?
|
210
|
-
other_vcs.local? && url ==
|
211
|
-
elsif
|
212
|
+
other_vcs.local? && url == other_vcs.url
|
213
|
+
elsif other_vcs.local?
|
214
|
+
false
|
215
|
+
elsif none?
|
216
|
+
other_vcs.none?
|
217
|
+
elsif other_vcs.none?
|
218
|
+
false
|
219
|
+
else
|
212
220
|
this_importer = create_autobuild_importer
|
213
221
|
other_importer = other_vcs.create_autobuild_importer
|
214
222
|
this_importer.source_id == other_importer.source_id
|
@@ -223,14 +231,11 @@ def eql?(other_vcs)
|
|
223
231
|
to_hash == other_vcs.to_hash
|
224
232
|
end
|
225
233
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
url = Autoproj.single_expansion(url, 'HOME' => ENV['HOME'])
|
232
|
-
if url && url !~ /^(\w+:\/)?\/|^[:\w]+\@|^(\w+\@)?[\w\.-]+:/
|
233
|
-
url = File.expand_path(url, root_dir || Autoproj.root_dir)
|
234
|
+
ABSOLUTE_PATH_OR_URI = /^([\w+]+:\/)?\/|^[:\w]+\@|^(\w+\@)?[\w\.-]+:/
|
235
|
+
|
236
|
+
def self.to_absolute_url(url, root_dir)
|
237
|
+
if url && url !~ ABSOLUTE_PATH_OR_URI
|
238
|
+
url = File.expand_path(url, root_dir)
|
234
239
|
end
|
235
240
|
url
|
236
241
|
end
|
@@ -240,6 +245,15 @@ def needs_import?
|
|
240
245
|
type != 'none' && type != 'local'
|
241
246
|
end
|
242
247
|
|
248
|
+
def overrides_key
|
249
|
+
return if none?
|
250
|
+
if local?
|
251
|
+
"local:#{url}"
|
252
|
+
else
|
253
|
+
create_autobuild_importer.repository_id
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
243
257
|
# Returns a properly configured instance of a subclass of
|
244
258
|
# Autobuild::Importer that match this VCS definition
|
245
259
|
#
|
@@ -247,13 +261,13 @@ def needs_import?
|
|
247
261
|
def create_autobuild_importer
|
248
262
|
return if !needs_import?
|
249
263
|
|
250
|
-
url = VCSDefinition.to_absolute_url(self.url)
|
251
264
|
importer = Autobuild.send(type, url, options)
|
252
265
|
if importer.respond_to?(:declare_alternate_repository)
|
253
|
-
history.each do |
|
254
|
-
|
255
|
-
|
256
|
-
|
266
|
+
history.each do |entry|
|
267
|
+
package_set = entry.package_set
|
268
|
+
vcs = entry.vcs
|
269
|
+
next if !package_set || package_set.main?
|
270
|
+
importer.declare_alternate_repository(package_set.name, vcs.url, vcs.options)
|
257
271
|
end
|
258
272
|
end
|
259
273
|
importer
|
@@ -295,30 +309,33 @@ def self.call_source_handler(vcs, url, options)
|
|
295
309
|
end
|
296
310
|
end
|
297
311
|
|
298
|
-
# call-seq:
|
299
|
-
# Autoproj.add_source_handler name do |url, options|
|
300
|
-
# # build a hash that represent source configuration
|
301
|
-
# # and return it
|
302
|
-
# end
|
303
|
-
#
|
304
312
|
# Add a custom source handler named +name+
|
305
313
|
#
|
306
314
|
# Custom source handlers are shortcuts that can be used to represent VCS
|
307
|
-
# information. For instance, the
|
308
|
-
#
|
309
|
-
#
|
310
|
-
# gitorious_server_configuration 'GITORIOUS', 'gitorious.org'
|
315
|
+
# information. For instance, the {Autoproj.git_server_configuration} helper defines a
|
316
|
+
# source handler that allows to easily add new github packages:
|
311
317
|
#
|
312
|
-
#
|
318
|
+
# Autoproj.git_server_configuration('GITHUB', 'github.com',
|
319
|
+
# http_url: 'https://github.com',
|
320
|
+
# default: 'http,ssh')
|
313
321
|
#
|
322
|
+
# Defines a 'github' custom handler that expands into the full VCS
|
323
|
+
# configuration to access github
|
314
324
|
#
|
315
325
|
# version_control:
|
316
|
-
# - tools/orocos.rb
|
317
|
-
#
|
326
|
+
# - tools/orocos.rb:
|
327
|
+
# github: rock-core/base-types
|
318
328
|
# branch: test
|
319
|
-
#
|
320
329
|
#
|
330
|
+
# @yieldparam [String] url the url given to the handler
|
331
|
+
# @yieldparam [Hash] the rest of the VCS hash
|
332
|
+
# @return [Hash] a VCS hash with the information expanded
|
321
333
|
def self.add_source_handler(name, &handler)
|
322
334
|
@custom_source_handlers[name.to_s] = lambda(&handler)
|
323
335
|
end
|
336
|
+
|
337
|
+
# Deregister a source handler defined with {.add_source_handler}
|
338
|
+
def self.remove_source_handler(name)
|
339
|
+
@custom_source_handlers.delete(name)
|
340
|
+
end
|
324
341
|
end
|