Class: Autoproj::PackageManagers::ShellScriptManager

Inherits:
Manager
  • Object
show all
Defined in:
lib/autoproj/package_managers/shell_script_manager.rb

Overview

Base class for all package managers that simply require the call of a shell script to install packages (e.g. yum, apt, …)

Instance Attribute Summary collapse

Attributes inherited from Manager

#enabled, #silent, #ws

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Manager

#call_while_empty?, #configure_manager, #enabled?, #initialize_environment, #os_dependencies, #silent?, #strict?

Constructor Details

#initialize(ws, needs_locking, user_install_cmd, auto_install_cmd, needs_root = true) ⇒ ShellScriptManager

Returns a new instance of ShellScriptManager.

Parameters:

  • names (Array<String>)

    the package managers names, see #names

  • needs_locking (Boolean)

    whether this package manager can be started by two separate autoproj instances at the same time. See #needs_locking?

  • user_install_cmd (String)

    the user-visible command line. See #user_install_cmd

  • auto_install_cmd (String)

    the command line used by autoproj itself, see #auto_install_cmd.

  • needs_root (Boolean) (defaults to: true)

    if the command lines should be started as root or not. See #needs_root?



103
104
105
106
107
108
109
110
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 103

def initialize(ws, needs_locking, user_install_cmd,
    auto_install_cmd, needs_root = true)
    super(ws)
    @needs_locking = needs_locking
    @user_install_cmd = user_install_cmd
    @auto_install_cmd = auto_install_cmd
    @needs_root = needs_root
end

Instance Attribute Details

#auto_install_cmdString (readonly)

Command line used by autoproj to install packages

Since it is to be used for automated install by autoproj, it should not require any interaction with the user. When generating the command line, the %s slot is replaced by the quoted package name(s).

Returns:

  • (String)

    a command line pattern that allows to install packages without user interaction. It is used when a package should be installed by autoproj automatically



80
81
82
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 80

def auto_install_cmd
  @auto_install_cmd
end

#needs_locking=(value) ⇒ Object (writeonly)

Overrides the #needs_locking? flag



41
42
43
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 41

def needs_locking=(value)
  @needs_locking = value
end

#needs_root=(value) ⇒ Object (writeonly)

Overrides the #needs_root? flag



57
58
59
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 57

def needs_root=(value)
  @needs_root = value
end

#user_install_cmdString (readonly)

Command line displayed to the user to install packages

When generating the command line, the %s slot is replaced by the quoted package name(s).

Returns:

  • (String)

    a command line pattern that allows to install packages with user interaction. It is displayed to the user when it chose to not let autoproj install packages for this package manager automatically



90
91
92
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 90

def user_install_cmd
  @user_install_cmd
end

Class Method Details

.execute(command_line, with_locking, with_root, env: Autoproj.workspace.env, inherit: Set.new) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 6

def self.execute(command_line, with_locking, with_root,
    env: Autoproj.workspace.env, inherit: Set.new)
    if with_locking
        File.open("/tmp/autoproj_osdeps_lock", "w") do |lock_io|
            until lock_io.flock(File::LOCK_EX | File::LOCK_NB)
                Autoproj.message "  waiting for other autoproj "\
                                 "instances to finish their osdeps "\
                                 "installation"
                sleep 5
            end
            return execute(command_line, false, with_root,
                           env: env, inherit: inherit)
        ensure
            lock_io.flock(File::LOCK_UN)
        end
    end

    process_env = env
    if with_root
        process_env = Autobuild::Environment.new
        process_env.isolate
        process_env.add_path("PATH", "/usr/local/sbin",
                             "/usr/sbin", "/sbin")

        inherit.each { |var| process_env.set(var, env[var]) }
        sudo = Autobuild.tool_in_path("sudo", env: process_env)
        command_line = [sudo, "--preserve-env", *command_line]
    end

    Autobuild::Subprocess.run "autoproj", "osdeps", *command_line,
                              env: process_env.resolved_env,
                              env_inherit: false
end

Instance Method Details

#generate_auto_os_script(os_packages, auto_install_cmd: self.auto_install_cmd) ⇒ Object

Generate the shell script that should be executed by autoproj to install the given packages

Parameters:

  • os_packages (Array<String>)

    the name of the packages to be installed

  • options (Hash)

    a customizable set of options



139
140
141
142
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 139

def generate_auto_os_script(os_packages,
    auto_install_cmd: self.auto_install_cmd)
    generate_script(auto_install_cmd, os_packages)
end

#generate_script(cmd, args) ⇒ Object



145
146
147
148
149
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 145

def generate_script(cmd, args)
    cmd = cmd.join(" ")
    args = args.join("' '")
    "#{cmd} #{args}"
end

#generate_user_os_script(os_packages, user_install_cmd: self.user_install_cmd) ⇒ Object

Generate the shell script that would allow the user to install the given packages

Parameters:

  • os_packages (Array<String>)

    the name of the packages to be installed

  • options (Hash)

    a customizable set of options



121
122
123
124
125
126
127
128
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 121

def generate_user_os_script(os_packages,
    user_install_cmd: self.user_install_cmd)
    if user_install_cmd
        generate_script(user_install_cmd, os_packages)
    else
        generate_auto_os_script(os_packages)
    end
end

#install(packages, filter_uptodate_packages: false, install_only: false, auto_install_cmd: self.auto_install_cmd, user_install_cmd: self.user_install_cmd, inherit: Set.new) ⇒ Boolean

Install packages using this package manager

Parameters:

  • packages (Array<String>)

    the name of the packages that should be installed

  • options (Hash)

    a customizable set of options

Returns:

  • (Boolean)

    true if packages got installed, false otherwise



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 206

def install(packages, filter_uptodate_packages: false, install_only: false,
    auto_install_cmd: self.auto_install_cmd,
    user_install_cmd: self.user_install_cmd,
    inherit: Set.new)
    return if packages.empty?

    handled_os = ws.supported_operating_system?
    if handled_os
        shell_script = generate_auto_os_script(
            packages, auto_install_cmd: auto_install_cmd
        )
        user_shell_script = generate_user_os_script(
            packages, user_install_cmd: user_install_cmd
        )
    end
    if osdeps_interaction(packages, user_shell_script)
        Autoproj.message "  installing OS packages: "\
                         "#{packages.sort.join(', ')}"

        if Autoproj.verbose
            Autoproj.message "Generating installation script for "\
                             "non-ruby OS dependencies"
            Autoproj.message shell_script
        end

        ShellScriptManager.execute(
            [*auto_install_cmd, *packages], needs_locking?,
            needs_root?, env: ws.env, inherit: inherit
        )
        return true
    end
    false
end

#needs_locking?Boolean

Whether two autoproj instances can run this package manager at the same time

This declares if this package manager cannot be used concurrently. If it is the case, autoproj will ensure that there is no two autoproj instances running this package manager at the same time

Returns:

  • (Boolean)

See Also:



52
53
54
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 52

def needs_locking?
    @needs_locking
end

#needs_root?Boolean

Whether this package manager needs root access.

This declares if the command line(s) for this package manager should be started as root. Root access is provided using sudo

Returns:

  • (Boolean)

See Also:



66
67
68
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 66

def needs_root?
    @needs_root
end

#osdeps_interaction(os_packages, shell_script) ⇒ Boolean

Handles interaction with the user

This method will verify whether the user required autoproj to install packages from this package manager automatically. It displays a relevant message if it is not the case.

Returns:

  • (Boolean)

    true if the packages should be installed automatically, false otherwise



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/autoproj/package_managers/shell_script_manager.rb', line 159

def osdeps_interaction(os_packages, shell_script)
    if OSPackageInstaller.force_osdeps
        return true
    elsif enabled?
        return true
    elsif silent?
        return false
    end

    # We're asked to not install the OS packages but to display them
    # anyway, do so now
    puts <<-EOMSG

    #{Autoproj.color('The build process and/or the packages require some other software to be installed', :bold)}
    #{Autoproj.color('and you required autoproj to not install them itself', :bold)}
    #{unless respond_to?(:filter_uptodate_packages)
          Autoproj.color('\nIf these packages are already installed, simply ignore this message\n', :red)
      end}
    The following packages are available as OS dependencies, i.e. as prebuilt
    packages provided by your distribution / operating system. You will have to
    install them manually if they are not already installed

    #{os_packages.sort.join("\n      ")}

    the following command line(s) can be run as root to install them:

    #{shell_script.split("\n").join("\n|   ")}

    EOMSG
    print "    #{Autoproj.color('Press ENTER to continue ', :bold)}"
    STDOUT.flush
    STDIN.readline
    puts
    false
end