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