Class: Bundler::Spinel::Engine

Inherits:
Object
  • Object
show all
Defined in:
lib/bundler/spinel/engine.rb

Overview

Locates the Spinel compiler and derives a stable revision identity for it.

Forward-compatibility hinges on this: every compatibility verdict in the ledger is keyed on the engine revision, never on a gem name alone. Spinel ships no version string (‘spinel –version` just prints usage; `git describe` returns a bare SHA with no tags), so we key on the git revision of the Spinel checkout — falling back to a content hash of the binary when it isn’t a git checkout. Upgrade Spinel → new rev → no ledger entry → the gem is re-probed automatically. A gem that is ‘rejected` today and works after a Spinel feature lands flips to `clean` on the next probe, with no manual blocklist to maintain.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dir: nil) ⇒ Engine

Returns a new instance of Engine.



21
22
23
24
25
26
27
28
29
30
# File 'lib/bundler/spinel/engine.rb', line 21

def initialize(dir: nil)
  # Resolution order: explicit SPINEL_DIR, then an engine provisioned by
  # `spinel-compat install-engine` (~/.cache/spinel/current), then ~/spinel.
  @dir = dir || ENV["SPINEL_DIR"] || default_dir
  # Prefer a checkout at `dir` (gives a git rev); otherwise fall back to a
  # `spinel` on PATH (installed binary — rev becomes a binary hash). This
  # makes the default work for most setups without configuration.
  local = File.join(@dir, "spinel")
  @bin = File.executable?(local) ? local : (which("spinel") || local)
end

Instance Attribute Details

#binObject (readonly)

Returns the value of attribute bin.



19
20
21
# File 'lib/bundler/spinel/engine.rb', line 19

def bin
  @bin
end

#declared_versionObject

The label a Gemfile declares via ‘engine_version:`. Advisory only — the ledger key is `rev`, not this. Recorded so `check` can warn when the declared label and the actual binary drift apart.



70
71
72
# File 'lib/bundler/spinel/engine.rb', line 70

def declared_version
  @declared_version
end

#dirObject (readonly)

Returns the value of attribute dir.



19
20
21
# File 'lib/bundler/spinel/engine.rb', line 19

def dir
  @dir
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/bundler/spinel/engine.rb', line 40

def available?
  File.executable?(@bin)
end

#default_dirObject

The provisioned-engine cache (install-engine) if it has a built binary, else the conventional ~/spinel. Keeps zero-config working after a ‘spinel-compat install-engine`.



35
36
37
38
# File 'lib/bundler/spinel/engine.rb', line 35

def default_dir
  cur = File.expand_path("~/.cache/spinel/current")
  File.executable?(File.join(cur, "spinel")) ? cur : File.expand_path("~/spinel")
end

#ensure!Object

Raises:



44
45
46
47
48
49
# File 'lib/bundler/spinel/engine.rb', line 44

def ensure!
  return if available?

  raise Error, "spinel compiler not found at #{@bin} " \
               "(set SPINEL_DIR or pass --spinel-dir)"
end

#platformObject



61
62
63
64
65
# File 'lib/bundler/spinel/engine.rb', line 61

def platform
  cpu = RbConfig::CONFIG["host_cpu"]
  os  = RbConfig::CONFIG["host_os"].sub(/\d.*\z/, "").sub(/darwin.*/, "darwin")
  "#{cpu}-#{os}"
end

#revObject

Short, human-facing engine id, platform-scoped:

"git:0adca86/arm64-darwin"  or  "git:0adca86+dirty/aarch64-linux".

Platform matters because verdicts that depend on the C compile + runtime (analyze-failed, miscompile, build-error, verified) are not portable across targets — only ‘unresolved:X` (pure analysis) is. So the same Spinel commit built on the Mac and on the gx10 are distinct ledger revs.



57
58
59
# File 'lib/bundler/spinel/engine.rb', line 57

def rev
  @rev ||= "#{compute_rev}/#{platform}"
end