Class: FastlaneCore::CommandExecutor

Inherits:
Object
  • Object
show all
Defined in:
lib/fastlane_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, loading: nil) ⇒ String

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

  • loading (String) (defaults to: nil)

    A loading string that is shown before the first output

Returns:

  • (String)

    All the output as string



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/fastlane_core/command_executor.rb', line 33

def execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, loading: nil)
  print_all = true if $verbose
  prefix ||= {}

  output = []
  command = command.join(" ") if command.kind_of?(Array)
  UI.command(command) if print_command

  if print_all and loading # this is only used to show the "Loading text"...
    UI.command_output(loading)
  end

  begin
    PTY.spawn(command) do |stdin, stdout, pid|
      begin
        stdin.each do |l|
          line = l.strip # strip so that \n gets removed
          output << line

          next unless print_all

          # 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
      rescue Errno::EIO
        # This is expected on some linux systems, that indicates that the subcommand finished
        # and we kept trying to read, ignore it
      ensure
        Process.wait(pid)
      end
    end
  rescue => ex
    # This could happen when the environment is wrong:
    # > invalid byte sequence in US-ASCII (ArgumentError)
    output << ex.to_s
    o = output.join("\n")
    puts o
    if error
      error.call(o, nil)
    else
      raise ex
    end
  end

  # Exit status for build command, should be 0 if build succeeded
  status = $?.exitstatus
  if status != 0
    o = output.join("\n")
    puts o # the user has the right to see the raw output
    UI.error "Exit status: #{status}"
    if error
      error.call(o, status)
    else
      UI.user_error!("Exit status: #{status}")
    end
  end

  return output.join("\n")
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



11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/fastlane_core/command_executor.rb', line 11

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.join(path, "#{cmd}#{ext}")
      return cmd_path if File.executable?(cmd_path) && !File.directory?(cmd_path)
    end
  end

  return nil
end