Class: Pipely::Bundler::GemPackager

Inherits:
Object
  • Object
show all
Defined in:
lib/pipely/bundler/gem_packager.rb

Overview

Builds cache files for git- or path-sourced gems.

Defined Under Namespace

Classes: GemBuildError, GemFetchError

Instance Method Summary collapse

Constructor Details

#initialize(vendor_dir) ⇒ GemPackager



18
19
20
21
22
23
# File 'lib/pipely/bundler/gem_packager.rb', line 18

def initialize(vendor_dir)
  @vendor_dir = vendor_dir
  unless Dir.exists? @vendor_dir
    FileUtils.mkdir_p(@vendor_dir)
  end
end

Instance Method Details

#build_from_source(spec_name, source_path) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pipely/bundler/gem_packager.rb', line 61

def build_from_source(spec_name, source_path)
  gem_spec_path = "#{spec_name}.gemspec"

  # Build the gemspec
  gem_spec = Gem::Specification::load(
    File.join(source_path,gem_spec_path))

  gem_file = build_gem(spec_name, source_path)

  # Move to vendor dir
  FileUtils.mv(
    File.join(source_path,gem_file),
    File.join(@vendor_dir,gem_file))

  { gem_spec.name => File.join(@vendor_dir, gem_file) }
end

#build_gem(spec_name, source_path) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/pipely/bundler/gem_packager.rb', line 78

def build_gem(spec_name, source_path)
  gem_spec_path = "#{spec_name}.gemspec"

  Dir.chdir(source_path) do
    result = `gem build #{gem_spec_path} 2>&1`

    if result =~ /ERROR/i
      raise GemBuildError.new(
        "Failed to build #{gem_spec_path} \n" << result)
    else
      result.scan(
          /File:(.+.gem)$/).flatten.first.strip
    end
  end
end

#download_from_rubygems(gem_file_name) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/pipely/bundler/gem_packager.rb', line 94

def download_from_rubygems(gem_file_name)
  vendored_gem = File.join( @vendor_dir, gem_file_name )

  # XXX: add link on wiki details what is going on here
  puts "Fetching gem #{gem_file_name} directly from rubygems, most " +
       "likely this gem was packaged along with your ruby " +
       "distrubtion, for more details see LINK"

  ruby_gem_url = "https://rubygems.org/downloads/#{gem_file_name}"

  fetcher = Gem::RemoteFetcher.new
  gem_data = fetcher.fetch_path(ruby_gem_url)
  IO.binwrite(vendored_gem, gem_data)

  vendored_gem
end

#package(spec) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/pipely/bundler/gem_packager.rb', line 25

def package(spec)
  if vendored_gem = vendor_local_gem(spec)
    vendored_gem

  # Finally, some gems do not exist in the cache or as source.  For
  # instance, json is shipped with the ruby dist. Try to fetch directly
  # from rubygems.
  else
    gem_file_name = "#{spec.name}-#{spec.version}.gem"
    { spec.name => download_from_rubygems(gem_file_name)}
  end
end

#vendor_local_gem(spec) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/pipely/bundler/gem_packager.rb', line 38

def vendor_local_gem(spec)
  gem_file = spec.cache_file
  vendored_gem = File.join( @vendor_dir, File.basename(gem_file) )

  if File.exists?(vendored_gem)
    { spec.name => vendored_gem }

  # Gem exists in the local ruby gems cache
  elsif File.exists? gem_file

    # Copy to vendor dir
    FileUtils.cp(gem_file, vendored_gem)

    { spec.name => vendored_gem }

  # If source exists, build a gem from it
  elsif File.directory?(spec.gem_dir)
    build_from_source(spec.name, spec.gem_dir)
  else
    nil
  end
end