autoproj 2.10.1 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -8
  3. data/.travis.yml +5 -3
  4. data/autoproj.gemspec +7 -6
  5. data/bin/alog +1 -0
  6. data/bin/autoproj +1 -1
  7. data/bin/autoproj_bootstrap +149 -86
  8. data/bin/autoproj_bootstrap.in +9 -7
  9. data/bin/autoproj_install +148 -82
  10. data/bin/autoproj_install.in +8 -3
  11. data/lib/autoproj.rb +3 -0
  12. data/lib/autoproj/aruba_minitest.rb +15 -0
  13. data/lib/autoproj/autobuild_extensions/dsl.rb +61 -27
  14. data/lib/autoproj/base.rb +35 -6
  15. data/lib/autoproj/cli/base.rb +1 -1
  16. data/lib/autoproj/cli/build.rb +9 -3
  17. data/lib/autoproj/cli/cache.rb +79 -7
  18. data/lib/autoproj/cli/doc.rb +4 -18
  19. data/lib/autoproj/cli/inspection_tool.rb +5 -6
  20. data/lib/autoproj/cli/main.rb +41 -18
  21. data/lib/autoproj/cli/main_doc.rb +86 -0
  22. data/lib/autoproj/cli/main_plugin.rb +3 -0
  23. data/lib/autoproj/cli/main_test.rb +15 -0
  24. data/lib/autoproj/cli/show.rb +12 -18
  25. data/lib/autoproj/cli/status.rb +15 -9
  26. data/lib/autoproj/cli/test.rb +13 -84
  27. data/lib/autoproj/cli/update.rb +77 -19
  28. data/lib/autoproj/cli/utility.rb +136 -0
  29. data/lib/autoproj/configuration.rb +28 -4
  30. data/lib/autoproj/default.osdeps +18 -0
  31. data/lib/autoproj/installation_manifest.rb +7 -5
  32. data/lib/autoproj/manifest.rb +15 -21
  33. data/lib/autoproj/ops/build.rb +23 -27
  34. data/lib/autoproj/ops/cache.rb +151 -33
  35. data/lib/autoproj/ops/cached_env.rb +2 -2
  36. data/lib/autoproj/ops/import.rb +146 -80
  37. data/lib/autoproj/ops/install.rb +140 -79
  38. data/lib/autoproj/ops/phase_reporting.rb +49 -0
  39. data/lib/autoproj/ops/snapshot.rb +2 -1
  40. data/lib/autoproj/ops/tools.rb +2 -2
  41. data/lib/autoproj/os_package_installer.rb +19 -11
  42. data/lib/autoproj/package_definition.rb +29 -10
  43. data/lib/autoproj/package_managers/apt_dpkg_manager.rb +49 -28
  44. data/lib/autoproj/package_managers/bundler_manager.rb +257 -87
  45. data/lib/autoproj/package_managers/homebrew_manager.rb +2 -2
  46. data/lib/autoproj/package_managers/shell_script_manager.rb +44 -24
  47. data/lib/autoproj/package_manifest.rb +49 -34
  48. data/lib/autoproj/package_set.rb +48 -29
  49. data/lib/autoproj/repository_managers/apt.rb +0 -1
  50. data/lib/autoproj/test.rb +29 -10
  51. data/lib/autoproj/variable_expansion.rb +3 -1
  52. data/lib/autoproj/vcs_definition.rb +30 -15
  53. data/lib/autoproj/version.rb +1 -1
  54. data/lib/autoproj/workspace.rb +55 -13
  55. metadata +32 -28
@@ -92,6 +92,12 @@ ruby24:
92
92
  ruby25:
93
93
  default: ignore # we assume that if the user has a ruby 2.5 runtime, it is usable
94
94
 
95
+ ruby26:
96
+ default: ignore # we assume that if the user has a ruby 2.5 runtime, it is usable
97
+
98
+ ruby27:
99
+ default: ignore # we assume that if the user has a ruby 2.5 runtime, it is usable
100
+
95
101
  build-essential:
96
102
  debian,ubuntu: build-essential
97
103
  gentoo: ignore
@@ -132,15 +138,19 @@ archive:
132
138
  debian,ubuntu:
133
139
  - tar
134
140
  - unzip
141
+ - ca-certificates
135
142
  gentoo:
136
143
  - app-arch/tar
137
144
  - app-arch/unzip
145
+ - app-misc/ca-certificates
138
146
  arch:
139
147
  - tar
140
148
  - unzip
149
+ - ca-certificates
141
150
  fedora:
142
151
  - tar
143
152
  - unzip
153
+ - ca-certificates
144
154
  macos-port:
145
155
  - gnutar
146
156
  - unzip
@@ -149,6 +159,7 @@ archive:
149
159
  opensuse:
150
160
  - tar
151
161
  - unzip
162
+ - ca-certificates
152
163
  default: ignore
153
164
 
154
165
  cvs:
@@ -171,6 +182,13 @@ python:
171
182
  opensuse: python-devel
172
183
  default: ignore # will be installed manually by the user
173
184
 
185
+ python-setuptools:
186
+ arch: python2-distribute
187
+ debian,ubuntu: python-setuptools
188
+ fedora: python-setuptools
189
+ gentoo: dev-python/setuptools
190
+ default: ignore # will be installed manually by the user
191
+
174
192
  sudo:
175
193
  macos-brew: ignore
176
194
  default: sudo
@@ -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, :prefix, :builddir, :logdir, :dependencies
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['prefix'],
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,
@@ -50,12 +50,14 @@ def self.load(file)
50
50
 
51
51
  # Load the manifest data contained in +file+
52
52
  def load(file)
53
- if !File.exist?(file)
54
- raise ConfigError.new(File.dirname(file)), "expected an autoproj configuration in #{File.dirname(file)}, but #{file} does not exist"
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.load(File.read(file)) || Hash.new
60
+ YAML.safe_load(File.read(file)) || {}
59
61
  end
60
62
 
61
63
  @file = file
@@ -81,7 +83,8 @@ def initialize_from_hash(data)
81
83
  @has_layout = !!data['layout']
82
84
 
83
85
  if data['constants']
84
- @constant_definitions = Autoproj.resolve_constant_definitions(data['constants'])
86
+ @constant_definitions =
87
+ Autoproj.resolve_constant_definitions(data['constants'])
85
88
  end
86
89
  end
87
90
 
@@ -1020,23 +1023,14 @@ def load_package_manifest(pkg)
1020
1023
  if manifest
1021
1024
  pkg.autobuild.description = manifest
1022
1025
  else
1023
- Autoproj.warn "#{package.name} from #{package_set.name} does not have a manifest"
1026
+ Autoproj.warn "#{package.name} from #{package_set.name} "\
1027
+ "does not have a manifest"
1024
1028
  end
1025
1029
 
1026
- manifest = pkg.autobuild.description
1027
- manifest.each_dependency(pkg.modes) do |name, is_optional|
1028
- begin
1029
- if is_optional
1030
- package.optional_dependency name
1031
- else
1032
- package.depends_on name
1033
- end
1034
- rescue ConfigError => e
1035
- raise ConfigError.new(manifest_path),
1036
- "manifest #{manifest_path} of #{package.name} from #{package_set.name} lists '#{name}' as dependency, but it is neither a normal package nor an osdeps package. osdeps reports: #{e.message}", e.backtrace
1037
- end
1038
- end
1039
- manifest
1030
+ pkg.apply_dependencies_from_manifest
1031
+ # #description is initialized with a null package manifest
1032
+ # return it even if we haven't overriden it
1033
+ pkg.autobuild.description
1040
1034
  end
1041
1035
 
1042
1036
  def load_all_available_package_manifests
@@ -1243,7 +1237,7 @@ def self.config
1243
1237
  workspace.config
1244
1238
  end
1245
1239
 
1246
- def self.add_osdeps_overrides(*args, &block)
1247
- manifest.add_osdeps_overrides(*args, &block)
1240
+ def self.add_osdeps_overrides(*args, **kw, &block)
1241
+ manifest.add_osdeps_overrides(*args, **kw, &block)
1248
1242
  end
1249
1243
  end
@@ -87,40 +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(all_enabled_packages, "autoproj-build", ['build'], options)
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
- build_report(all_enabled_packages) if @report_path
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 build_report(package_list)
100
- FileUtils.mkdir_p File.dirname(@report_path)
101
-
102
- packages = package_list.map do |pkg_name|
103
- pkg = manifest.find_autobuild_package(pkg_name)
104
-
105
- {
106
- name: pkg.name,
107
- import_invoked: pkg.import_invoked?,
108
- prepare_invoked: pkg.prepare_invoked?,
109
- build_invoked: pkg.build_invoked?,
110
- failed: pkg.failed?,
111
- imported: pkg.imported?,
112
- prepared: pkg.prepared?,
113
- built: pkg.built?
114
- }
115
- end
116
-
117
- build_report = JSON.pretty_generate({
118
- build_report: {
119
- timestamp: Time.now,
120
- packages: packages
121
- }
122
- })
123
- IO.write(@report_path, build_report)
115
+ def package_metadata(autobuild_package)
116
+ {
117
+ invoked: !!autobuild_package.install_invoked?,
118
+ success: !!autobuild_package.installed?
119
+ }
124
120
  end
125
121
  end
126
122
  end
@@ -4,9 +4,10 @@ class Cache
4
4
  attr_reader :cache_dir
5
5
  attr_reader :manifest
6
6
 
7
- def initialize(cache_dir, manifest)
7
+ def initialize(cache_dir, ws)
8
8
  @cache_dir = cache_dir
9
- @manifest = manifest
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, options = Hash.new)
31
+ def cache_git(pkg, checkout_only: false)
31
32
  pkg.importdir = File.join(git_cache_dir, pkg.name)
32
- if options[:checkout_only] && File.directory?(pkg.importdir)
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
- if !File.directory?(pkg.importdir)
39
+ unless File.directory?(pkg.importdir)
41
40
  FileUtils.mkdir_p File.dirname(pkg.importdir)
42
- Autobuild::Subprocess.run("autoproj-cache", "import", Autobuild.tool(:git), "--git-dir", pkg.importdir, 'init', "--bare")
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('autoproj-cache', :import, Autobuild.tool('git'), '--git-dir', pkg.importdir, 'remote', 'update', 'autobuild')
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('autoproj-cache', :import, Autobuild.tool('git'), '--git-dir', pkg.importdir, 'fetch', 'autobuild', '--tags')
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('autoproj-cache', :import, Autobuild.tool('git'), '--git-dir', pkg.importdir, 'gc', '--prune=all')
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, checkout_only: 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,42 +100,148 @@ 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
- next if pkg.srcdir != pkg.importdir # No need to process this one, it is uses another package's import
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 " [#{i}/#{total}] caching #{pkg.name} (git)"
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 " [#{i}/#{total}] caching #{pkg.name} (archive)"
115
+ Autoproj.message(
116
+ " [#{i}/#{total}] caching #{pkg.name} (archive)"
117
+ )
99
118
  cache_archive(pkg)
100
119
  else
101
- Autoproj.message " [#{i}/#{total}] not caching #{pkg.name} (cannot cache #{pkg.importer.class})"
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
- if keep_going
107
- pkg.error " failed to cache #{pkg.name}, but going on as requested"
108
- lines = e.to_s.split("\n")
109
- if lines.empty?
110
- lines = e.message.split("\n")
111
- end
112
- if lines.empty?
113
- lines = ["unknown error"]
114
- end
115
- pkg.message(lines.shift, :red, :bold)
116
- lines.each do |line|
117
- pkg.message(line)
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
- nil
120
- else
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
-