diff options
Diffstat (limited to 'rubygems.to_chunk')
-rwxr-xr-x | rubygems.to_chunk | 128 |
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 |