Class: U3dCore::CommandExecutor

Inherits:
Object
  • Object
show all
Defined in:
lib/u3d_core/command_executor.rb

Overview

Executes commands and takes care of error handling and more

Class Method Summary collapse

Class Method Details

.execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, admin: false) ⇒ String

Deprecated.

Returns All the output as string.

Parameters:

  • command (String) (defaults to: nil)

    The command to be executed

  • print_all (Boolean) (defaults to: false)

    Do we want to print out the command output while running?

  • print_command (Boolean) (defaults to: true)

    Should we print the command that’s being executed

  • error (Block) (defaults to: nil)

    A block that’s called if an error occurs

  • prefix (Array) (defaults to: nil)

    An array containg a prefix + block which might get applied to the output

  • admin (Boolean) (defaults to: false)

    Do we need admin privilege for this command?

Returns:

  • (String)

    All the output as string



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/u3d_core/command_executor.rb', line 59

def execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, admin: false)
  print_all = true if U3dCore::Globals.verbose?
  prefix ||= {}

  output_callback = nil
  if print_all
    output_callback = proc do |line|
      # Prefix the current line with a string
      prefix.each do |element|
        line = element[:prefix] + line if element[:block] && element[:block].call(line)
      end
      UI.command_output(line)
    end
  end

  execute_command(command: command, output_callback: output_callback, print_command: print_command, error_callback: error, admin: admin)
end

.execute_command(command: nil, output_callback: nil, print_command: true, error_callback: nil, admin: false) ⇒ String

Returns All the output as string.

Parameters:

  • command (String) (defaults to: nil)

    The command to be executed

  • output_callback (Block) (defaults to: nil)

    the command to pass to print output

  • print_command (Boolean) (defaults to: true)

    Should we print the command that’s being executed

  • error_callback (Block) (defaults to: nil)

    A block that’s called if an error occurs

  • admin (Boolean) (defaults to: false)

    Do we need admin privilege for this command?

Returns:

  • (String)

    All the output as string



83
84
85
86
87
88
89
90
# File 'lib/u3d_core/command_executor.rb', line 83

def execute_command(command: nil, output_callback: nil, print_command: true, error_callback: nil, admin: false)
  command = command.join(' ') if command.is_a?(Array)
  UI.command(command) if print_command

  command = grant_admin_privileges(command) if admin

  execute_command_low(command: command, output_callback: output_callback, error_callback: error_callback)
end

.grant_admin_privileges(command) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/u3d_core/command_executor.rb', line 147

def grant_admin_privileges(command)
  if Helper.windows?
    raise CredentialsError, "The command \'#{command}\' must be run in administrative shell" unless has_admin_privileges?
  else
    env_username = ENV['USER']
    unless env_username == "root"
      cred = U3dCore::Credentials.new(user: env_username)
      raise CredentialsError, "The command \'#{command}\' must be run with admin privileges" unless has_admin_privileges?
      command = "sudo -k && echo #{cred.password.shellescape} | sudo -S bash -c \"#{command}\""
    end
  end
  UI.verbose 'Admin privileges granted for command execution'
  command
end

.has_admin_privileges?(retry_count: 2) ⇒ Boolean

rubocop:disable PredicateName,PerceivedComplexity

Returns:

  • (Boolean)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/u3d_core/command_executor.rb', line 119

def has_admin_privileges?(retry_count: 2)
  # rubocop:enable PredicateName,PerceivedComplexity
  if Helper.windows?
    begin
      result = system_no_output('reg query HKU\\S-1-5-19')
    rescue StandardError
      result = false
    end
  else
    env_username = ENV['USER']
    if env_username == "root"
      result = true
    else
      credentials = U3dCore::Credentials.new(user: env_username)
      begin
        result = system_no_output("sudo -k && echo #{credentials.password.shellescape} | sudo -S /usr/bin/whoami")
      rescue StandardError
        result = false
      end
      credentials.forget_credentials unless result # FIXME: why?
    end
  end
  # returns false if result is nil (command execution fail)
  result = result ? true : false
  result = has_admin_privileges?(retry_count: retry_count - 1) unless retry_count <= 0 || result
  result
end

.which(cmd) ⇒ Object

Cross-platform way of finding an executable in the $PATH. Respects the $PATHEXT, which lists valid file extensions for executables on Windows.

which('ruby') #=> /usr/bin/ruby

Derived from stackoverflow.com/a/5471032/3005



36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/u3d_core/command_executor.rb', line 36

def which(cmd)
  # PATHEXT contains the list of file extensions that Windows considers executable, semicolon separated.
  # e.g. ".COM;.EXE;.BAT;.CMD"
  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']

  ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
    exts.each do |ext|
      cmd_path = File.expand_path("#{cmd}#{ext}", path)
      return cmd_path if File.executable?(cmd_path) && !File.directory?(cmd_path)
    end
  end

  return nil
end