lib/binbundle/gem_bins.rb in binbundle-1.0.9 vs lib/binbundle/gem_bins.rb in binbundle-1.0.10

- old
+ new

@@ -1,24 +1,47 @@ # frozen_string_literal: true module Binbundle # Main class class GemBins - def local_gems - Gem::Specification.sort_by { |g| [g.name.downcase, g.version] }.group_by(&:name) - end + # Get gem for bin :gem_for + attr_writer :gem_for + # Get bins for gem :bin_for + attr_writer :bin_for + + # Set options (for testing) + attr_writer :file, :dry_run + + ## + ## Create a new GemBins object + ## + ## @param options The options + ## @option options [Boolean] :include_version Include version number in output + ## @option options [Boolean] :sudo Include sudo in output + ## @option options [Boolean] :user_install Include --user-install in output + ## @option options [Boolean] :dry_run Output to STDOUT + ## @option options [String] :file File to parse + ## @option options [Boolean] :local Work from local gems instead of Binfile + ## def initialize(options = {}) @include_version = options[:include_version] || false @user_install = options[:user_install] @sudo = options[:sudo] @dry_run = options[:dry_run] @file = File.expand_path(options[:file]) - - @local_gems = local_gems.delete_if { |_, specs| specs.delete_if { |spec| spec.executables.empty? }.empty? } end + ## + ## Retrieve info (bin_for or gem_for) + ## + ## @param options The options + ## @option options [Boolean] :local Work from local gems instead of Binfile + ## @option options [String] :gem_for Find gem for this binary + ## @option options [String] :bin_for Find bins for this gem + ## + ## @return [String] resulting gem or bins def info(options) unless File.exist?(@file) || options[:local] puts "File #{@file} not found" Process.exit 1 end @@ -27,42 +50,44 @@ bins_to_s else IO.read(@file) end - gem_list = GemList.new(contents, include_version: @include_version) + gem_list = JewelryBox.new(contents: contents, + include_version: @include_version, + sudo: @sudo, + user_install: @user_install) if options[:gem_for] gem_list.gem_for_bin(options[:gem_for]) elsif options[:bin_for] gem_list.bins_for_gem(options[:bin_for]) end end + ## + ## Install all gems in Binfile + ## def install unless File.exist?(@file) puts "File #{@file} not found" Process.exit 1 end - res = Prompt.yn("Install gems from #{File.basename(@file)}", default_response: true) + contents = IO.read(@file) + lines = JewelryBox.new(contents: contents, include_version: @include_version, sudo: @sudo, + user_install: @user_install) + total = lines.count + successes = 0 + failures = 0 + res = Prompt.yn("Install #{total} gems from #{File.basename(@file)}", default_response: true) Process.exit 0 unless res puts "Installing gems from #{@file}" - contents = IO.read(@file) - gem_list = GemList.new(contents, include_version: @include_version) - lines = if @sudo - gem_list.sudo - elsif @user_install - gem_list.user_install - else - gem_list.normal_install - end - if @dry_run - puts lines.join("\n") + puts lines Process.exit 0 end `sudo echo -n ''` if @sudo @@ -77,54 +102,55 @@ output = `/bin/bash -c '#{cmd}' 2>&1` result = $CHILD_STATUS.success? if result + successes += 1 spinner.success spinner.stop else + failures += 1 spinner.error spinner.stop @errors << output end end + puts "Total #{total}, installed: #{successes}, #{failures} errors." + return if @errors.empty? puts 'ERRORS:' puts @errors.join("\n") + Process.exit 1 end - def gem_command(gem, attrs) - ver = @include_version ? " -v '#{attrs[:version]}'" : '' - ui = @user_install ? '--user-install ' : '' - sudo = @sudo ? 'sudo ' : '' - "# Executables: #{attrs[:bins].join(', ')}\n#{sudo}gem install #{ui}#{gem}#{ver}" - end - + ## + ## Output all gems as Binfile format + ## + ## @return [String] Binfile format + ## def bins_to_s - gems_with_bins = {} - - @local_gems.each do |g, specs| - versions = specs.map { |spec| spec.version.to_s } - bins = specs.map(&:executables) - gems_with_bins[g] = { version: versions.max, bins: bins.sort.uniq } - end - - gems_with_bins.map { |gem, attrs| gem_command(gem, attrs) }.join("\n\n") + local_gems.map(&:gem_command).join("\n\n") end + ## + ## Output or write Binfile + ## def generate output = bins_to_s if @dry_run puts output else write_file(output) end end + ## + ## Writes to Binfile + ## def write_file(output) if File.exist?(@file) res = Prompt.yn("#{@file} already exists, overwrite", default_response: false) Process.exit 1 unless res end @@ -141,8 +167,27 @@ return unless res FileUtils.chmod 0o777, @file puts 'Made file executable' + end + + private + + ## + ## Find local gems and group by name + ## + ## @return [Array] array of local gems as Hashes + ## + def local_gems + gems_with_bins = JewelryBox.new(include_version: @include_version, sudo: @sudo, user_install: @user_install) + + all = Gem::Specification.sort_by { |g| [g.name.downcase, g.version] }.group_by(&:name) + all.delete_if { |_, specs| specs.delete_if { |spec| spec.executables.empty? }.empty? } + all.each do |g, specs| + gems_with_bins << Jewel.new(g, specs.last.executables.sort.uniq, specs.last.version.to_s) + end + + gems_with_bins end end end