Class: Agent::Lock::Launcher

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/agent/lock/launcher.rb

Overview

The one place this gem touches the outside world.

Streams and Kernel arrive as arguments so a test can pass its own and read back what happened. Nothing below this class may call puts, touch STDOUT, or call exit without a receiver: do that and the suite either cannot see the output or dies in the middle of an example. Aruba's in-process launcher expects exactly this shape, which is what makes the end-to-end specs fast enough to run on every save.

Constant Summary collapse

DEFAULT_PROGRAM =
"agent-lock"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argv = ARGV, stdin = $stdin, stdout = $stdout, stderr = $stderr, kernel = Kernel, pastel = Pastel.new(enabled: stdout.respond_to?(:tty?) && stdout.tty?), program: DEFAULT_PROGRAM) ⇒ Launcher

The positional signature is fixed by what Aruba's in-process launcher constructs, and by the pattern it comes from, so the cop loses this one. The program name is a keyword so that Aruba, which knows nothing of it, still gets a working default.

It is handed in rather than read from $PROGRAM_NAME here, because under the test runner that says rspec.

rubocop:disable-next Metrics/ParameterLists

Parameters:

  • argv (Array<String>) (defaults to: ARGV)
  • program (String) (defaults to: DEFAULT_PROGRAM) —

    e.g. File.basename($PROGRAM_NAME)



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/agent/lock/launcher.rb', line 54

def initialize(argv = ARGV,
               stdin = $stdin,
               stdout = $stdout,
               stderr = $stderr,
               kernel = Kernel,
               pastel = Pastel.new(enabled: stdout.respond_to?(:tty?) && stdout.tty?),
               program: DEFAULT_PROGRAM)
  self.argv   = Array(argv)
  self.stdin  = stdin
  self.stdout = stdout
  self.stderr = stderr
  self.kernel = kernel
  self.pastel = pastel
  @program    = program
end

Instance Attribute Details

#argv ⇒ Object

Returns the value of attribute argv.



28
29
30
# File 'lib/agent/lock/launcher.rb', line 28

def argv
  @argv
end

#exit_code ⇒ Integer?

What a command asked the process to exit with. Commands set it rather than exiting, so that one kernel.exit in ensure is the only way out.

Returns:

  • (Integer, nil)


34
35
36
# File 'lib/agent/lock/launcher.rb', line 34

def exit_code
  @exit_code
end

#kernel ⇒ Object

Returns the value of attribute kernel.



28
29
30
# File 'lib/agent/lock/launcher.rb', line 28

def kernel
  @kernel
end

#pastel ⇒ Object

Returns the value of attribute pastel.



28
29
30
# File 'lib/agent/lock/launcher.rb', line 28

def pastel
  @pastel
end

#program ⇒ String (readonly)

The name the user typed, alock or agent-lock, for every hint and error prefix. A hint naming the other one may not be on the PATH, or may be the old shell script that shadows this gem's agent-lock.

Returns:

  • (String)


41
42
43
# File 'lib/agent/lock/launcher.rb', line 41

def program
  @program
end

#stderr ⇒ Object

Returns the value of attribute stderr.



28
29
30
# File 'lib/agent/lock/launcher.rb', line 28

def stderr
  @stderr
end

#stdin ⇒ Object

Returns the value of attribute stdin.



28
29
30
# File 'lib/agent/lock/launcher.rb', line 28

def stdin
  @stdin
end

#stdout ⇒ Object

Returns the value of attribute stdout.



28
29
30
# File 'lib/agent/lock/launcher.rb', line 28

def stdout
  @stdout
end

Instance Method Details

#execute! ⇒ void

This method returns an undefined value.

rubocop:disable-next Metrics/AbcSize



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/agent/lock/launcher.rb', line 72

def execute!
  backend_banner if %w[-h --help].intersect?(argv)

  code = 0
  Dry::CLI.new(CLI.registry_for(self)).call(arguments: argv, out: stdout, err: stderr)
rescue SystemExit => e
  # dry-cli exits directly for `--help` and for a bad flag. Catching it
  # keeps that from taking the whole test process down with it.
  code = e.status
rescue Dry::CLI::Error, Error => e
  stderr.puts(bold(red("ERROR: #{program}: #{e.message}")))
  code = 2
rescue Interrupt
  stderr.puts(bold(yellow("WARNING: #{program}: interrupted")))
  code = 130
ensure
  kernel.exit(exit_code || code)
end