diff --git a/lib/label.rb b/lib/label.rb index e234ddb..2d9be56 100644 --- a/lib/label.rb +++ b/lib/label.rb @@ -1,6 +1,7 @@ require "label/version" require "label/gemspec_info" require "label/description_formatter" +require "label/gem_options_extractor" require "optparse" require "ostruct" require "gems" @@ -105,16 +106,9 @@ def format description, prepend_string # as :github, :path and/or :branch and return a Hash with those options # :rubygems is the default def extract_source_and_options line - source = {} - options = line.split "," - options[1, options.length - 1].each do |option| - if option.match(/:/) - args = option.split(":").map {|arg| arg.strip.gsub(/('|\")/, '') } - source[args.first.to_sym] = args.last - end - end - source[:rubygems] = true if source.empty? - source + extractor = GemOptionsExtractor.new line + extractor.extract! + extractor.gem_options end end diff --git a/lib/label/gem_options_extractor.rb b/lib/label/gem_options_extractor.rb new file mode 100644 index 0000000..2029659 --- /dev/null +++ b/lib/label/gem_options_extractor.rb @@ -0,0 +1,57 @@ +module Label + # Takes a line gotten from a Gemfile and returns all the options associated + # to that gem + class GemOptionsExtractor + attr_reader :gem_options + + def initialize(line) + @line = line + @gem_options = {} + end + + # parses into a hash all the option specified for a gem including the + # source which is :rubygems by default (optional values: :github, + # :git or :path) + def extract! + @raw_options = line.split(',') + extract_version_if_defined + normalize_options.each do |option| + gem_options[option[:name]] = option[:value] + end + gem_options[:rubygems] = true if source_empty? + end + + private + + attr_reader :line + attr_writer :gem_options + attr_accessor :raw_options + + def extract_version_if_defined + # the second position always should be + # the version number + if raw_options[1] && !raw_options[1].match(/:/) + gem_options[:version] = clean_value(raw_options[1]) + end + end + + def normalize_options + raw_options.map do |raw_option| + if raw_option.match(':') + args = raw_option.split(':').map { |arg| clean_value(arg) } + { name: args.first.to_sym, value: args.last } + end + end.compact + end + + def clean_value(value) + value.to_s.strip.gsub(/('|\")/, '') + end + + def source_empty? + !(gem_options.key?(:github) || + gem_options.key?(:git) || + gem_options.key?(:path)) + end + end +end diff --git a/spec/label/gem_options_extractor_spec.rb b/spec/label/gem_options_extractor_spec.rb new file mode 100644 index 0000000..ea8c892 --- /dev/null +++ b/spec/label/gem_options_extractor_spec.rb @@ -0,0 +1,34 @@ +require 'label/gem_options_extractor' + +def extract(gem_line) + extractor = Label::GemOptionsExtractor.new(gem_line) + extractor.extract! + extractor.gem_options +end + +describe Label::GemOptionsExtractor, :wip do + + describe '#extract' do + it 'extracts source if available' do + result = extract("gem 'rspec', github: 'rspec/rspec'") + expect(result).to eq(github: 'rspec/rspec') + end + + it 'defaults source to rubygems' do + expect(extract("gem 'rspec'")).to eq(rubygems: true) + end + + it 'extracts gem version if available' do + result = extract("gem 'rspec', '~> 3.0.0.beta'") + expect(result).to eq(version: '~> 3.0.0.beta', rubygems: true) + end + + it 'extracts the rest of the options as a hash' do + result = extract("gem 'rspec', github: 'jgorset/rspec'"\ + ", tag: 'awesome_feature'") + expect(result).to eq(github: 'jgorset/rspec', tag: 'awesome_feature') + end + + end + +end diff --git a/spec/label_spec.rb b/spec/label_spec.rb index 76e41f4..178a196 100644 --- a/spec/label_spec.rb +++ b/spec/label_spec.rb @@ -49,7 +49,7 @@ allow(subject).to receive(:describe).with("pry", github: "pry/pry", branch: "development") .and_return("An IRB alternative and runtime developer console") - allow(subject).to receive(:describe).with("rspec-rails", rubygems: true).and_return( + allow(subject).to receive(:describe).with("rspec-rails", rubygems: true, version: '~> 3.0.0.beta2').and_return( "Rspec for Rails" )