autoproj 2.11.0 → 2.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -8
- data/.travis.yml +5 -3
- data/autoproj.gemspec +6 -6
- data/bin/alog +1 -0
- data/bin/autoproj +1 -1
- data/bin/autoproj_bootstrap +130 -67
- data/bin/autoproj_bootstrap.in +9 -7
- data/bin/autoproj_install +129 -63
- data/bin/autoproj_install.in +8 -3
- data/lib/autoproj/autobuild_extensions/dsl.rb +27 -12
- data/lib/autoproj/base.rb +18 -0
- data/lib/autoproj/cli/base.rb +1 -1
- data/lib/autoproj/cli/build.rb +8 -3
- data/lib/autoproj/cli/cache.rb +79 -7
- data/lib/autoproj/cli/inspection_tool.rb +5 -6
- data/lib/autoproj/cli/main.rb +33 -9
- data/lib/autoproj/cli/show.rb +12 -18
- data/lib/autoproj/cli/status.rb +15 -9
- data/lib/autoproj/cli/test.rb +1 -1
- data/lib/autoproj/cli/update.rb +72 -17
- data/lib/autoproj/cli/utility.rb +25 -28
- data/lib/autoproj/configuration.rb +15 -4
- data/lib/autoproj/default.osdeps +29 -3
- data/lib/autoproj/environment.rb +17 -13
- data/lib/autoproj/installation_manifest.rb +7 -5
- data/lib/autoproj/manifest.rb +14 -6
- data/lib/autoproj/ops/build.rb +23 -21
- data/lib/autoproj/ops/cache.rb +151 -33
- data/lib/autoproj/ops/cached_env.rb +2 -2
- data/lib/autoproj/ops/import.rb +23 -4
- data/lib/autoproj/ops/install.rb +121 -60
- data/lib/autoproj/ops/phase_reporting.rb +49 -0
- data/lib/autoproj/ops/snapshot.rb +2 -1
- data/lib/autoproj/ops/tools.rb +2 -2
- data/lib/autoproj/os_package_installer.rb +19 -11
- data/lib/autoproj/package_definition.rb +1 -1
- data/lib/autoproj/package_managers/apt_dpkg_manager.rb +49 -28
- data/lib/autoproj/package_managers/bundler_manager.rb +102 -19
- data/lib/autoproj/package_managers/homebrew_manager.rb +2 -2
- data/lib/autoproj/package_managers/pip_manager.rb +34 -22
- data/lib/autoproj/package_managers/shell_script_manager.rb +44 -24
- data/lib/autoproj/package_manifest.rb +43 -31
- data/lib/autoproj/package_set.rb +2 -2
- data/lib/autoproj/python.rb +285 -0
- data/lib/autoproj/test.rb +26 -10
- data/lib/autoproj/variable_expansion.rb +3 -1
- data/lib/autoproj/vcs_definition.rb +25 -12
- data/lib/autoproj/version.rb +1 -1
- data/lib/autoproj/workspace.rb +60 -16
- data/lib/autoproj.rb +3 -0
- metadata +17 -28
data/lib/autoproj/manifest.rb
CHANGED
@@ -50,12 +50,19 @@ module Autoproj
|
|
50
50
|
|
51
51
|
# Load the manifest data contained in +file+
|
52
52
|
def load(file)
|
53
|
-
|
54
|
-
raise ConfigError.new(File.dirname(file)),
|
53
|
+
unless File.exist?(file)
|
54
|
+
raise ConfigError.new(File.dirname(file)),
|
55
|
+
"expected an autoproj configuration in #{File.dirname(file)}, "\
|
56
|
+
"but #{file} does not exist"
|
55
57
|
end
|
56
58
|
|
57
59
|
data = Autoproj.in_file(file, Autoproj::YAML_LOAD_ERROR) do
|
58
|
-
YAML.
|
60
|
+
YAML.safe_load(File.read(file)) || {}
|
61
|
+
end
|
62
|
+
|
63
|
+
if data["layout"]&.member?(nil)
|
64
|
+
Autoproj.warn "There is an empty entry in your layout in #{file}. All empty entries are ignored."
|
65
|
+
data["layout"] = data["layout"].compact
|
59
66
|
end
|
60
67
|
|
61
68
|
@file = file
|
@@ -81,7 +88,8 @@ module Autoproj
|
|
81
88
|
@has_layout = !!data['layout']
|
82
89
|
|
83
90
|
if data['constants']
|
84
|
-
@constant_definitions =
|
91
|
+
@constant_definitions =
|
92
|
+
Autoproj.resolve_constant_definitions(data['constants'])
|
85
93
|
end
|
86
94
|
end
|
87
95
|
|
@@ -1234,7 +1242,7 @@ module Autoproj
|
|
1234
1242
|
workspace.config
|
1235
1243
|
end
|
1236
1244
|
|
1237
|
-
def self.add_osdeps_overrides(*args, &block)
|
1238
|
-
manifest.add_osdeps_overrides(*args, &block)
|
1245
|
+
def self.add_osdeps_overrides(*args, **kw, &block)
|
1246
|
+
manifest.add_osdeps_overrides(*args, **kw, &block)
|
1239
1247
|
end
|
1240
1248
|
end
|
data/lib/autoproj/ops/build.rb
CHANGED
@@ -87,34 +87,36 @@ module Autoproj
|
|
87
87
|
# names of the packages that should be rebuilt
|
88
88
|
# @return [void]
|
89
89
|
def build_packages(all_enabled_packages, options = Hash.new)
|
90
|
+
if @report_path
|
91
|
+
reporting = Ops::PhaseReporting.new(
|
92
|
+
'build', @report_path, method(:package_metadata)
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
90
96
|
Autobuild.do_rebuild = false
|
91
97
|
Autobuild.do_forced_build = false
|
98
|
+
reporting&.initialize_incremental_report
|
92
99
|
begin
|
93
|
-
Autobuild.apply(
|
100
|
+
Autobuild.apply(
|
101
|
+
all_enabled_packages,
|
102
|
+
"autoproj-build", ['build'], options
|
103
|
+
) do |pkg, phase|
|
104
|
+
reporting&.report_incremental(pkg) if phase == 'build'
|
105
|
+
end
|
106
|
+
|
94
107
|
ensure
|
95
|
-
|
108
|
+
packages = all_enabled_packages.map do |name|
|
109
|
+
@manifest.find_autobuild_package(name)
|
110
|
+
end
|
111
|
+
reporting&.create_report(packages)
|
96
112
|
end
|
97
113
|
end
|
98
114
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
h[pkg.name] = {
|
106
|
-
invoked: !!pkg.install_invoked?,
|
107
|
-
success: !!pkg.installed?
|
108
|
-
}
|
109
|
-
end
|
110
|
-
|
111
|
-
report = JSON.pretty_generate({
|
112
|
-
build_report: {
|
113
|
-
timestamp: Time.now,
|
114
|
-
packages: packages
|
115
|
-
}
|
116
|
-
})
|
117
|
-
IO.write(@report_path, report)
|
115
|
+
def package_metadata(autobuild_package)
|
116
|
+
{
|
117
|
+
invoked: !!autobuild_package.install_invoked?,
|
118
|
+
success: !!autobuild_package.installed?
|
119
|
+
}
|
118
120
|
end
|
119
121
|
end
|
120
122
|
end
|
data/lib/autoproj/ops/cache.rb
CHANGED
@@ -4,9 +4,10 @@ module Autoproj
|
|
4
4
|
attr_reader :cache_dir
|
5
5
|
attr_reader :manifest
|
6
6
|
|
7
|
-
def initialize(cache_dir,
|
7
|
+
def initialize(cache_dir, ws)
|
8
8
|
@cache_dir = cache_dir
|
9
|
-
@
|
9
|
+
@ws = ws
|
10
|
+
@manifest = ws.manifest
|
10
11
|
end
|
11
12
|
|
12
13
|
def with_retry(count)
|
@@ -27,29 +28,39 @@ module Autoproj
|
|
27
28
|
File.join(cache_dir, 'git')
|
28
29
|
end
|
29
30
|
|
30
|
-
def cache_git(pkg,
|
31
|
+
def cache_git(pkg, checkout_only: false)
|
31
32
|
pkg.importdir = File.join(git_cache_dir, pkg.name)
|
32
|
-
if
|
33
|
-
return
|
34
|
-
end
|
33
|
+
return if checkout_only && File.directory?(pkg.importdir)
|
35
34
|
|
36
35
|
pkg.importer.local_branch = nil
|
37
36
|
pkg.importer.remote_branch = nil
|
38
37
|
pkg.importer.remote_name = 'autobuild'
|
39
38
|
|
40
|
-
|
39
|
+
unless File.directory?(pkg.importdir)
|
41
40
|
FileUtils.mkdir_p File.dirname(pkg.importdir)
|
42
|
-
Autobuild::Subprocess.run(
|
41
|
+
Autobuild::Subprocess.run(
|
42
|
+
"autoproj-cache", "import", Autobuild.tool(:git),
|
43
|
+
"--git-dir", pkg.importdir, 'init', "--bare"
|
44
|
+
)
|
43
45
|
end
|
44
46
|
pkg.importer.update_remotes_configuration(pkg)
|
45
47
|
|
46
48
|
with_retry(10) do
|
47
|
-
Autobuild::Subprocess.run(
|
49
|
+
Autobuild::Subprocess.run(
|
50
|
+
'autoproj-cache', :import, Autobuild.tool('git'),
|
51
|
+
'--git-dir', pkg.importdir, 'remote', 'update', 'autobuild'
|
52
|
+
)
|
48
53
|
end
|
49
54
|
with_retry(10) do
|
50
|
-
Autobuild::Subprocess.run(
|
55
|
+
Autobuild::Subprocess.run(
|
56
|
+
'autoproj-cache', :import, Autobuild.tool('git'),
|
57
|
+
'--git-dir', pkg.importdir, 'fetch', 'autobuild', '--tags'
|
58
|
+
)
|
51
59
|
end
|
52
|
-
Autobuild::Subprocess.run(
|
60
|
+
Autobuild::Subprocess.run(
|
61
|
+
'autoproj-cache', :import, Autobuild.tool('git'),
|
62
|
+
'--git-dir', pkg.importdir, 'gc', '--prune=all'
|
63
|
+
)
|
53
64
|
end
|
54
65
|
|
55
66
|
def archive_cache_dir
|
@@ -63,7 +74,8 @@ module Autoproj
|
|
63
74
|
end
|
64
75
|
end
|
65
76
|
|
66
|
-
def create_or_update(*package_names, all: true, keep_going: false,
|
77
|
+
def create_or_update(*package_names, all: true, keep_going: false,
|
78
|
+
checkout_only: false)
|
67
79
|
FileUtils.mkdir_p cache_dir
|
68
80
|
|
69
81
|
if package_names.empty?
|
@@ -75,7 +87,7 @@ module Autoproj
|
|
75
87
|
end
|
76
88
|
else
|
77
89
|
packages = package_names.map do |name|
|
78
|
-
if pkg = manifest.find_autobuild_package(name)
|
90
|
+
if (pkg = manifest.find_autobuild_package(name))
|
79
91
|
pkg
|
80
92
|
else
|
81
93
|
raise PackageNotFound, "no package named #{name}"
|
@@ -88,42 +100,148 @@ module Autoproj
|
|
88
100
|
total = packages.size
|
89
101
|
Autoproj.message "Handling #{total} packages"
|
90
102
|
packages.each_with_index do |pkg, i|
|
91
|
-
|
103
|
+
# No need to process this one, it is uses another package's
|
104
|
+
# import
|
105
|
+
next if pkg.srcdir != pkg.importdir
|
106
|
+
|
92
107
|
begin
|
93
108
|
case pkg.importer
|
94
109
|
when Autobuild::Git
|
95
|
-
Autoproj.message
|
110
|
+
Autoproj.message(
|
111
|
+
" [#{i}/#{total}] caching #{pkg.name} (git)"
|
112
|
+
)
|
96
113
|
cache_git(pkg, checkout_only: checkout_only)
|
97
114
|
when Autobuild::ArchiveImporter
|
98
|
-
Autoproj.message
|
115
|
+
Autoproj.message(
|
116
|
+
" [#{i}/#{total}] caching #{pkg.name} (archive)"
|
117
|
+
)
|
99
118
|
cache_archive(pkg)
|
100
119
|
else
|
101
|
-
Autoproj.message
|
120
|
+
Autoproj.message(
|
121
|
+
" [#{i}/#{total}] not caching #{pkg.name} "\
|
122
|
+
"(cannot cache #{pkg.importer.class})"
|
123
|
+
)
|
102
124
|
end
|
103
125
|
rescue Interrupt
|
104
126
|
raise
|
105
127
|
rescue ::Exception => e
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
pkg.message(
|
116
|
-
|
117
|
-
|
128
|
+
raise unless keep_going
|
129
|
+
|
130
|
+
pkg.error " failed to cache #{pkg.name}, "\
|
131
|
+
'but going on as requested'
|
132
|
+
lines = e.to_s.split('\n')
|
133
|
+
lines = e.message.split('\n') if lines.empty?
|
134
|
+
lines = ['unknown error'] if lines.empty?
|
135
|
+
pkg.message(lines.shift, :red, :bold)
|
136
|
+
lines.each do |line|
|
137
|
+
pkg.message(line)
|
138
|
+
end
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def gems_cache_dir
|
145
|
+
File.join(cache_dir, 'package_managers', 'gem')
|
146
|
+
end
|
147
|
+
|
148
|
+
def create_or_update_gems(keep_going: true, compile_force: false, compile: [])
|
149
|
+
# Note: this might directly copy into the cache directoy, and
|
150
|
+
# we support it later
|
151
|
+
cache_dir = File.join(@ws.prefix_dir, 'gems', 'vendor', 'cache')
|
152
|
+
PackageManagers::BundlerManager.run_bundler(
|
153
|
+
@ws, 'cache'
|
154
|
+
)
|
155
|
+
|
156
|
+
FileUtils.mkdir_p(gems_cache_dir) unless File.exist?(gems_cache_dir)
|
157
|
+
|
158
|
+
needs_copy =
|
159
|
+
if File.exist?(cache_dir)
|
160
|
+
real_cache_dir = File.realpath(cache_dir)
|
161
|
+
real_target_dir = File.realpath(gems_cache_dir)
|
162
|
+
(real_cache_dir != real_target_dir)
|
163
|
+
end
|
164
|
+
|
165
|
+
synchronize_gems_cache_dirs(real_cache_dir, real_target_dir) if needs_copy
|
166
|
+
|
167
|
+
platform_suffix = "-#{Gem::Platform.local}.gem"
|
168
|
+
failed = []
|
169
|
+
compile.each do |gem_name, artifacts: []|
|
170
|
+
Dir.glob(File.join(cache_dir, "#{gem_name}*.gem")) do |gem|
|
171
|
+
next if gem.end_with?(platform_suffix)
|
172
|
+
|
173
|
+
gem_basename = File.basename(gem, ".gem")
|
174
|
+
expected_platform_gem = File.join(
|
175
|
+
real_target_dir, "#{gem_basename}#{platform_suffix}"
|
176
|
+
)
|
177
|
+
next if !compile_force && File.file?(expected_platform_gem)
|
178
|
+
|
179
|
+
begin
|
180
|
+
compile_gem(
|
181
|
+
gem, artifacts: artifacts, output: real_target_dir
|
182
|
+
)
|
183
|
+
rescue CompilationFailed
|
184
|
+
unless keep_going
|
185
|
+
raise CompilationFailed, "#{gem} failed to compile"
|
118
186
|
end
|
119
|
-
|
120
|
-
|
121
|
-
raise
|
187
|
+
|
188
|
+
failed << gem
|
122
189
|
end
|
123
190
|
end
|
124
191
|
end
|
192
|
+
|
193
|
+
unless failed.empty?
|
194
|
+
raise CompilationFailed, "#{failed.sort.join(', ')} failed to compile"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class CompilationFailed < RuntimeError; end
|
199
|
+
|
200
|
+
def synchronize_gems_cache_dirs(source, target)
|
201
|
+
Dir.glob(File.join(source, "*.gem")) do |source_file|
|
202
|
+
basename = File.basename(source_file)
|
203
|
+
target_file = File.join(target, basename)
|
204
|
+
next if File.file?(target_file)
|
205
|
+
|
206
|
+
Autoproj.message "gems: caching #{basename}"
|
207
|
+
FileUtils.cp source_file, target_file
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def guess_gem_program
|
212
|
+
return Autobuild.programs['gem'] if Autobuild.programs['gem']
|
213
|
+
|
214
|
+
ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
|
215
|
+
ruby_bindir = RbConfig::CONFIG['bindir']
|
216
|
+
|
217
|
+
candidates = ['gem']
|
218
|
+
candidates << "gem#{$1}" if ruby_bin =~ /^ruby(.+)$/
|
219
|
+
|
220
|
+
candidates.each do |gem_name|
|
221
|
+
if File.file?(gem_full_path = File.join(ruby_bindir, gem_name))
|
222
|
+
Autobuild.programs['gem'] = gem_full_path
|
223
|
+
return Autobuild.programs['gem']
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
raise ArgumentError,
|
228
|
+
'cannot find a gem program (tried '\
|
229
|
+
"#{candidates.sort.join(', ')} in #{ruby_bindir})"
|
230
|
+
end
|
231
|
+
|
232
|
+
private def compile_gem(gem_path, output:, artifacts: [])
|
233
|
+
artifacts = artifacts.flat_map do |include, n|
|
234
|
+
if include
|
235
|
+
["--include", n]
|
236
|
+
else
|
237
|
+
["--exclude", n]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
unless system(Autobuild.tool('ruby'), '-S', guess_gem_program,
|
241
|
+
'compile', '--output', output, *artifacts, gem_path)
|
242
|
+
raise CompilationFailed, "#{gem_path} failed to compile"
|
243
|
+
end
|
125
244
|
end
|
126
245
|
end
|
127
246
|
end
|
128
247
|
end
|
129
|
-
|
@@ -9,7 +9,7 @@ module Autoproj
|
|
9
9
|
def self.load_cached_env(root_dir)
|
10
10
|
path = cached_env_path(root_dir)
|
11
11
|
if File.file?(path)
|
12
|
-
env = YAML.
|
12
|
+
env = YAML.safe_load(File.read(path))
|
13
13
|
Autobuild::Environment::ExportedEnvironment.new(
|
14
14
|
env['set'], env['unset'], env['update'])
|
15
15
|
end
|
@@ -20,7 +20,7 @@ module Autoproj
|
|
20
20
|
path = cached_env_path(root_dir)
|
21
21
|
existing =
|
22
22
|
begin
|
23
|
-
YAML.
|
23
|
+
YAML.safe_load(File.read(path))
|
24
24
|
rescue Exception
|
25
25
|
end
|
26
26
|
|
data/lib/autoproj/ops/import.rb
CHANGED
@@ -199,6 +199,7 @@ module Autoproj
|
|
199
199
|
install_vcs_packages: Hash.new,
|
200
200
|
non_imported_packages: :checkout,
|
201
201
|
auto_exclude: auto_exclude?,
|
202
|
+
filter: ->(package) { true },
|
202
203
|
**import_options)
|
203
204
|
|
204
205
|
unless %i[checkout ignore return].include?(non_imported_packages)
|
@@ -235,6 +236,11 @@ module Autoproj
|
|
235
236
|
missing_vcs = Array.new
|
236
237
|
installed_vcs_packages = Set['none', 'local']
|
237
238
|
while failures.empty? || keep_going
|
239
|
+
# Allow 'filter' to parallelize as well
|
240
|
+
if filter.respond_to?(:lookahead)
|
241
|
+
package_queue.each { |pkg| filter.lookahead(pkg) }
|
242
|
+
end
|
243
|
+
|
238
244
|
# Queue work for all packages in the queue
|
239
245
|
package_queue.each do |pkg|
|
240
246
|
# Remove packages that have already been processed
|
@@ -255,6 +261,11 @@ module Autoproj
|
|
255
261
|
end
|
256
262
|
all_processed_packages << pkg
|
257
263
|
|
264
|
+
unless filter.call(pkg)
|
265
|
+
completion_queue << [pkg, Time.now]
|
266
|
+
next
|
267
|
+
end
|
268
|
+
|
258
269
|
importer = pkg.autobuild.importer
|
259
270
|
if !pre_package_import(selection, manifest, pkg.autobuild,
|
260
271
|
reverse_dependencies)
|
@@ -272,8 +283,8 @@ module Autoproj
|
|
272
283
|
next
|
273
284
|
end
|
274
285
|
|
275
|
-
pending_packages << pkg
|
276
286
|
begin
|
287
|
+
pending_packages << pkg
|
277
288
|
queue_import_work(
|
278
289
|
executor, completion_queue, pkg,
|
279
290
|
retry_count: retry_count,
|
@@ -288,8 +299,12 @@ module Autoproj
|
|
288
299
|
if completion_queue.empty? && pending_packages.empty?
|
289
300
|
unless missing_vcs.empty?
|
290
301
|
installed_vcs_packages.merge(
|
291
|
-
install_vcs_packages_for(
|
292
|
-
|
302
|
+
install_vcs_packages_for(
|
303
|
+
*missing_vcs,
|
304
|
+
install_only: import_options[:checkout_only],
|
305
|
+
**install_vcs_packages
|
306
|
+
)
|
307
|
+
)
|
293
308
|
package_queue.concat(missing_vcs)
|
294
309
|
missing_vcs.clear
|
295
310
|
next
|
@@ -366,7 +381,9 @@ module Autoproj
|
|
366
381
|
end
|
367
382
|
end
|
368
383
|
|
369
|
-
def finalize_package_load(processed_packages,
|
384
|
+
def finalize_package_load(processed_packages,
|
385
|
+
ignore_optional_dependencies: false,
|
386
|
+
auto_exclude: auto_exclude?)
|
370
387
|
manifest = ws.manifest
|
371
388
|
|
372
389
|
all = Set.new
|
@@ -426,6 +443,7 @@ module Autoproj
|
|
426
443
|
keep_going: false,
|
427
444
|
install_vcs_packages: Hash.new,
|
428
445
|
auto_exclude: auto_exclude?,
|
446
|
+
filter: ->(pkg) { true },
|
429
447
|
**import_options)
|
430
448
|
|
431
449
|
manifest = ws.manifest
|
@@ -437,6 +455,7 @@ module Autoproj
|
|
437
455
|
recursive: recursive,
|
438
456
|
install_vcs_packages: install_vcs_packages,
|
439
457
|
auto_exclude: auto_exclude,
|
458
|
+
filter: filter,
|
440
459
|
**import_options)
|
441
460
|
|
442
461
|
raise failures.first if !keep_going && !failures.empty?
|
data/lib/autoproj/ops/install.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
require 'optparse'
|
3
5
|
require 'fileutils'
|
4
6
|
require 'yaml'
|
7
|
+
require 'English'
|
5
8
|
|
6
9
|
module Autoproj
|
7
10
|
module Ops
|
@@ -13,6 +16,36 @@ module Autoproj
|
|
13
16
|
class Install
|
14
17
|
class UnexpectedBinstub < RuntimeError; end
|
15
18
|
|
19
|
+
RUBYLIB_REINIT = <<~RUBY
|
20
|
+
if defined?(Bundler)
|
21
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
22
|
+
Bundler.with_unbundled_env do
|
23
|
+
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
24
|
+
end
|
25
|
+
else
|
26
|
+
Bundler.with_clean_env do
|
27
|
+
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
elsif ENV['RUBYLIB']
|
31
|
+
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
32
|
+
end
|
33
|
+
RUBY
|
34
|
+
|
35
|
+
WITHOUT_BUNDLER = <<~RUBY
|
36
|
+
if defined?(Bundler)
|
37
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
38
|
+
Bundler.with_unbundled_env do
|
39
|
+
exec($0, *ARGV)
|
40
|
+
end
|
41
|
+
else
|
42
|
+
Bundler.with_clean_env do
|
43
|
+
exec($0, *ARGV)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
RUBY
|
48
|
+
|
16
49
|
# The created workspace's root directory
|
17
50
|
attr_reader :root_dir
|
18
51
|
# Content of the Gemfile generated to install autoproj itself
|
@@ -220,6 +253,10 @@ module Autoproj
|
|
220
253
|
"gem \"utilrb\", \">= 3.0.1\""].join("\n")
|
221
254
|
end
|
222
255
|
|
256
|
+
def add_seed_config(path)
|
257
|
+
@config.merge!(YAML.safe_load(File.read(path), [Symbol]))
|
258
|
+
end
|
259
|
+
|
223
260
|
# Parse the provided command line options and returns the non-options
|
224
261
|
def parse_options(args = ARGV)
|
225
262
|
options = OptionParser.new do |opt|
|
@@ -243,6 +280,10 @@ module Autoproj
|
|
243
280
|
opt.on '--public-gems', "install gems in the default gem location" do
|
244
281
|
self.install_gems_in_gem_user_dir
|
245
282
|
end
|
283
|
+
opt.on '--bundler-version=VERSION_CONSTRAINT', String, 'use the provided '\
|
284
|
+
'string as a version constraint for bundler' do |version|
|
285
|
+
@config['bundler_version'] = version
|
286
|
+
end
|
246
287
|
opt.on '--version=VERSION_CONSTRAINT', String, 'use the provided '\
|
247
288
|
'string as a version constraint for autoproj' do |version|
|
248
289
|
if @gemfile
|
@@ -257,9 +298,14 @@ module Autoproj
|
|
257
298
|
end
|
258
299
|
@gemfile = File.read(path)
|
259
300
|
end
|
301
|
+
opt.on '--no-seed-config',
|
302
|
+
'when reinstalling an existing autoproj workspace, do not '\
|
303
|
+
'use the config in .autoproj/ as seed' do
|
304
|
+
@config.clear
|
305
|
+
end
|
260
306
|
opt.on '--seed-config=PATH', String, 'path to a seed file that '\
|
261
307
|
'should be used to initialize the configuration' do |path|
|
262
|
-
|
308
|
+
add_seed_config(path)
|
263
309
|
end
|
264
310
|
opt.on '--prefer-os-independent-packages', 'prefer OS-independent '\
|
265
311
|
'packages (such as a RubyGem) over their OS-packaged equivalent '\
|
@@ -289,22 +335,50 @@ module Autoproj
|
|
289
335
|
@autoproj_options + args
|
290
336
|
end
|
291
337
|
|
292
|
-
def
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
return unless $?.success?
|
338
|
+
def bundler_version
|
339
|
+
@config['bundler_version']
|
340
|
+
end
|
341
|
+
|
342
|
+
def find_bundler(gem_program, version: nil)
|
298
343
|
bundler_path = File.join(gems_gem_home, 'bin', 'bundle')
|
299
|
-
|
300
|
-
|
301
|
-
|
344
|
+
return unless File.exist?(bundler_path)
|
345
|
+
|
346
|
+
setup_paths =
|
347
|
+
if version
|
348
|
+
find_versioned_bundler_setup(gem_program, version)
|
349
|
+
else
|
350
|
+
find_unversioned_bundler_setup(gem_program)
|
302
351
|
end
|
352
|
+
|
353
|
+
setup_paths.each do |setup_path|
|
354
|
+
return bundler_path if setup_path.start_with?(gems_gem_home)
|
303
355
|
end
|
304
|
-
|
356
|
+
nil
|
357
|
+
end
|
358
|
+
|
359
|
+
def find_versioned_bundler_setup(gem_program, version)
|
360
|
+
contents = IO.popen(
|
361
|
+
[env_for_child, Gem.ruby, gem_program,
|
362
|
+
'contents', '-v', version, 'bundler'],
|
363
|
+
&:readlines
|
364
|
+
)
|
365
|
+
return [] unless $CHILD_STATUS.success?
|
366
|
+
|
367
|
+
contents.grep(%r{bundler/setup.rb$})
|
368
|
+
end
|
369
|
+
|
370
|
+
def find_unversioned_bundler_setup(gem_program)
|
371
|
+
setup_paths = IO.popen(
|
372
|
+
[env_for_child, Gem.ruby, gem_program,
|
373
|
+
'which', '-a', 'bundler/setup'],
|
374
|
+
&:readlines
|
375
|
+
)
|
376
|
+
return [] unless $CHILD_STATUS.success?
|
377
|
+
|
378
|
+
setup_paths
|
305
379
|
end
|
306
380
|
|
307
|
-
def install_bundler(gem_program, silent: false)
|
381
|
+
def install_bundler(gem_program, version: nil, silent: false)
|
308
382
|
local = ['--local'] if local?
|
309
383
|
|
310
384
|
redirection = Hash.new
|
@@ -312,6 +386,9 @@ module Autoproj
|
|
312
386
|
redirection = Hash[out: :close]
|
313
387
|
end
|
314
388
|
|
389
|
+
version_args = []
|
390
|
+
version_args << '-v' << version if version
|
391
|
+
|
315
392
|
# Shut up the bundler warning about 'bin' not being in PATH
|
316
393
|
env = self.env
|
317
394
|
env['PATH'] += [File.join(gems_gem_home, 'bin')]
|
@@ -322,14 +399,14 @@ module Autoproj
|
|
322
399
|
'--clear-sources', '--source', gem_source,
|
323
400
|
'--no-user-install', '--install-dir', gems_gem_home,
|
324
401
|
*local, "--bindir=#{File.join(gems_gem_home, 'bin')}",
|
325
|
-
'bundler', **redirection)
|
402
|
+
'bundler', *version_args, **redirection)
|
326
403
|
|
327
404
|
if !result
|
328
405
|
STDERR.puts "FATAL: failed to install bundler in #{gems_gem_home}"
|
329
406
|
nil
|
330
407
|
end
|
331
408
|
|
332
|
-
if (bundler_path = find_bundler(gem_program))
|
409
|
+
if (bundler_path = find_bundler(gem_program, version: version))
|
333
410
|
bundler_path
|
334
411
|
else
|
335
412
|
STDERR.puts "gem install bundler returned successfully, but still "\
|
@@ -338,7 +415,7 @@ module Autoproj
|
|
338
415
|
end
|
339
416
|
end
|
340
417
|
|
341
|
-
def install_autoproj(bundler)
|
418
|
+
def install_autoproj(bundler, bundler_version: self.bundler_version)
|
342
419
|
# Force bundler to update. If the user does not want this, let
|
343
420
|
# him specify a Gemfile with tighter version constraints
|
344
421
|
lockfile = File.join(dot_autoproj, 'Gemfile.lock')
|
@@ -353,14 +430,19 @@ module Autoproj
|
|
353
430
|
opts << "--path=#{gems_install_path}"
|
354
431
|
shims_path = File.join(dot_autoproj, 'bin')
|
355
432
|
|
356
|
-
|
357
|
-
|
358
|
-
"--gemfile=#{autoproj_gemfile_path}",
|
359
|
-
"--shebang=#{Gem.ruby}",
|
360
|
-
"--binstubs=#{shims_path}",
|
361
|
-
*opts, chdir: dot_autoproj)
|
433
|
+
version_arg = []
|
434
|
+
version_arg << "_#{bundler_version}_" if bundler_version
|
362
435
|
|
363
|
-
|
436
|
+
result = system(
|
437
|
+
clean_env,
|
438
|
+
Gem.ruby, bundler, *version_arg, 'install',
|
439
|
+
"--gemfile=#{autoproj_gemfile_path}",
|
440
|
+
"--shebang=#{Gem.ruby}",
|
441
|
+
"--binstubs=#{shims_path}",
|
442
|
+
*opts, chdir: dot_autoproj
|
443
|
+
)
|
444
|
+
|
445
|
+
unless result
|
364
446
|
STDERR.puts "FATAL: failed to install autoproj in #{dot_autoproj}"
|
365
447
|
exit 1
|
366
448
|
end
|
@@ -369,7 +451,7 @@ module Autoproj
|
|
369
451
|
root_dir, autoproj_gemfile_path, gems_gem_home)
|
370
452
|
end
|
371
453
|
|
372
|
-
EXCLUDED_FROM_SHIMS = %w
|
454
|
+
EXCLUDED_FROM_SHIMS = %w[rake thor].freeze
|
373
455
|
|
374
456
|
def self.rewrite_shims(shim_path, ruby_executable,
|
375
457
|
root_dir, autoproj_gemfile_path, gems_gem_home)
|
@@ -425,11 +507,7 @@ module Autoproj
|
|
425
507
|
#
|
426
508
|
|
427
509
|
# Autoproj generated preamble
|
428
|
-
|
429
|
-
Bundler.with_clean_env do
|
430
|
-
exec($0, *ARGV)
|
431
|
-
end
|
432
|
-
end
|
510
|
+
#{WITHOUT_BUNDLER}
|
433
511
|
ENV['BUNDLE_GEMFILE'] ||= '#{autoproj_gemfile_path}'
|
434
512
|
ENV['GEM_HOME'] = '#{gems_gem_home}'
|
435
513
|
ENV.delete('GEM_PATH')
|
@@ -441,12 +519,7 @@ Gem.paths = Hash['GEM_HOME' => '#{gems_gem_home}', 'GEM_PATH' => '']
|
|
441
519
|
def self.shim_bundler_old(ruby_executable, autoproj_gemfile_path, gems_gem_home)
|
442
520
|
"#! #{ruby_executable}
|
443
521
|
|
444
|
-
|
445
|
-
Bundler.with_clean_env do
|
446
|
-
exec($0, *ARGV)
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
522
|
+
#{WITHOUT_BUNDLER}
|
450
523
|
ENV['BUNDLE_GEMFILE'] ||= '#{autoproj_gemfile_path}'
|
451
524
|
ENV['GEM_HOME'] = '#{gems_gem_home}'
|
452
525
|
ENV.delete('GEM_PATH')
|
@@ -471,14 +544,7 @@ load Gem.bin_path('bundler', 'bundler')"
|
|
471
544
|
#
|
472
545
|
|
473
546
|
# Autoproj generated preamble, v1
|
474
|
-
|
475
|
-
Bundler.with_clean_env do
|
476
|
-
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
477
|
-
end
|
478
|
-
elsif ENV['RUBYLIB']
|
479
|
-
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
480
|
-
end
|
481
|
-
|
547
|
+
#{RUBYLIB_REINIT}
|
482
548
|
ENV['BUNDLE_GEMFILE'] = '#{autoproj_gemfile_path}'
|
483
549
|
ENV['AUTOPROJ_CURRENT_ROOT'] = '#{root_dir}'
|
484
550
|
Gem.paths = Hash['GEM_HOME' => '#{gems_gem_home}', 'GEM_PATH' => '']
|
@@ -490,14 +556,7 @@ Gem.paths = Hash['GEM_HOME' => '#{gems_gem_home}', 'GEM_PATH' => '']
|
|
490
556
|
gems_gem_home, load_line)
|
491
557
|
"#! #{ruby_executable}
|
492
558
|
|
493
|
-
|
494
|
-
Bundler.with_clean_env do
|
495
|
-
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
496
|
-
end
|
497
|
-
elsif ENV['RUBYLIB']
|
498
|
-
exec(Hash['RUBYLIB' => nil], $0, *ARGV)
|
499
|
-
end
|
500
|
-
|
559
|
+
#{RUBYLIB_REINIT}
|
501
560
|
ENV['BUNDLE_GEMFILE'] = '#{autoproj_gemfile_path}'
|
502
561
|
ENV['AUTOPROJ_CURRENT_ROOT'] = '#{root_dir}'
|
503
562
|
require 'rubygems'
|
@@ -591,8 +650,11 @@ require 'bundler/setup'
|
|
591
650
|
#
|
592
651
|
# So, we're calling 'gem' as a subcommand to discovery the
|
593
652
|
# actual bindir
|
594
|
-
bindir = IO.popen(
|
595
|
-
|
653
|
+
bindir = IO.popen(
|
654
|
+
env_for_child,
|
655
|
+
[Gem.ruby, '-e', 'puts "#{Gem.user_dir}/bin"'], # rubocop:disable Lint/InterpolationCheck
|
656
|
+
&:read
|
657
|
+
)
|
596
658
|
if bindir
|
597
659
|
@gem_bindir = bindir.chomp
|
598
660
|
else
|
@@ -600,11 +662,11 @@ require 'bundler/setup'
|
|
600
662
|
end
|
601
663
|
end
|
602
664
|
|
603
|
-
def install
|
665
|
+
def install(bundler_version: self.bundler_version)
|
604
666
|
if ENV['BUNDLER_GEMFILE']
|
605
667
|
raise "cannot run autoproj_install or autoproj_bootstrap while "\
|
606
|
-
|
607
|
-
|
668
|
+
"under a 'bundler exec' subcommand or having loaded an "\
|
669
|
+
"env.sh. Open a new console and try again"
|
608
670
|
end
|
609
671
|
|
610
672
|
gem_program = self.class.guess_gem_program
|
@@ -612,13 +674,12 @@ require 'bundler/setup'
|
|
612
674
|
env['GEM_HOME'] = [gems_gem_home]
|
613
675
|
env['GEM_PATH'] = [gems_gem_home]
|
614
676
|
|
615
|
-
if bundler = find_bundler(gem_program)
|
677
|
+
if (bundler = find_bundler(gem_program, version: bundler_version))
|
616
678
|
puts "Detected bundler at #{bundler}"
|
617
679
|
else
|
618
680
|
puts "Installing bundler in #{gems_gem_home}"
|
619
|
-
|
620
|
-
|
621
|
-
end
|
681
|
+
bundler = install_bundler(gem_program, version: bundler_version)
|
682
|
+
exit(1) unless bundler
|
622
683
|
end
|
623
684
|
self.class.rewrite_shims(
|
624
685
|
File.join(dot_autoproj, 'bin'),
|
@@ -630,7 +691,7 @@ require 'bundler/setup'
|
|
630
691
|
save_gemfile
|
631
692
|
|
632
693
|
puts "Installing autoproj in #{gems_gem_home}"
|
633
|
-
install_autoproj(bundler)
|
694
|
+
install_autoproj(bundler, bundler_version: bundler_version)
|
634
695
|
end
|
635
696
|
|
636
697
|
def load_config
|