autoproj 2.0.0.b7 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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
+