Module: AgentsControl::Which

Defined in:
lib/agents_control/which.rb

Overview

Finds executables by absolute path rather than via PATH.

The daemon is launched by launchd, not an interactive shell, and PATH is different there: Ruby version-manager shims may be missing, and an Intel Homebrew install on Apple Silicon without Rosetta doesn't run at all. So PATH is checked last, not first.

Defined Under Namespace

Classes: NotFoundError

Constant Summary collapse

SEARCH_DIRS =

Directories in order of trust: version managers and ARM Homebrew first, then system paths, and only then whatever PATH turns up.

[
  "~/.asdf/shims",
  "~/.rbenv/shims",
  "/opt/homebrew/bin",
  "/opt/homebrew/sbin",
  "/usr/local/bin",
  "/usr/bin",
  "/bin",
  "/usr/sbin",
  "/sbin"
].freeze

Class Method Summary collapse

Class Method Details

.executable?(path) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/agents_control/which.rb', line 53

def executable?(path)
  File.file?(path) && File.executable?(path)
end

.find(name, extra_dirs: []) ⇒ Object

Absolute path to the binary, or nil.



28
29
30
31
# File 'lib/agents_control/which.rb', line 28

def find(name, extra_dirs: [])
  dirs = extra_dirs + SEARCH_DIRS
  from_dirs(name, dirs) || from_path(name)
end

.find!(name, extra_dirs: []) ⇒ Object

Like find, but with a clear error instead of nil — for places where a missing binary means there's no point continuing.



35
36
37
38
# File 'lib/agents_control/which.rb', line 35

def find!(name, extra_dirs: [])
  find(name, extra_dirs: extra_dirs) ||
    raise(NotFoundError, "executable not found: #{name.inspect}")
end

.from_dirs(name, dirs) ⇒ Object



40
41
42
43
44
# File 'lib/agents_control/which.rb', line 40

def from_dirs(name, dirs)
  dirs.lazy
      .map { |dir| File.join(File.expand_path(dir), name) }
      .find { |path| executable?(path) }
end

.from_path(name) ⇒ Object



46
47
48
49
50
51
# File 'lib/agents_control/which.rb', line 46

def from_path(name)
  ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).lazy
     .reject(&:empty?)
     .map { |dir| File.join(dir, name) }
     .find { |path| executable?(path) }
end