autoproj 2.11.0 → 2.12.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/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.rb +1 -0
- data/lib/autoproj/autobuild_extensions/dsl.rb +4 -2
- data/lib/autoproj/base.rb +18 -0
- data/lib/autoproj/cli/cache.rb +35 -6
- data/lib/autoproj/cli/main.rb +28 -7
- data/lib/autoproj/cli/test.rb +1 -1
- data/lib/autoproj/cli/utility.rb +21 -25
- data/lib/autoproj/configuration.rb +12 -1
- data/lib/autoproj/installation_manifest.rb +7 -5
- data/lib/autoproj/ops/build.rb +23 -21
- data/lib/autoproj/ops/cache.rb +135 -30
- 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/os_package_installer.rb +19 -11
- data/lib/autoproj/package_managers/apt_dpkg_manager.rb +11 -5
- data/lib/autoproj/package_managers/bundler_manager.rb +100 -19
- data/lib/autoproj/package_managers/homebrew_manager.rb +2 -2
- data/lib/autoproj/test.rb +20 -6
- data/lib/autoproj/version.rb +1 -1
- data/lib/autoproj/workspace.rb +19 -4
- metadata +3 -2
data/bin/autoproj_install.in
CHANGED
@@ -13,8 +13,13 @@ require 'autoproj/ops/install'
|
|
13
13
|
ENV.delete('BUNDLE_GEMFILE')
|
14
14
|
ENV.delete('RUBYLIB')
|
15
15
|
ops = Autoproj::Ops::Install.new(Dir.pwd)
|
16
|
+
|
17
|
+
existing_config = File.join(Dir.pwd, '.autoproj', 'config.yml')
|
18
|
+
if File.file?(existing_config)
|
19
|
+
puts "Found existing configuration, using it as seed"
|
20
|
+
puts "use --no-seed-config to avoid this behavior"
|
21
|
+
ops.add_seed_config(existing_config)
|
22
|
+
end
|
16
23
|
ops.parse_options(ARGV)
|
17
24
|
ops.stage1
|
18
|
-
|
19
|
-
ops.call_stage2
|
20
|
-
end
|
25
|
+
ops.call_stage2 unless ops.skip_stage2?
|
data/lib/autoproj.rb
CHANGED
@@ -149,11 +149,13 @@ def ignore(*paths)
|
|
149
149
|
|
150
150
|
# Adds a new setup block to an existing package
|
151
151
|
def setup_package(package_name, workspace: Autoproj.workspace, &block)
|
152
|
-
|
152
|
+
unless block
|
153
|
+
raise Autoproj::ConfigError.new, 'you must give a block to #setup_package'
|
154
|
+
end
|
153
155
|
|
154
156
|
package_definition = workspace.manifest.find_package_definition(package_name)
|
155
157
|
if !package_definition
|
156
|
-
raise ConfigError.new, "#{package_name} is not a known package"
|
158
|
+
raise Autoproj::ConfigError.new, "#{package_name} is not a known package"
|
157
159
|
elsif package_definition.autobuild.kind_of?(Autobuild::DummyPackage)
|
158
160
|
# Nothing to do!
|
159
161
|
else
|
data/lib/autoproj/base.rb
CHANGED
@@ -56,4 +56,22 @@ def self.post_import(*packages, &block)
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
# Shim for a smooth upgrade path to bundler 2.1+
|
61
|
+
def self.bundler_unbundled_system(*args, **options)
|
62
|
+
if Bundler.respond_to?(:unbundled_system)
|
63
|
+
Bundler.unbundled_system(*args, **options)
|
64
|
+
else
|
65
|
+
Bundler.clean_system(*args, **options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Shim for a smooth upgrade path to bundler 2.1+
|
70
|
+
def self.bundler_with_unbundled_env(&block)
|
71
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
72
|
+
Bundler.with_unbundled_env(&block)
|
73
|
+
else
|
74
|
+
Bundler.with_clean_env(&block)
|
75
|
+
end
|
76
|
+
end
|
59
77
|
end
|
data/lib/autoproj/cli/cache.rb
CHANGED
@@ -10,21 +10,50 @@ def validate_options(argv, options = Hash.new)
|
|
10
10
|
if argv.empty?
|
11
11
|
default_cache_dirs = Autobuild::Importer.default_cache_dirs
|
12
12
|
if !default_cache_dirs || default_cache_dirs.empty?
|
13
|
-
raise CLIInvalidArguments,
|
13
|
+
raise CLIInvalidArguments,
|
14
|
+
"no cache directory defined with e.g. the "\
|
15
|
+
"AUTOBUILD_CACHE_DIR environment variable, "\
|
16
|
+
"expected one cache directory as argument"
|
14
17
|
end
|
15
|
-
Autoproj.warn "using cache directory #{default_cache_dirs.first}
|
18
|
+
Autoproj.warn "using cache directory #{default_cache_dirs.first} "\
|
19
|
+
"from the autoproj configuration"
|
16
20
|
argv << default_cache_dirs.first
|
17
21
|
end
|
18
22
|
|
19
|
-
|
23
|
+
if (compile = options[:gems_compile])
|
24
|
+
options[:gems_compile] = compile.map do |name|
|
25
|
+
name, *artifacts = name.split('+')
|
26
|
+
[name, artifacts: artifacts]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
[File.expand_path(argv.first, ws.root_dir), *argv[1..-1], options]
|
20
31
|
end
|
21
32
|
|
22
|
-
def run(cache_dir, *package_names,
|
33
|
+
def run(cache_dir, *package_names,
|
34
|
+
keep_going: false,
|
35
|
+
packages: true, all: true, checkout_only: false,
|
36
|
+
gems: false, gems_compile: [], gems_compile_force: false)
|
23
37
|
initialize_and_load
|
24
38
|
finalize_setup
|
25
39
|
|
26
|
-
cache_op = Autoproj::Ops::Cache.new(cache_dir, ws
|
27
|
-
|
40
|
+
cache_op = Autoproj::Ops::Cache.new(cache_dir, ws)
|
41
|
+
if packages
|
42
|
+
cache_op.create_or_update(
|
43
|
+
*package_names,
|
44
|
+
all: all, keep_going: keep_going,
|
45
|
+
checkout_only: checkout_only
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
if gems
|
50
|
+
Autoproj.message "caching gems in #{cache_op.gems_cache_dir}"
|
51
|
+
cache_op.create_or_update_gems(
|
52
|
+
keep_going: keep_going,
|
53
|
+
compile: gems_compile,
|
54
|
+
compile_force: gems_compile_force
|
55
|
+
)
|
56
|
+
end
|
28
57
|
end
|
29
58
|
end
|
30
59
|
end
|
data/lib/autoproj/cli/main.rb
CHANGED
@@ -300,13 +300,34 @@ def build(*packages)
|
|
300
300
|
end
|
301
301
|
end
|
302
302
|
|
303
|
-
desc 'cache CACHE_DIR', 'create or update a cache directory that
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
option :
|
309
|
-
|
303
|
+
desc 'cache CACHE_DIR', 'create or update a cache directory that '\
|
304
|
+
'can be given to AUTOBUILD_CACHE_DIR'
|
305
|
+
option :keep_going,
|
306
|
+
aliases: :k,
|
307
|
+
desc: 'do not stop on errors'
|
308
|
+
option :checkout_only,
|
309
|
+
aliases: :c, type: :boolean, default: false,
|
310
|
+
desc: 'only checkout packages, do not update already-cached ones'
|
311
|
+
option :all,
|
312
|
+
type: :boolean, default: true,
|
313
|
+
desc: 'cache all defined packages (the default), '\
|
314
|
+
' or only the selected ones'
|
315
|
+
option :packages,
|
316
|
+
type: :boolean, default: true,
|
317
|
+
desc: 'update the package cache'
|
318
|
+
option :gems,
|
319
|
+
type: :boolean, default: false,
|
320
|
+
desc: 'update the gems cache'
|
321
|
+
option :gems_compile_force,
|
322
|
+
type: :boolean, default: false,
|
323
|
+
desc: 'with --gems-compile, recompile existing gems as well'
|
324
|
+
option :gems_compile,
|
325
|
+
type: :array,
|
326
|
+
desc: 'pre-compile the following gems. This requires gem-compiler '\
|
327
|
+
'to be available in the workspace. Use GEM_NAME+ARTIFACT'\
|
328
|
+
'[+ARTIFACT] to add files or directories to the precompiled '\
|
329
|
+
'gems beyond what gem-compiler auto-adds (which is mostly '\
|
330
|
+
'dynamic libraries)'
|
310
331
|
def cache(*args)
|
311
332
|
run_autoproj_cli(:cache, :Cache, Hash[], *args)
|
312
333
|
end
|
data/lib/autoproj/cli/test.rb
CHANGED
@@ -10,7 +10,7 @@ def initialize(ws = Workspace.default,
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def package_metadata(package)
|
13
|
-
u = package.
|
13
|
+
u = package.test_utility
|
14
14
|
super.merge(
|
15
15
|
'coverage_available' => !!u.coverage_available?,
|
16
16
|
'coverage_enabled' => !!u.coverage_enabled?,
|
data/lib/autoproj/cli/utility.rb
CHANGED
@@ -89,24 +89,37 @@ def run(user_selection, options = {})
|
|
89
89
|
raise CLIInvalidArguments, "autoproj: the provided package "\
|
90
90
|
"is not selected for build"
|
91
91
|
end
|
92
|
+
return if package_names.empty?
|
92
93
|
|
93
94
|
packages = package_names.map do |pkg_name|
|
94
95
|
ws.manifest.find_package_definition(pkg_name)
|
95
96
|
end
|
96
97
|
|
98
|
+
apply_to_packages(packages, parallel: options[:parallel])
|
99
|
+
end
|
100
|
+
|
101
|
+
def apply_to_packages(packages, parallel: ws.config.parallel_build_level)
|
102
|
+
if @report_path
|
103
|
+
reporting = Ops::PhaseReporting.new(
|
104
|
+
@utility_name, @report_path,
|
105
|
+
method(:package_metadata)
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
reporting&.initialize_incremental_report
|
97
110
|
Autobuild.apply(
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
111
|
+
packages.map(&:name), "autoproj-#{@utility_name}",
|
112
|
+
[@utility_name], parallel: parallel
|
113
|
+
) do |pkg, phase|
|
114
|
+
reporting&.report_incremental(pkg) if phase == utility_name
|
115
|
+
end
|
103
116
|
|
104
117
|
ensure
|
105
|
-
create_report(packages)
|
118
|
+
reporting&.create_report(packages.map(&:autobuild))
|
106
119
|
end
|
107
120
|
|
108
|
-
def package_metadata(
|
109
|
-
u =
|
121
|
+
def package_metadata(autobuild_package)
|
122
|
+
u = autobuild_package.utility(@utility_name)
|
110
123
|
{
|
111
124
|
'source_dir' => u.source_dir,
|
112
125
|
'target_dir' => u.target_dir,
|
@@ -117,23 +130,6 @@ def package_metadata(package)
|
|
117
130
|
'installed' => !!u.installed?,
|
118
131
|
}
|
119
132
|
end
|
120
|
-
|
121
|
-
def create_report(packages)
|
122
|
-
info = packages.each_with_object({}) do |p, map|
|
123
|
-
map[p.name] = package_metadata(p)
|
124
|
-
end
|
125
|
-
|
126
|
-
FileUtils.mkdir_p File.dirname(@report_path)
|
127
|
-
File.open(@report_path, 'w') do |io|
|
128
|
-
dump = JSON.dump(
|
129
|
-
"#{@utility_name}_report" => {
|
130
|
-
'timestamp' => Time.now,
|
131
|
-
'packages' => info
|
132
|
-
}
|
133
|
-
)
|
134
|
-
io.write dump
|
135
|
-
end
|
136
|
-
end
|
137
133
|
end
|
138
134
|
end
|
139
135
|
end
|
@@ -196,7 +196,9 @@ def configure(option_name)
|
|
196
196
|
Autoproj.info " using: #{value} (noninteractive mode)"
|
197
197
|
end
|
198
198
|
@modified = true
|
199
|
-
if
|
199
|
+
if is_default
|
200
|
+
value = opt.validate(value)
|
201
|
+
else
|
200
202
|
config[option_name] = [value, true]
|
201
203
|
displayed_options[option_name] = value
|
202
204
|
end
|
@@ -353,6 +355,10 @@ def shell_helpers=(flag)
|
|
353
355
|
set 'shell_helpers', flag, true
|
354
356
|
end
|
355
357
|
|
358
|
+
def bundler_version
|
359
|
+
get 'bundler_version', nil
|
360
|
+
end
|
361
|
+
|
356
362
|
def apply_autobuild_configuration
|
357
363
|
if has_value_for?('autobuild')
|
358
364
|
params = get('autobuild')
|
@@ -369,6 +375,11 @@ def importer_cache_dir
|
|
369
375
|
get('importer_cache_dir', nil)
|
370
376
|
end
|
371
377
|
|
378
|
+
# Set import and gem cache directory
|
379
|
+
def importer_cache_dir=(path)
|
380
|
+
set('importer_cache_dir', path, true)
|
381
|
+
end
|
382
|
+
|
372
383
|
# Sets the directory in which packages will be installed
|
373
384
|
def prefix_dir=(path)
|
374
385
|
set('prefix', path, true)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Autoproj
|
2
2
|
# Manifest of installed packages imported from another autoproj installation
|
3
3
|
class InstallationManifest
|
4
|
-
Package = Struct.new :name, :type, :vcs, :srcdir, :
|
4
|
+
Package = Struct.new :name, :type, :vcs, :srcdir, :importdir,
|
5
|
+
:prefix, :builddir, :logdir, :dependencies
|
5
6
|
PackageSet = Struct.new :name, :vcs, :raw_local_dir, :user_local_dir
|
6
7
|
|
7
8
|
attr_reader :path
|
@@ -28,11 +29,11 @@ def add_package_set(pkg_set)
|
|
28
29
|
def each_package_set(&block)
|
29
30
|
package_sets.each_value(&block)
|
30
31
|
end
|
31
|
-
|
32
|
+
|
32
33
|
def each_package(&block)
|
33
34
|
packages.each_value(&block)
|
34
35
|
end
|
35
|
-
|
36
|
+
|
36
37
|
def load
|
37
38
|
@packages = Hash.new
|
38
39
|
raw = YAML.load(File.open(path))
|
@@ -51,8 +52,8 @@ def load
|
|
51
52
|
package_sets[pkg_set.name] = pkg_set
|
52
53
|
else
|
53
54
|
pkg = Package.new(
|
54
|
-
entry['name'], entry['type'], entry['vcs'], entry['srcdir'], entry['
|
55
|
-
entry['builddir'], entry['logdir'], entry['dependencies'])
|
55
|
+
entry['name'], entry['type'], entry['vcs'], entry['srcdir'], entry['importdir'],
|
56
|
+
entry['prefix'], entry['builddir'], entry['logdir'], entry['dependencies'])
|
56
57
|
packages[pkg.name] = pkg
|
57
58
|
end
|
58
59
|
end
|
@@ -74,6 +75,7 @@ def save(path = self.path)
|
|
74
75
|
'type' => v.class.name,
|
75
76
|
'vcs' => package_def.vcs.to_hash,
|
76
77
|
'srcdir' => v.srcdir,
|
78
|
+
'importdir' => (v.importdir if v.respond_to?(:importdir)),
|
77
79
|
'builddir' => (v.builddir if v.respond_to?(:builddir)),
|
78
80
|
'logdir' => v.logdir,
|
79
81
|
'prefix' => v.prefix,
|
data/lib/autoproj/ops/build.rb
CHANGED
@@ -87,34 +87,36 @@ def force_build_packages(selected_packages, all_enabled_packages)
|
|
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 @@ class Cache
|
|
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 @@ def git_cache_dir
|
|
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 @@ def cache_archive(pkg)
|
|
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 @@ def create_or_update(*package_names, all: true, keep_going: false, checkout_only
|
|
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,7 +100,10 @@ def create_or_update(*package_names, all: true, keep_going: false, checkout_only
|
|
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
|
@@ -103,27 +118,117 @@ def create_or_update(*package_names, all: true, keep_going: false, checkout_only
|
|
103
118
|
rescue Interrupt
|
104
119
|
raise
|
105
120
|
rescue ::Exception => e
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
pkg.message(
|
116
|
-
|
117
|
-
|
121
|
+
raise unless keep_going
|
122
|
+
|
123
|
+
pkg.error " failed to cache #{pkg.name}, "\
|
124
|
+
'but going on as requested'
|
125
|
+
lines = e.to_s.split('\n')
|
126
|
+
lines = e.message.split('\n') if lines.empty?
|
127
|
+
lines = ['unknown error'] if lines.empty?
|
128
|
+
pkg.message(lines.shift, :red, :bold)
|
129
|
+
lines.each do |line|
|
130
|
+
pkg.message(line)
|
131
|
+
end
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def gems_cache_dir
|
138
|
+
File.join(cache_dir, 'package_managers', 'gem')
|
139
|
+
end
|
140
|
+
|
141
|
+
def create_or_update_gems(keep_going: true, compile_force: false, compile: [])
|
142
|
+
# Note: this might directly copy into the cache directoy, and
|
143
|
+
# we support it later
|
144
|
+
cache_dir = File.join(@ws.prefix_dir, 'gems', 'vendor', 'cache')
|
145
|
+
PackageManagers::BundlerManager.run_bundler(
|
146
|
+
@ws, 'cache'
|
147
|
+
)
|
148
|
+
|
149
|
+
FileUtils.mkdir_p(gems_cache_dir) unless File.exist?(gems_cache_dir)
|
150
|
+
|
151
|
+
needs_copy =
|
152
|
+
if File.exist?(cache_dir)
|
153
|
+
real_cache_dir = File.realpath(cache_dir)
|
154
|
+
real_target_dir = File.realpath(gems_cache_dir)
|
155
|
+
(real_cache_dir != real_target_dir)
|
156
|
+
end
|
157
|
+
|
158
|
+
synchronize_gems_cache_dirs(real_cache_dir, real_target_dir) if needs_copy
|
159
|
+
|
160
|
+
platform_suffix = "-#{Gem::Platform.local}.gem"
|
161
|
+
failed = []
|
162
|
+
compile.each do |gem_name, artifacts: []|
|
163
|
+
Dir.glob(File.join(cache_dir, "#{gem_name}*.gem")) do |gem|
|
164
|
+
next if gem.end_with?(platform_suffix)
|
165
|
+
|
166
|
+
gem_basename = File.basename(gem, ".gem")
|
167
|
+
expected_platform_gem = File.join(
|
168
|
+
real_target_dir, "#{gem_basename}#{platform_suffix}"
|
169
|
+
)
|
170
|
+
next if !compile_force && File.file?(expected_platform_gem)
|
171
|
+
|
172
|
+
begin
|
173
|
+
compile_gem(gem, artifacts: artifacts, output: real_target_dir)
|
174
|
+
rescue CompilationFailed
|
175
|
+
unless keep_going
|
176
|
+
raise CompilationFailed, "#{gem} failed to compile"
|
118
177
|
end
|
119
|
-
|
120
|
-
|
121
|
-
raise
|
178
|
+
|
179
|
+
failed << gem
|
122
180
|
end
|
123
181
|
end
|
124
182
|
end
|
183
|
+
|
184
|
+
unless failed.empty?
|
185
|
+
raise CompilationFailed, "#{failed.sort.join(', ')} failed to compile"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
class CompilationFailed < RuntimeError; end
|
190
|
+
|
191
|
+
def synchronize_gems_cache_dirs(source, target)
|
192
|
+
Dir.glob(File.join(source, "*.gem")) do |source_file|
|
193
|
+
basename = File.basename(source_file)
|
194
|
+
target_file = File.join(target, basename)
|
195
|
+
next if File.file?(target_file)
|
196
|
+
|
197
|
+
Autoproj.message "gems: caching #{basename}"
|
198
|
+
FileUtils.cp source_file, target_file
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def guess_gem_program
|
203
|
+
if Autobuild.programs['gem']
|
204
|
+
return Autobuild.programs['gem']
|
205
|
+
end
|
206
|
+
|
207
|
+
ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
|
208
|
+
ruby_bindir = RbConfig::CONFIG['bindir']
|
209
|
+
|
210
|
+
candidates = ['gem']
|
211
|
+
if ruby_bin =~ /^ruby(.+)$/
|
212
|
+
candidates << "gem#{$1}"
|
213
|
+
end
|
214
|
+
|
215
|
+
candidates.each do |gem_name|
|
216
|
+
if File.file?(gem_full_path = File.join(ruby_bindir, gem_name))
|
217
|
+
Autobuild.programs['gem'] = gem_full_path
|
218
|
+
return Autobuild.programs['gem']
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
raise ArgumentError, "cannot find a gem program (tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
|
223
|
+
end
|
224
|
+
|
225
|
+
private def compile_gem(gem_path, output:, artifacts: [])
|
226
|
+
artifacts = artifacts.flat_map { |n| ["--artifact", n] }
|
227
|
+
unless system(Autobuild.tool('ruby'), '-S', guess_gem_program,
|
228
|
+
'compile', '--output', output, *artifacts, gem_path)
|
229
|
+
raise CompilationFailed, "#{gem_path} failed to compile"
|
230
|
+
end
|
125
231
|
end
|
126
232
|
end
|
127
233
|
end
|
128
234
|
end
|
129
|
-
|