summaryrefslogtreecommitdiff
path: root/rubygems.to_chunk
diff options
context:
space:
mode:
Diffstat (limited to 'rubygems.to_chunk')
-rwxr-xr-xrubygems.to_chunk128
1 files changed, 12 insertions, 116 deletions
diff --git a/rubygems.to_chunk b/rubygems.to_chunk
index 796fe89..e1f7132 100755
--- a/rubygems.to_chunk
+++ b/rubygems.to_chunk
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
#
-# Create a chunk morphology to integrate a RubyGem in Baserock
+# Create a chunk morphology to build a RubyGem in Baserock
#
# Copyright (C) 2014 Codethink Limited
#
@@ -20,35 +20,20 @@
require 'bundler'
require_relative 'importer_base'
-
-class << Bundler
- def default_gemfile
- # This is a hack to make things not crash when there's no Gemfile
- Pathname.new('.')
- end
-end
-
-def spec_is_from_current_source_tree(spec, source_dir)
- spec.source.instance_of? Bundler::Source::Path and
- File.identical?(spec.source.path, source_dir)
-end
+require_relative 'importer_bundler_extensions'
BANNER = "Usage: rubygems.to_chunk SOURCE_DIR GEM_NAME [VERSION]"
DESCRIPTION = <<-END
-This tool reads the Gemfile and optionally the Gemfile.lock from a Ruby project
-source tree in SOURCE_DIR. It outputs a chunk morphology for GEM_NAME on
-stdout. If VERSION is supplied, it is used to check that the build instructions
-will produce the expected version of the Gem.
+This tool looks in SOURCE_DIR to generate a chunk morphology with build
+instructions for GEM_NAME. If VERSION is supplied, it is used to check that the
+build instructions will produce the expected version of the Gem.
It is intended for use with the `baserock-import` tool.
END
class RubyGemChunkMorphologyGenerator < Importer::Base
- def initialize
- local_data = YAML.load_file(local_data_path("rubygems.yaml"))
- @build_dependency_whitelist = local_data['build-dependency-whitelist']
- end
+ include Importer::BundlerExtensions
def parse_options(arguments)
opts = create_option_parser(BANNER, DESCRIPTION)
@@ -69,39 +54,6 @@ class RubyGemChunkMorphologyGenerator < Importer::Base
[source_dir, gem_name, expected_version]
end
- def load_local_gemspecs()
- # Look for .gemspec files in the source repo.
- #
- # If there is no .gemspec, but you set 'name' and 'version' then
- # inside Bundler::Source::Path.load_spec_files this call will create a
- # fake gemspec matching that name and version. That's probably not useful.
-
- dir = '.'
-
- source = Bundler::Source::Path.new({
- 'path' => dir,
- })
-
- log.info "Loaded #{source.specs.count} specs from source dir."
- source.specs.each do |spec|
- log.debug " * #{spec.inspect} #{spec.dependencies.inspect}"
- end
-
- source
- end
-
- def get_spec_for_gem(specs, gem_name)
- found = specs[gem_name].select {|s| Gem::Platform.match(s.platform)}
- if found.empty?
- raise Exception,
- "No Gemspecs found matching '#{gem_name}'"
- elsif found.length != 1
- raise Exception,
- "Unsure which Gem to use for #{gem_name}, got #{found}"
- end
- found[0]
- end
-
def chunk_name_for_gemspec(spec)
# Chunk names are the Gem's "full name" (name + version number), so
# that we don't break in the rare but possible case that two different
@@ -195,79 +147,23 @@ class RubyGemChunkMorphologyGenerator < Importer::Base
}
end
- def build_deps_for_gem(spec)
- deps = spec.dependencies.select do |d|
- d.type == :development && @build_dependency_whitelist.member?(d.name)
- end
- end
-
- def runtime_deps_for_gem(spec)
- spec.dependencies.select {|d| d.type == :runtime}
- end
-
def run
source_dir_name, gem_name, expected_version = parse_options(ARGV)
log.info("Creating chunk morph for #{gem_name} based on " +
"source code in #{source_dir_name}")
- Dir.chdir(source_dir_name)
-
- # 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 #{source_dir_name}"
- exit 1
+ resolved_specs = Dir.chdir(source_dir_name) do
+ # FIXME: we don't need to do this here, it'd be enough just to load
+ # the given gemspec
+ definition = create_bundler_definition_for_gemspec(gem_name)
+ definition.resolve_remotely!
end
- definition = fake_gemfile.to_definition('Gemfile.lock', true)
- resolved_specs = definition.resolve_remotely!
-
spec = get_spec_for_gem(resolved_specs, gem_name)
-
- 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
+ validate_spec(spec, source_dir_name, expected_version)
morph = generate_chunk_morph_for_gem(spec)
-
- # One might think that you could use the Bundler::Dependency.groups
- # field to filter but it doesn't seem to be useful. Instead we go back to
- # the Gem::Specification of the target Gem and use the dependencies fild
- # there. We look up each dependency in the resolved_specset to find out
- # what version Bundler has chosen of it.
-
- def format_deps_for_morphology(specset, dep_list)
- info = dep_list.collect do |dep|
- spec = specset[dep][0]
- [spec.name, spec.version.to_s]
- end
- Hash[info]
- end
-
- build_deps = format_deps_for_morphology(
- resolved_specs, build_deps_for_gem(spec))
- runtime_deps = format_deps_for_morphology(
- resolved_specs, runtime_deps_for_gem(spec))
-
- morph['x-build-dependencies-rubygems'] = build_deps
- morph['x-runtime-dependencies-rubygems'] = runtime_deps
-
write_morph(STDOUT, morph)
end
end