Class: Subcontractor::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/subcontractor/cli.rb

Instance Method Summary collapse

Instance Method Details

#build_command(parts, options) ⇒ Object



77
78
79
80
81
# File 'lib/subcontractor/cli.rb', line 77

def build_command(parts, options)
  parts.unshift("rvm #{options[:rvm]} exec") if options.has_key?(:rvm)
  parts.unshift("env RBENV_VERSION=#{options[:rbenv]} rbenv exec") if options.has_key?(:rbenv)
  parts.join(' ')
end

#find_child_pids(pids) ⇒ Object



70
71
72
73
74
75
# File 'lib/subcontractor/cli.rb', line 70

def find_child_pids(pids)
  lines = `ps axo pid,ppid`.lines
  child_pids = lines.map(&:split).select do |(child_pid, parent_pid)|
    pids.include?(parent_pid.to_i)
  end.map(&:first).map(&:to_i)
end

#find_pids_to_kill(*pids_to_investigate) ⇒ Object



61
62
63
64
65
66
67
68
# File 'lib/subcontractor/cli.rb', line 61

def find_pids_to_kill(*pids_to_investigate)
  pids_to_kill = pids_to_investigate
  begin
    pids_to_investigate = find_child_pids(pids_to_investigate)
    pids_to_kill = pids_to_investigate + pids_to_kill
  end until pids_to_investigate.empty?
  pids_to_kill
end

#parse_options(argv) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/subcontractor/cli.rb', line 83

def parse_options(argv)
  options = {}
  parser = OptionParser.new do |opt|
    opt.banner = "USAGE: subcontract [options] -- executable"
    opt.on('-r', '--rvm RVM', 'run in a specific RVM') do |rvm|
      options[:rvm] = rvm
    end
    opt.on('-b', '--rbenv RBENV', 'run in a specific RBENV') do |rbenv|
      options[:rbenv] = rbenv
    end
    opt.on('-d', '--chdir PATH', 'chdir to PATH before starting process') do |path|
      options[:chdir] = path
    end
    opt.on('-s', '--signal SIGNAL', 'signal to send to process to kill it, default TERM') do |signal|
      options[:signal] = signal
    end
  end

  parser.parse! argv
  options
end

#runObject



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/subcontractor/cli.rb', line 39

def run
  options = parse_options(ARGV)
  command = build_command(ARGV.dup, options)
  Dir.chdir(options[:chdir]) if options[:chdir]
  signal = options[:signal] || "TERM"
  SafePty.spawn(command) do |stdin, stdout, pid|
    trap("TERM") do
      send_kill(signal, find_pids_to_kill(pid))
    end
    trap("INT") do
      send_kill(signal, find_pids_to_kill(pid))
    end
    until stdin.eof?
      puts stdin.gets
    end
  end
end

#send_kill(signal, pids) ⇒ Object



57
58
59
# File 'lib/subcontractor/cli.rb', line 57

def send_kill(signal, pids)
  pids.each { |pid| Process.kill(signal, pid) }
end