autoproj 2.0.0.b7 → 2.0.0.rc1

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.gitignore +8 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +6 -0
  6. data/README.md +4 -0
  7. data/Rakefile +40 -81
  8. data/autoproj.gemspec +29 -0
  9. data/lib/autoproj/cli/cache.rb +7 -2
  10. data/lib/autoproj/cli/main.rb +46 -25
  11. data/lib/autoproj/cli/main_test.rb +6 -4
  12. data/lib/autoproj/cli/status.rb +2 -2
  13. data/lib/autoproj/configuration.rb +5 -0
  14. data/lib/autoproj/git_server_configuration.rb +117 -0
  15. data/lib/autoproj/osdeps.rb +14 -914
  16. data/lib/autoproj/package_managers/apt_dpkg_manager.rb +70 -0
  17. data/lib/autoproj/package_managers/emerge_manager.rb +14 -0
  18. data/lib/autoproj/package_managers/gem_manager.rb +313 -0
  19. data/lib/autoproj/package_managers/homebrew_manager.rb +44 -0
  20. data/lib/autoproj/package_managers/manager.rb +45 -0
  21. data/lib/autoproj/package_managers/pacman_manager.rb +14 -0
  22. data/lib/autoproj/package_managers/pip_manager.rb +86 -0
  23. data/lib/autoproj/package_managers/pkg_manager.rb +14 -0
  24. data/lib/autoproj/package_managers/port_manager.rb +14 -0
  25. data/lib/autoproj/package_managers/shell_script_manager.rb +207 -0
  26. data/lib/autoproj/package_managers/unknown_os_manager.rb +42 -0
  27. data/lib/autoproj/package_managers/yum_manager.rb +56 -0
  28. data/lib/autoproj/package_managers/zypper_manager.rb +43 -0
  29. data/lib/autoproj/package_manifest.rb +1 -1
  30. data/lib/autoproj/test.rb +13 -14
  31. data/lib/autoproj/variable_expansion.rb +4 -2
  32. data/lib/autoproj/version.rb +1 -1
  33. data/lib/autoproj/workspace.rb +5 -1
  34. data/manifest.xml +20 -0
  35. metadata +73 -87
  36. data/.gemtest +0 -0
  37. data/Manifest.txt +0 -105
  38. data/test/data/empty_manifest.xml +0 -2
  39. data/test/data/full_manifest.xml +0 -19
  40. data/test/data/invalid_manifest.xml +0 -3
  41. data/test/data/os_release.with_complex_version_field +0 -3
  42. data/test/data/os_release.with_duplicate_values +0 -3
  43. data/test/data/os_release.with_missing_optional_fields +0 -2
  44. data/test/data/os_release.with_quoted_and_unquoted_fields +0 -2
  45. data/test/data/test_manifest/autoproj/local_set/local.autobuild +0 -0
  46. data/test/data/test_manifest/autoproj/local_set/source.yml +0 -1
  47. data/test/data/test_manifest/autoproj/manifest +0 -7
  48. data/test/ops/test_configuration.rb +0 -20
  49. data/test/ops/test_snapshot.rb +0 -26
  50. data/test/package_managers/apt-dpkg-status +0 -41
  51. data/test/package_managers/apt-dpkg-status.installed-last +0 -27
  52. data/test/package_managers/apt-dpkg-status.noninstalled-last +0 -12
  53. data/test/package_managers/test_apt_dpkg_manager.rb +0 -41
  54. data/test/package_managers/test_gem.rb +0 -156
  55. data/test/package_managers/test_pip.rb +0 -42
  56. data/test/test_manifest.rb +0 -48
  57. data/test/test_os_dependencies.rb +0 -586
  58. data/test/test_package.rb +0 -30
  59. data/test/test_package_manifest.rb +0 -65
  60. data/test/test_vcs_definition.rb +0 -46
@@ -0,0 +1,70 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for systems that use APT and dpkg for
4
+ # package management
5
+ class AptDpkgManager < ShellScriptManager
6
+ attr_accessor :status_file
7
+
8
+ def initialize(status_file = "/var/lib/dpkg/status")
9
+ @status_file = status_file
10
+ super(['apt-dpkg'], true,
11
+ "apt-get install '%s'",
12
+ "export DEBIAN_FRONTEND=noninteractive; apt-get install -y '%s'")
13
+ end
14
+
15
+ # On a dpkg-enabled system, checks if the provided package is installed
16
+ # and returns true if it is the case
17
+ def installed?(package_name)
18
+ if !@installed_packages
19
+ @installed_packages = Set.new
20
+ dpkg_status = File.readlines(status_file)
21
+ dpkg_status << ""
22
+
23
+ current_packages = []
24
+ is_installed = false
25
+ dpkg_status.each do |line|
26
+ line = line.chomp
27
+ line = line.encode( "UTF-8", "binary", :invalid => :replace, :undef => :replace)
28
+ if line == ""
29
+ if is_installed
30
+ current_packages.each do |pkg|
31
+ @installed_packages << pkg
32
+ end
33
+ is_installed = false
34
+ end
35
+ current_packages.clear
36
+ elsif line =~ /Package: (.*)$/
37
+ current_packages << $1
38
+ elsif line =~ /Provides: (.*)$/
39
+ current_packages.concat($1.split(',').map(&:strip))
40
+ elsif line == "Status: install ok installed"
41
+ is_installed = true
42
+ end
43
+ end
44
+ end
45
+
46
+ if package_name =~ /^(\w[a-z0-9+-.]+)/
47
+ @installed_packages.include?($1)
48
+ else
49
+ Autoproj.warn "#{package_name} is not a valid Debian package name"
50
+ false
51
+ end
52
+ end
53
+
54
+ def install(packages)
55
+ if super
56
+ # Invalidate caching of installed packages, as we just
57
+ # installed new packages !
58
+ @installed_packages = nil
59
+ end
60
+ end
61
+
62
+ def filter_uptodate_packages(packages, options = Hash.new)
63
+ packages.find_all do |package_name|
64
+ !installed?(package_name)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
@@ -0,0 +1,14 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for systems that use emerge (i.e. gentoo) as
4
+ # their package manager
5
+ class EmergeManager < ShellScriptManager
6
+ def initialize
7
+ super(['emerge'], true,
8
+ "emerge '%s'",
9
+ "emerge --noreplace '%s'")
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,313 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for the RubyGems system
4
+ class GemManager < Manager
5
+ class << self
6
+ attr_writer :with_prerelease
7
+ attr_accessor :with_doc
8
+ end
9
+ @with_prerelease = false
10
+ @with_doc = false
11
+
12
+ def self.with_prerelease(*value)
13
+ if value.empty?
14
+ @with_prerelease
15
+ else
16
+ begin
17
+ saved_flag = @with_prerelease
18
+ @with_prerelease = value.first
19
+ yield
20
+ ensure
21
+ @with_prerelease = saved_flag
22
+ end
23
+ end
24
+ end
25
+
26
+ # Filters all paths that come from other autoproj installations out
27
+ # of GEM_PATH
28
+ def self.initialize_environment(env = Autobuild.env, manifest = Autoproj.manifest, root_dir = Autoproj.root_dir)
29
+ env.original_env['GEM_PATH'] =
30
+ (env['GEM_PATH'] || "").split(File::PATH_SEPARATOR).find_all do |p|
31
+ !Autoproj.in_autoproj_installation?(p)
32
+ end.join(File::PATH_SEPARATOR)
33
+ env.inherit 'GEM_PATH'
34
+ env.init_from_env 'GEM_PATH'
35
+
36
+ orig_gem_path = env.original_env['GEM_PATH'].split(File::PATH_SEPARATOR)
37
+ env.system_env['GEM_PATH'] = Gem.default_path
38
+ env.original_env['GEM_PATH'] = orig_gem_path.join(File::PATH_SEPARATOR)
39
+
40
+ manifest.each_reused_autoproj_installation do |p|
41
+ p_gems = File.join(p, '.gems')
42
+ if File.directory?(p_gems)
43
+ env.push_path 'GEM_PATH', p_gems
44
+ env.push_path 'PATH', File.join(p_gems, 'bin')
45
+ end
46
+ end
47
+
48
+ @gem_home = (ENV['AUTOPROJ_GEM_HOME'] || File.join(root_dir, ".gems"))
49
+ env.push_path 'GEM_PATH', gem_home
50
+ env.set 'GEM_HOME', gem_home
51
+ env.push_path 'PATH', "#{gem_home}/bin"
52
+
53
+ # Now, reset the directories in our own RubyGems instance
54
+ Gem.paths = env.resolved_env
55
+
56
+ use_cache_dir
57
+ end
58
+
59
+ # Override the gem home detected by {initialize_environment}, or set
60
+ # it in cases where calling {initialize_environment} is not possible
61
+ def self.gem_home=(gem_home)
62
+ @gem_home = gem_home
63
+ end
64
+
65
+ # A global cache directory that should be used to avoid
66
+ # re-downloading gems
67
+ def self.cache_dir
68
+ if dir = ENV['AUTOBUILD_CACHE_DIR']
69
+ dir = File.join(dir, 'gems')
70
+ FileUtils.mkdir_p dir
71
+ dir
72
+ end
73
+ end
74
+
75
+ def self.use_cache_dir
76
+ # If there is a cache directory, make sure .gems/cache points to
77
+ # it (there are no programmatic ways to override this)
78
+ if cache = cache_dir
79
+ gem_cache_dir = File.join(gem_home, 'cache')
80
+ if !File.symlink?(gem_cache_dir) || File.readlink(gem_cache_dir) != cache
81
+ FileUtils.mkdir_p gem_home
82
+ FileUtils.rm_rf gem_cache_dir
83
+ Autoproj.create_symlink(cache, gem_cache_dir)
84
+ end
85
+ end
86
+ end
87
+
88
+ # Return the directory in which RubyGems package should be installed
89
+ def self.gem_home
90
+ @gem_home
91
+ end
92
+
93
+ # Returns the set of default options that are added to gem
94
+ #
95
+ # By default, we add --no-user-install to un-break distributions
96
+ # like Arch that set --user-install by default (thus disabling the
97
+ # role of GEM_HOME)
98
+ def self.default_install_options
99
+ @default_install_options ||= ['--no-user-install', '--no-format-executable']
100
+ end
101
+
102
+ def initialize
103
+ super(['gem'])
104
+ @installed_gems = Set.new
105
+ end
106
+
107
+ # Used to override the Gem::SpecFetcher object used by this gem
108
+ # manager. Useful mainly for testing
109
+ attr_writer :gem_fetcher
110
+
111
+ # The set of gems installed during this autoproj session
112
+ attr_reader :installed_gems
113
+
114
+ def gem_fetcher
115
+ if !@gem_fetcher
116
+ Autoproj.message " looking for RubyGems updates"
117
+ @gem_fetcher = Gem::SpecFetcher.fetcher
118
+ end
119
+ @gem_fetcher
120
+ end
121
+
122
+ def guess_gem_program
123
+ if Autobuild.programs['gem']
124
+ return Autobuild.programs['gem']
125
+ end
126
+
127
+ ruby_bin = RbConfig::CONFIG['RUBY_INSTALL_NAME']
128
+ ruby_bindir = RbConfig::CONFIG['bindir']
129
+
130
+ candidates = ['gem']
131
+ if ruby_bin =~ /^ruby(.+)$/
132
+ candidates << "gem#{$1}"
133
+ end
134
+
135
+ candidates.each do |gem_name|
136
+ if File.file?(gem_full_path = File.join(ruby_bindir, gem_name))
137
+ Autobuild.programs['gem'] = gem_full_path
138
+ return
139
+ end
140
+ end
141
+
142
+ raise ArgumentError, "cannot find a gem program (tried #{candidates.sort.join(", ")} in #{ruby_bindir})"
143
+ end
144
+
145
+ def build_gem_cmdlines(gems)
146
+ with_version, without_version = gems.partition { |name, v| v }
147
+
148
+ cmdlines = []
149
+ if !without_version.empty?
150
+ cmdlines << without_version.flatten
151
+ end
152
+ with_version.each do |name, v|
153
+ cmdlines << [name, "-v", v]
154
+ end
155
+ cmdlines
156
+ end
157
+
158
+ def pristine(gems)
159
+ guess_gem_program
160
+ base_cmdline = [Autobuild.tool_in_path('ruby'), '-S', Autobuild.tool('gem')]
161
+ cmdlines = [
162
+ [*base_cmdline, 'clean'],
163
+ ]
164
+ cmdlines += build_gem_cmdlines(gems).map do |line|
165
+ base_cmdline + ["pristine", "--extensions"] + line
166
+ end
167
+ if gems_interaction(gems, cmdlines)
168
+ Autoproj.message " restoring RubyGems: #{gems.map { |g| g.join(" ") }.sort.join(", ")}"
169
+ cmdlines.each do |c|
170
+ Autobuild::Subprocess.run 'autoproj', 'osdeps', *c
171
+ end
172
+ end
173
+ end
174
+
175
+ def install(gems)
176
+ guess_gem_program
177
+
178
+ base_cmdline = [Autobuild.tool_in_path('ruby'), '-S', Autobuild.tool('gem'), 'install', *GemManager.default_install_options]
179
+ if !GemManager.with_doc
180
+ base_cmdline << '--no-rdoc' << '--no-ri'
181
+ end
182
+
183
+ if GemManager.with_prerelease
184
+ base_cmdline << "--prerelease"
185
+ end
186
+
187
+ cmdlines = build_gem_cmdlines(gems).map do |line|
188
+ base_cmdline + line
189
+ end
190
+ if gems_interaction(gems, cmdlines)
191
+ Autoproj.message " installing/updating RubyGems dependencies: #{gems.map { |g| g.join(" ") }.sort.join(", ")}"
192
+
193
+ cmdlines.each do |c|
194
+ Autobuild::Subprocess.run 'autoproj', 'osdeps', *c,
195
+ env: Hash['GEM_HOME' => Gem.paths.home,
196
+ 'GEM_PATH' => Gem.paths.path.join(":")]
197
+ end
198
+ gems.each do |name, v|
199
+ installed_gems << name
200
+ end
201
+ true
202
+ end
203
+ end
204
+
205
+ # Returns the set of RubyGem packages in +packages+ that are not already
206
+ # installed, or that can be upgraded
207
+ def filter_uptodate_packages(gems, options = Hash.new)
208
+ options = validate_options options,
209
+ install_only: !Autobuild.do_update
210
+
211
+ # Don't install gems that are already there ...
212
+ gems = gems.dup
213
+ gems.delete_if do |name, version|
214
+ next(true) if installed_gems.include?(name)
215
+
216
+ version_requirements = Gem::Requirement.new(version || '>= 0')
217
+ installed =
218
+ if Gem::Specification.respond_to?(:find_by_name)
219
+ begin
220
+ [Gem::Specification.find_by_name(name, version_requirements)]
221
+ rescue Gem::LoadError
222
+ []
223
+ end
224
+ else
225
+ Gem.source_index.find_name(name, version_requirements)
226
+ end
227
+
228
+ if !installed.empty? && !options[:install_only]
229
+ # Look if we can update the package ...
230
+ dep = Gem::Dependency.new(name, version_requirements)
231
+ available =
232
+ if gem_fetcher.respond_to?(:find_matching)
233
+ non_prerelease = gem_fetcher.find_matching(dep, true, true).map(&:first)
234
+ if GemManager.with_prerelease
235
+ prerelease = gem_fetcher.find_matching(dep, false, true, true).map(&:first)
236
+ else prerelease = Array.new
237
+ end
238
+ (non_prerelease + prerelease).
239
+ map { |n, v, _| [n, v] }
240
+
241
+ else # Post RubyGems-2.0
242
+ type = if GemManager.with_prerelease then :complete
243
+ else :released
244
+ end
245
+
246
+ gem_fetcher.detect(type) do |tuple|
247
+ tuple.name == name && dep.match?(tuple)
248
+ end.map { |tuple, _| [tuple.name, tuple.version] }
249
+ end
250
+ installed_version = installed.map(&:version).max
251
+ available_version = available.map { |_, v| v }.max
252
+ if !available_version
253
+ if version
254
+ raise ConfigError.new, "cannot find any gem with the name '#{name}' and version #{version}"
255
+ else
256
+ raise ConfigError.new, "cannot find any gem with the name '#{name}'"
257
+ end
258
+ end
259
+ needs_update = (available_version > installed_version)
260
+ !needs_update
261
+ else
262
+ !installed.empty?
263
+ end
264
+ end
265
+ gems
266
+ end
267
+
268
+ def parse_package_entry(entry)
269
+ if entry =~ /^([^><=~]*)([><=~]+.*)$/
270
+ [$1.strip, $2.strip]
271
+ else
272
+ [entry]
273
+ end
274
+ end
275
+
276
+ def gems_interaction(gems, cmdlines)
277
+ if OSDependencies.force_osdeps
278
+ return true
279
+ elsif enabled?
280
+ return true
281
+ elsif silent?
282
+ return false
283
+ end
284
+
285
+ # We're not supposed to install rubygem packages but silent is not
286
+ # set, so display information about them anyway
287
+ puts <<-EOMSG
288
+ #{Autoproj.color("The build process and/or the packages require some Ruby Gems to be installed", :bold)}
289
+ #{Autoproj.color("and you required autoproj to not do it itself", :bold)}
290
+ You can use the --all or --ruby options to autoproj osdeps to install these
291
+ packages anyway, and/or change to the osdeps handling mode by running an
292
+ autoproj operation with the --reconfigure option as for instance
293
+ autoproj build --reconfigure
294
+
295
+ The following command line can be used to install them manually
296
+
297
+ #{cmdlines.map { |c| c.join(" ") }.join("\n ")}
298
+
299
+ Autoproj expects these Gems to be installed in #{GemManager.gem_home} This can
300
+ be overridden by setting the AUTOPROJ_GEM_HOME environment variable manually
301
+
302
+ EOMSG
303
+ print " #{Autoproj.color("Press ENTER to continue ", :bold)}"
304
+
305
+ STDOUT.flush
306
+ STDIN.readline
307
+ puts
308
+ false
309
+ end
310
+ end
311
+ end
312
+ end
313
+
@@ -0,0 +1,44 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for Mac OS using homebrew as
4
+ # its package manager
5
+ class HomebrewManager < ShellScriptManager
6
+ def initialize
7
+ super(['brew'], true,
8
+ "brew install '%s'",
9
+ "brew install '%s'",
10
+ false)
11
+ end
12
+
13
+ def filter_uptodate_packages(packages, options = Hash.new)
14
+ # TODO there might be duplicates in packages which should be fixed
15
+ # somewhere else
16
+ packages = packages.uniq
17
+ result = `brew info --json=v1 '#{packages.join("' '")}'`
18
+ result = begin
19
+ JSON.parse(result)
20
+ rescue JSON::ParserError
21
+ if result && !result.empty?
22
+ Autoproj.warn "Error while parsing result of brew info --json=v1"
23
+ else
24
+ # one of the packages is unknown fallback to install all
25
+ # packaes which will complain about it
26
+ end
27
+ return packages
28
+ end
29
+ # fall back if something else went wrong
30
+ if packages.size != result.size
31
+ Autoproj.warn "brew info returns less or more packages when requested. Falling back to install all packages"
32
+ return packages
33
+ end
34
+
35
+ new_packages = []
36
+ result.each do |pkg|
37
+ new_packages << pkg["name"] if pkg["installed"].empty?
38
+ end
39
+ new_packages
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,45 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Base class for all package managers. Subclasses must add the
4
+ # #install(packages) method and may add the
5
+ # #filter_uptodate_packages(packages) method
6
+ #
7
+ # Package managers must be registered in PACKAGE_HANDLERS and
8
+ # (if applicable) OS_PACKAGE_HANDLERS.
9
+ class Manager
10
+ # @return [Array<String>] the various names this package manager is
11
+ # known about
12
+ attr_reader :names
13
+
14
+ attr_writer :enabled
15
+ def enabled?; !!@enabled end
16
+
17
+ attr_writer :silent
18
+ def silent?; !!@silent end
19
+
20
+ # Create a package manager registered with various names
21
+ #
22
+ # @param [Array<String>] names the package manager names. It MUST be
23
+ # different from the OS names that autoproj uses. See the comment
24
+ # for OS_PACKAGE_HANDLERS for an explanation
25
+ def initialize(names = [])
26
+ @names = names.dup
27
+ @enabled = true
28
+ @silent = true
29
+ end
30
+
31
+ # The primary name for this package manager
32
+ def name
33
+ names.first
34
+ end
35
+
36
+ # Overload to perform initialization of environment variables in
37
+ # order to have a properly functioning package manager
38
+ #
39
+ # This is e.g. needed for python pip or rubygems
40
+ def self.initialize_environment(_env = nil, _manifest = nil, _root_dir = Autoproj.root_dir)
41
+ end
42
+ end
43
+ end
44
+ end
45
+