lib/asdf/tool_versions.rb (129 lines of code) (raw):

# frozen_string_literal: true require 'pathname' module Asdf class ToolVersions def default_tool_version_for(tool) tool_versions[tool]&.default_tool_version end def default_version_for(tool) default_tool_version_for(tool)&.version end def unnecessary_software_to_uninstall? work_to_do?(output: false) end def uninstall_unnecessary_software!(prompt: true) return true unless work_to_do? if prompt inform return true unless confirm? end failed_to_uninstall = {} unnecessary_installed_versions_of_software.each do |name, versions| GDK::Output.print "Uninstalling #{name} " versions.each_with_index do |(version, tool_version), i| GDK::Output.print ', ' if i.positive? GDK::Output.print version begin tool_version.uninstall! rescue ToolVersion::UninstallFailedError failed_to_uninstall[name] ||= [] failed_to_uninstall[name] << version end end icon = if failed_to_uninstall.empty? :success elsif failed_to_uninstall.count == versions.count :error else :warning end GDK::Output.puts(" #{GDK::Output.icon(icon)}") end return true if failed_to_uninstall.empty? GDK::Output.puts(stderr: true) GDK::Output.warn("Failed to uninstall the following:\n\n") failed_to_uninstall.each do |name, versions| GDK::Output.puts("#{name} #{versions.join(', ')}") end false end def unnecessary_installed_versions_of_software installed_versions_of_wanted_software.each_with_object({}) do |(name, versions), unncessary_software| versions.each do |version, tool_version| next if wanted_software[name][version] unncessary_software[name] ||= {} unncessary_software[name][version] = tool_version end end end private def config GDK.config end def asdf_opt_out? config.asdf.opt_out? end def inform GDK::Output.warn('About to uninstall the following asdf software:') GDK::Output.puts(stderr: true) unnecessary_installed_versions_of_software.each do |name, versions| GDK::Output.puts("#{name} #{versions.keys.join(', ')}") end GDK::Output.puts(stderr: true) end def work_to_do?(output: true) if asdf_opt_out? GDK::Output.info('Skipping because asdf.opt_out is set to true.') if output return false elsif !asdf_data_installs_dir.exist? GDK::Output.info("Skipping because '#{asdf_data_installs_dir}' does not exist.") if output return false elsif unnecessary_installed_versions_of_software.empty? GDK::Output.info('No unnecessary asdf software to uninstall.') if output return false end true end def confirm? return true if ENV.fetch('GDK_ASDF_UNINSTALL_UNNECESSARY_SOFTWARE_CONFIRM', 'false') == 'true' || !GDK::Output.interactive? GDK::Output.prompt('Are you sure? [y/N]').match?(/\Ay(?:es)*\z/i) end def raw_tool_versions_lines GDK.root.glob('{.tool-versions,{*,*/*}/.tool-versions}').each_with_object([]) do |path, lines| lines.concat(File.readlines(path)) end end def tool_versions @tool_versions ||= raw_tool_versions_lines.each_with_object({}) do |line, all| match = line.chomp.match(/\A(?<name>\w+) (?<versions>[\d. ]+)\z/) next unless match new_versions = match[:versions].split if all[match[:name]] all[match[:name]].versions |= new_versions else all[match[:name]] = Tool.new(match[:name], new_versions) end end end def wanted_software tool_versions.transform_values(&:tool_versions) end def asdf_data_dir @asdf_data_dir ||= Pathname.new(ENV.fetch('ASDF_DATA_DIR', File.join(Dir.home, '.asdf'))) end def asdf_data_installs_dir @asdf_data_installs_dir ||= asdf_data_dir.join('installs') end def asdf_install_dirs_for(name) asdf_data_installs_dir.join(name).glob('*') end def installed_versions_of_wanted_software wanted_software.each_with_object({}) do |(name, _), installed_software| asdf_install_dirs_for(name).each do |dir| version = dir.basename.to_s installed_software[name] ||= {} installed_software[name][version] = ToolVersion.new(name, version) end end end end end