Class: Bundler::Spinel::GemFetcher

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

Overview

Downloads and unpacks a gem’s source so the probe can compile it. Reuses RubyGems’ own ‘gem fetch` / `gem unpack` — we want the source tree, not an install. Sources are cached under a content dir so re-probes are free.

Constant Summary collapse

CACHE =

Default cache lives on $HOME. Override with SPINEL_COMPAT_CACHE to put the source cache on a roomier volume — a full ecosystem sweep caches ~193k gem sources (100s of GB), which overruns a tight root fs. On gx10 that means /srv/data/scratch (the 1.9 TB volume), not ~/.cache on the 916 GB root.

File.expand_path(ENV["SPINEL_COMPAT_CACHE"] || "~/.cache/spinel-compat/gems")

Instance Method Summary collapse

Constructor Details

#initialize(cache: CACHE) ⇒ GemFetcher

Returns a new instance of GemFetcher.



18
19
20
# File 'lib/bundler/spinel/gem_fetcher.rb', line 18

def initialize(cache: CACHE)
  @cache = cache
end

Instance Method Details

#fetch(name, version) ⇒ Object

Returns the path to the unpacked gem dir, fetching+unpacking if needed.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/bundler/spinel/gem_fetcher.rb', line 23

def fetch(name, version)
  dest = File.join(@cache, "#{name}-#{version}")
  return dest if File.directory?(dest)

  FileUtils.mkdir_p(@cache)
  Dir.mktmpdir do |tmp|
    out, st = Open3.capture2e(
      "gem", "fetch", name, "-v", version, "--platform", "ruby",
      chdir: tmp
    )
    raise Error, "gem fetch #{name} #{version} failed:\n#{out}" unless st.success?

    gemfile = Dir[File.join(tmp, "#{name}-*.gem")].first
    raise Error, "no .gem produced for #{name} #{version}" unless gemfile

    out, st = Open3.capture2e("gem", "unpack", gemfile, "--target", @cache)
    raise Error, "gem unpack failed:\n#{out}" unless st.success?
  end
  # `gem unpack` may name the dir with a platform suffix; normalise.
  return dest if File.directory?(dest)

  actual = Dir[File.join(@cache, "#{name}-#{version}*")].find { |d| File.directory?(d) }
  actual or raise Error, "unpacked dir for #{name} #{version} not found"
end