autoproj 2.10.1 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
-