summaryrefslogtreecommitdiff
path: root/baserockimport/exts/importer_bundler_extensions.rb
blob: 034b3c2041771d99cb5306d165914401516c3cdd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env ruby
#
# Extensions to Bundler library which allow using it in importers.
#
# Copyright (C) 2014  Codethink Limited
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

require 'bundler'

class << Bundler
  def default_gemfile
    # This is a hack to make things not crash when there's no Gemfile
    Pathname.new('.')
  end
end

module Importer
  module BundlerExtensions
    def create_bundler_definition_for_gemspec(gem_name)
      # Using the real Gemfile doesn't get great results, because people can put
      # lots of stuff in there that is handy for developers to have but
      # irrelevant if you just want to produce a .gem. Also, there is only one
      # Gemfile per repo, but a repo may include multiple .gemspecs that we want
      # to process individually. Also, some projects don't use Bundler and may
      # not have a Gemfile at all.
      #
      # Instead of reading the real Gemfile, invent one that simply includes the
      # chosen .gemspec. If present, the Gemfile.lock will be honoured.
      fake_gemfile = Bundler::Dsl.new
      fake_gemfile.source('https://rubygems.org')
      begin
        fake_gemfile.gemspec({:name => gem_name})
      rescue Bundler::InvalidOption
        error "Did not find #{gem_name}.gemspec in current directory."
        exit 1
      end

      fake_gemfile.to_definition('Gemfile.lock', true)
    end

    def get_spec_for_gem(specs, gem_name)
      found = specs[gem_name].select {|s| Gem::Platform.match(s.platform)}
      if found.empty?
        raise "No Gemspecs found matching '#{gem_name}'"
      elsif found.length != 1
        raise "Unsure which Gem to use for #{gem_name}, got #{found}"
      end
      found[0]
    end

    def spec_is_from_current_source_tree(spec, source_dir)
      Dir.chdir(source_dir) do
        spec.source.instance_of? Bundler::Source::Path and
          File.identical?(spec.source.path, '.')
      end
    end

    def validate_spec(spec, source_dir_name, expected_version)
      if not spec_is_from_current_source_tree(spec, source_dir_name)
        error "Specified gem '#{spec.name}' doesn't live in the source in " \
              "'#{source_dir_name}'"
        log.debug "SPEC: #{spec.inspect} #{spec.source}"
        exit 1
      end

      if expected_version != nil && spec.version != expected_version
        # This check is brought to you by Coderay, which changes its version
        # number based on an environment variable. Other Gems may do this too.
        error "Source in #{source_dir_name} produces #{spec.full_name}, but " \
              "the expected version was #{expected_version}."
        exit 1
      end
    end
  end
end