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,14 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for systems that use pacman (i.e. arch) as
4
+ # their package manager
5
+ class PacmanManager < ShellScriptManager
6
+ def initialize
7
+ super(['pacman'], true,
8
+ "pacman -Sy --needed '%s'",
9
+ "pacman -Sy --needed --noconfirm '%s'")
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,86 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Using pip to install python packages
4
+ class PipManager < Manager
5
+ attr_reader :installed_pips
6
+
7
+ def self.initialize_environment(env = Autobuild.env, _manifest = nil, root_dir = Autoproj.root_dir)
8
+ env.set 'PYTHONUSERBASE', pip_home(env, root_dir)
9
+ end
10
+
11
+ # Return the directory where python packages are installed to.
12
+ # The actual path is pip_home/lib/pythonx.y/site-packages.
13
+ def self.pip_home(env = Autobuild.env, root_dir = Autoproj.root_dir)
14
+ env['AUTOPROJ_PYTHONUSERBASE'] || File.join(root_dir,".pip")
15
+ end
16
+
17
+ def initialize
18
+ super(['pip'])
19
+ @installed_pips = Set.new
20
+ end
21
+
22
+ def guess_pip_program
23
+ if Autobuild.programs['pip']
24
+ return Autobuild.programs['pip']
25
+ end
26
+
27
+ Autobuild.programs['pip'] = "pip"
28
+ end
29
+
30
+ def install(pips)
31
+ guess_pip_program
32
+ if pips.is_a?(String)
33
+ pips = [pips]
34
+ end
35
+
36
+ base_cmdline = [Autobuild.tool('pip'), 'install','--user']
37
+
38
+ cmdlines = [base_cmdline + pips]
39
+
40
+ if pips_interaction(pips, cmdlines)
41
+ Autoproj.message " installing/updating Python dependencies: "+
42
+ "#{pips.sort.join(", ")}"
43
+
44
+ cmdlines.each do |c|
45
+ Autobuild::Subprocess.run 'autoproj', 'osdeps', *c
46
+ end
47
+
48
+ pips.each do |p|
49
+ @installed_pips << p
50
+ end
51
+ end
52
+ end
53
+
54
+ def pips_interaction(pips, cmdlines)
55
+ if OSDependencies.force_osdeps
56
+ return true
57
+ elsif enabled?
58
+ return true
59
+ elsif silent?
60
+ return false
61
+ end
62
+
63
+ # We're not supposed to install rubygem packages but silent is not
64
+ # set, so display information about them anyway
65
+ puts <<-EOMSG
66
+ #{Autoproj.color("The build process and/or the packages require some Python packages to be installed", :bold)}
67
+ #{Autoproj.color("and you required autoproj to not do it itself", :bold)}
68
+ The following command line can be used to install them manually
69
+
70
+ #{cmdlines.map { |c| c.join(" ") }.join("\n ")}
71
+
72
+ Autoproj expects these Python packages to be installed in #{PipManager.pip_home} This can
73
+ be overridden by setting the AUTOPROJ_PYTHONUSERBASE environment variable manually
74
+
75
+ EOMSG
76
+ print " #{Autoproj.color("Press ENTER to continue ", :bold)}"
77
+
78
+ STDOUT.flush
79
+ STDIN.readline
80
+ puts
81
+ false
82
+ end
83
+ end
84
+ end
85
+ end
86
+
@@ -0,0 +1,14 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for systems that use pkg (i.e. FreeBSD) as
4
+ # their package manager
5
+ class PkgManager < ShellScriptManager
6
+ def initialize
7
+ super(['pkg'], true,
8
+ "pkg install -y '%s'",
9
+ "pkg install -y '%s'")
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,14 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for systems that use port (i.e. MacPorts/Darwin) as
4
+ # their package manager
5
+ class PortManager < ShellScriptManager
6
+ def initialize
7
+ super(['macports'], true,
8
+ "port install '%s'",
9
+ "port install '%s'")
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,207 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Base class for all package managers that simply require the call of a
4
+ # shell script to install packages (e.g. yum, apt, ...)
5
+ class ShellScriptManager < Manager
6
+ def self.execute(script, with_locking, with_root)
7
+ if with_locking
8
+ File.open('/tmp/autoproj_osdeps_lock', 'w') do |lock_io|
9
+ begin
10
+ while !lock_io.flock(File::LOCK_EX | File::LOCK_NB)
11
+ Autoproj.message " waiting for other autoproj instances to finish their osdeps installation"
12
+ sleep 5
13
+ end
14
+ return execute(script, false,with_root)
15
+ ensure
16
+ lock_io.flock(File::LOCK_UN)
17
+ end
18
+ end
19
+ end
20
+
21
+ sudo = Autobuild.tool_in_path('sudo')
22
+ Tempfile.open('osdeps_sh') do |io|
23
+ io.puts "#! /bin/bash"
24
+ io.puts GAIN_ROOT_ACCESS % [sudo] if with_root
25
+ io.write script
26
+ io.flush
27
+ Autobuild::Subprocess.run 'autoproj', 'osdeps', '/bin/bash', io.path
28
+ end
29
+ end
30
+
31
+ GAIN_ROOT_ACCESS = <<-EOSCRIPT
32
+ # Gain root access using sudo
33
+ if test `id -u` != "0"; then
34
+ exec %s /bin/bash $0 "$@"
35
+
36
+ fi
37
+ EOSCRIPT
38
+
39
+ # Overrides the {#needs_locking?} flag
40
+ attr_writer :needs_locking
41
+ # Whether two autoproj instances can run this package manager at the
42
+ # same time
43
+ #
44
+ # This declares if this package manager cannot be used concurrently.
45
+ # If it is the case, autoproj will ensure that there is no two
46
+ # autoproj instances running this package manager at the same time
47
+ #
48
+ # @return [Boolean]
49
+ # @see needs_locking=
50
+ def needs_locking?; !!@needs_locking end
51
+
52
+ # Overrides the {#needs_root?} flag
53
+ attr_writer :needs_root
54
+ # Whether this package manager needs root access.
55
+ #
56
+ # This declares if the command line(s) for this package manager
57
+ # should be started as root. Root access is provided using sudo
58
+ #
59
+ # @return [Boolean]
60
+ # @see needs_root=
61
+ def needs_root?; !!@needs_root end
62
+
63
+ # Command line used by autoproj to install packages
64
+ #
65
+ # Since it is to be used for automated install by autoproj, it
66
+ # should not require any interaction with the user. When generating
67
+ # the command line, the %s slot is replaced by the quoted package
68
+ # name(s).
69
+ #
70
+ # @return [String] a command line pattern that allows to install
71
+ # packages without user interaction. It is used when a package
72
+ # should be installed by autoproj automatically
73
+ attr_reader :auto_install_cmd
74
+ # Command line displayed to the user to install packages
75
+ #
76
+ # When generating the command line, the %s slot is replaced by the
77
+ # quoted package name(s).
78
+ #
79
+ # @return [String] a command line pattern that allows to install
80
+ # packages with user interaction. It is displayed to the
81
+ # user when it chose to not let autoproj install packages for this
82
+ # package manager automatically
83
+ attr_reader :user_install_cmd
84
+
85
+ # @param [Array<String>] names the package managers names, see
86
+ # {#names}
87
+ # @param [Boolean] needs_locking whether this package manager can be
88
+ # started by two separate autoproj instances at the same time. See
89
+ # {#needs_locking?}
90
+ # @param [String] user_install_cmd the user-visible command line. See
91
+ # {#user_install_cmd}
92
+ # @param [String] auto_install_cmd the command line used by autoproj
93
+ # itself, see {#auto_install_cmd}.
94
+ # @param [Boolean] needs_root if the command lines should be started
95
+ # as root or not. See {#needs_root?}
96
+ def initialize(names, needs_locking, user_install_cmd, auto_install_cmd,needs_root=true)
97
+ super(names)
98
+ @needs_locking, @user_install_cmd, @auto_install_cmd,@needs_root =
99
+ needs_locking, user_install_cmd, auto_install_cmd, needs_root
100
+ end
101
+
102
+ # Generate the shell script that would allow the user to install
103
+ # the given packages
104
+ #
105
+ # @param [Array<String>] os_packages the name of the packages to be
106
+ # installed
107
+ # @option options [String] :user_install_cmd (#user_install_cmd) the
108
+ # command-line pattern that should be used to generate the script.
109
+ # If given, it overrides the default value stored in
110
+ # {#user_install_cmd]
111
+ def generate_user_os_script(os_packages, options = Hash.new)
112
+ user_install_cmd = options[:user_install_cmd] || self.user_install_cmd
113
+ if user_install_cmd
114
+ (user_install_cmd % [os_packages.join("' '")])
115
+ else generate_auto_os_script(os_packages)
116
+ end
117
+ end
118
+
119
+ # Generate the shell script that should be executed by autoproj to
120
+ # install the given packages
121
+ #
122
+ # @param [Array<String>] os_packages the name of the packages to be
123
+ # installed
124
+ # @option options [String] :auto_install_cmd (#auto_install_cmd) the
125
+ # command-line pattern that should be used to generate the script.
126
+ # If given, it overrides the default value stored in
127
+ # {#auto_install_cmd]
128
+ def generate_auto_os_script(os_packages, options = Hash.new)
129
+ auto_install_cmd = options[:auto_install_cmd] || self.auto_install_cmd
130
+ (auto_install_cmd % [os_packages.join("' '")])
131
+ end
132
+
133
+ # Handles interaction with the user
134
+ #
135
+ # This method will verify whether the user required autoproj to
136
+ # install packages from this package manager automatically. It
137
+ # displays a relevant message if it is not the case.
138
+ #
139
+ # @return [Boolean] true if the packages should be installed
140
+ # automatically, false otherwise
141
+ def osdeps_interaction(os_packages, shell_script)
142
+ if OSDependencies.force_osdeps
143
+ return true
144
+ elsif enabled?
145
+ return true
146
+ elsif silent?
147
+ return false
148
+ end
149
+
150
+ # We're asked to not install the OS packages but to display them
151
+ # anyway, do so now
152
+ puts <<-EOMSG
153
+
154
+ #{Autoproj.color("The build process and/or the packages require some other software to be installed", :bold)}
155
+ #{Autoproj.color("and you required autoproj to not install them itself", :bold)}
156
+ #{Autoproj.color("\nIf these packages are already installed, simply ignore this message\n", :red) if !respond_to?(:filter_uptodate_packages)}
157
+ The following packages are available as OS dependencies, i.e. as prebuilt
158
+ packages provided by your distribution / operating system. You will have to
159
+ install them manually if they are not already installed
160
+
161
+ #{os_packages.sort.join("\n ")}
162
+
163
+ the following command line(s) can be run as root to install them:
164
+
165
+ #{shell_script.split("\n").join("\n| ")}
166
+
167
+ EOMSG
168
+ print " #{Autoproj.color("Press ENTER to continue ", :bold)}"
169
+ STDOUT.flush
170
+ STDIN.readline
171
+ puts
172
+ false
173
+ end
174
+
175
+ # Install packages using this package manager
176
+ #
177
+ # @param [Array<String>] packages the name of the packages that
178
+ # should be installed
179
+ # @option options [String] :user_install_cmd (#user_install_cmd) the
180
+ # command line that should be displayed to the user to install said
181
+ # packages. See the option in {#generate_user_os_script}
182
+ # @option options [String] :auto_install_cmd (#auto_install_cmd) the
183
+ # command line that should be used by autoproj to install said
184
+ # packages. See the option in {#generate_auto_os_script}
185
+ # @return [Boolean] true if packages got installed, false otherwise
186
+ def install(packages, options = Hash.new)
187
+ handled_os = OSDependencies.supported_operating_system?
188
+ if handled_os
189
+ shell_script = generate_auto_os_script(packages, options)
190
+ user_shell_script = generate_user_os_script(packages, options)
191
+ end
192
+ if osdeps_interaction(packages, user_shell_script)
193
+ Autoproj.message " installing OS packages: #{packages.sort.join(", ")}"
194
+
195
+ if Autoproj.verbose
196
+ Autoproj.message "Generating installation script for non-ruby OS dependencies"
197
+ Autoproj.message shell_script
198
+ end
199
+ ShellScriptManager.execute(shell_script, needs_locking?,needs_root?)
200
+ return true
201
+ end
202
+ false
203
+ end
204
+ end
205
+ end
206
+ end
207
+
@@ -0,0 +1,42 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Dummy package manager used for unknown OSes. It simply displays a
4
+ # message to the user when packages are needed
5
+ class UnknownOSManager < Manager
6
+ def initialize
7
+ super(['unknown'])
8
+ @installed_osdeps = Set.new
9
+ end
10
+
11
+ def osdeps_interaction_unknown_os(osdeps)
12
+ puts <<-EOMSG
13
+ #{Autoproj.color("The build process requires some other software packages to be installed on our operating system", :bold)}
14
+ #{Autoproj.color("If they are already installed, simply ignore this message", :red)}
15
+
16
+ #{osdeps.to_a.sort.join("\n ")}
17
+
18
+ EOMSG
19
+ print Autoproj.color("Press ENTER to continue", :bold)
20
+ STDOUT.flush
21
+ STDIN.readline
22
+ puts
23
+ nil
24
+ end
25
+
26
+ def install(osdeps)
27
+ if silent?
28
+ return false
29
+ else
30
+ osdeps = osdeps.to_set
31
+ osdeps -= @installed_osdeps
32
+ if !osdeps.empty?
33
+ result = osdeps_interaction_unknown_os(osdeps)
34
+ end
35
+ @installed_osdeps |= osdeps
36
+ return result
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,56 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ # Package manager interface for systems that use yum
4
+ class YumManager < ShellScriptManager
5
+ def initialize
6
+ super(['yum'], true,
7
+ "yum install '%s'",
8
+ "yum install -y '%s'")
9
+ end
10
+
11
+ def filter_uptodate_packages(packages, options = Hash.new)
12
+ result = `LANG=C rpm -q --queryformat "%{NAME}\n" '#{packages.join("' '")}'`
13
+
14
+ installed_packages = []
15
+ new_packages = []
16
+ result.split("\n").each_with_index do |line, index|
17
+ line = line.strip
18
+ if line =~ /package (.*) is not installed/
19
+ package_name = $1
20
+ if !packages.include?(package_name) # something is wrong, fallback to installing everything
21
+ return packages
22
+ end
23
+ new_packages << package_name
24
+ else
25
+ package_name = line.strip
26
+ if !packages.include?(package_name) # something is wrong, fallback to installing everything
27
+ return packages
28
+ end
29
+ installed_packages << package_name
30
+ end
31
+ end
32
+ new_packages
33
+ end
34
+
35
+ def install(packages)
36
+ patterns, packages = packages.partition { |pkg| pkg =~ /^@/ }
37
+ patterns = patterns.map { |str| str[1..-1] }
38
+ result = false
39
+ if !patterns.empty?
40
+ result |= super(patterns,
41
+ :auto_install_cmd => "yum groupinstall -y '%s'",
42
+ :user_install_cmd => "yum groupinstall '%s'")
43
+ end
44
+ if !packages.empty?
45
+ result |= super(packages)
46
+ end
47
+ if result
48
+ # Invalidate caching of installed packages, as we just
49
+ # installed new packages !
50
+ @installed_packages = nil
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,43 @@
1
+ module Autoproj
2
+ module PackageManagers
3
+ #Package manger for OpenSuse and Suse (untested)
4
+ class ZypperManager < ShellScriptManager
5
+ def initialize
6
+ super(['zypper'], true,
7
+ "zypper install '%s'",
8
+ "zypper -n install '%s'")
9
+ end
10
+
11
+ def filter_uptodate_packages(packages, options = Hash.new)
12
+ result = `LANG=C rpm -q --whatprovides '#{packages.join("' '")}'`
13
+ has_all_pkgs = $?.success?
14
+
15
+ if !has_all_pkgs
16
+ return packages # let zypper filter, we need root now anyways
17
+ else
18
+ return []
19
+ end
20
+ end
21
+
22
+ def install(packages)
23
+ patterns, packages = packages.partition { |pkg| pkg =~ /^@/ }
24
+ patterns = patterns.map { |str| str[1..-1] }
25
+ result = false
26
+ if !patterns.empty?
27
+ result |= super(patterns,
28
+ :auto_install_cmd => "zypper --non-interactive install --type pattern '%s'",
29
+ :user_install_cmd => "zypper install --type pattern '%s'")
30
+ end
31
+ if !packages.empty?
32
+ result |= super(packages)
33
+ end
34
+ if result
35
+ # Invalidate caching of installed packages, as we just
36
+ # installed new packages !
37
+ @installed_packages = nil
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+