From 14a81ec42ca8da2f3b59b5b5d1d0daaa1e9d2f08 Mon Sep 17 00:00:00 2001 From: Maximilian Downey Twiss Date: Thu, 4 Apr 2024 22:11:36 +1100 Subject: [PATCH] Split remove command into separate file (#9529) --- bin/crew | 85 ++++------------------------------------------ commands/remove.rb | 67 ++++++++++++++++++++++++++++++++++++ lib/const.rb | 8 ++--- lib/fixup.rb | 14 ++++---- 4 files changed, 82 insertions(+), 92 deletions(-) create mode 100644 commands/remove.rb diff --git a/bin/crew b/bin/crew index 0bdb49f33..341a8b605 100755 --- a/bin/crew +++ b/bin/crew @@ -8,6 +8,7 @@ require_relative '../commands/const' require_relative '../commands/help' require_relative '../commands/list' require_relative '../commands/prop' +require_relative '../commands/remove' require_relative '../commands/sysinfo' require_relative '../lib/color' require_relative '../lib/const' @@ -1284,7 +1285,7 @@ def install # remove it just before the file copy if @pkg.in_upgrade puts 'Removing since upgrade or reinstall...' - remove @pkg.name + Command.remove(@pkg, @opt_verbose) end unless @pkg.is_fake? @@ -1408,83 +1409,6 @@ def archive_package(crew_archive_dest) end end -def remove(pkg_name) - # make sure the package is actually installed - unless @device[:installed_packages].any? { |pkg| pkg[:name] == pkg_name } || File.file?(File.join(CREW_META_PATH, "#{pkg_name}.filelist")) - puts "Package #{pkg_name} isn't installed.".lightred - return - end - - # Perform any operations required prior to package removal. - search pkg_name, true - @pkg.preremove unless @in_fixup - - # Preserve CREW_ESSENTIAL_FILES and make sure they are real files - # and not symlinks, because preserving symlinked libraries does not - # prevent breakage. - CREW_ESSENTIAL_FILES.each do |file| - next unless File.symlink?("#{CREW_LIB_PREFIX}/#{file}") - - canonicalized_file = `readlink -m #{CREW_LIB_PREFIX}/#{file}`.chomp - if File.file?(canonicalized_file) && canonicalized_file.include?(CREW_PREFIX) - puts "Replacing symlinked essential #{file} with hard link to #{canonicalized_file} to avoid breakage.".lightblue if @opt_verbose - FileUtils.ln(canonicalized_file, "#{CREW_LIB_PREFIX}/#{file}", force: true) - end - end - - conflicts = determine_conflicts(Dir.pwd, pkg_name) - - # if the filelist exists, remove the files and directories installed by the package - if File.file?(File.join(CREW_META_PATH, "#{pkg_name}.filelist")) - Dir.chdir CREW_CONFIG_PATH do - # remove all files installed by the package - File.foreach("meta/#{pkg_name}.filelist", chomp: true) do |line| - # Do not remove essential files which crew (and dependencies) - # rely on, especially during package upgrades or reinstalls. - # These essential files are enumerated in const.rb as - # CREW_ESSENTIAL_FILES. - if CREW_ESSENTIAL_FILES.include?(File.basename(line)) - puts "Removing #{line} will break crew. It was #{'NOT'.lightred} deleted." if @opt_verbose - else - puts "Removing file #{line}".lightred if @opt_verbose - puts "filelist contains #{line}".lightred if @opt_verbose && !line.include?(CREW_PREFIX) - if line.start_with?(CREW_PREFIX) - if conflicts.include?(line) - puts "#{line} is in another package. It will not be removed during the removal of #{pkg_name}".orange - else - FileUtils.rm_rf line - end - end - end - end - - # remove all directories installed by the package - File.foreach("meta/#{pkg_name}.directorylist", chomp: true) do |line| - puts "directorylist contains #{line}".lightred if @opt_verbose && !line.include?(CREW_PREFIX) - next unless Dir.exist?(line) && Dir.empty?(line) && line.include?(CREW_PREFIX) - - puts "Removing directory #{line}".lightred if @opt_verbose - FileUtils.rmdir(line) - end - - # remove the file and directory list - FileUtils.rm_f Dir["meta/#{pkg_name}.{file,directory}list"] - end - end - - # remove from installed packages - puts "Removing package #{pkg_name}".lightred if @opt_verbose - @device[:installed_packages].delete_if { |elem| elem[:name] == pkg_name } - - # update the device manifest - File.write "#{CREW_CONFIG_PATH}/device.json", JSON.pretty_generate(JSON.parse(@device.to_json)) - - search pkg_name, true - @pkg.remove unless @in_fixup - - puts "#{pkg_name.capitalize} removed!".lightgreen -end - def print_deps_tree(args) warn 'Walking through dependencies recursively, this may take a while...', '' @@ -1905,7 +1829,10 @@ def reinstall_command(args) end def remove_command(args) - args[''].each {|name| remove name } + args[''].each do |name| + search name + Command.remove(@pkg, @opt_verbose) + end end def search_command(args) diff --git a/commands/remove.rb b/commands/remove.rb new file mode 100644 index 000000000..a85ae3408 --- /dev/null +++ b/commands/remove.rb @@ -0,0 +1,67 @@ +require 'fileutils' +require 'json' +require_relative '../lib/const' + +class Command + def self.remove(pkg, verbose) + device_json = JSON.load_file(File.join(CREW_CONFIG_PATH, 'device.json')) + + # Make sure the package is actually installed before we attempt to remove it. + if device_json['installed_packages'].none? { |entry| entry['name'] == pkg.name } + puts "Package #{pkg.name} isn't installed.".lightred + return + end + + # Don't remove any of the packages ruby (and thus crew) needs to run. + if %w[gcc_lib glibc gmp ruby zlibpkg zstd].include?(pkg.name) + puts "Refusing to remove essential package #{pkg.name}.".lightred + return + end + + # We can't remove a package if we don't have the filelist. + unless File.file?(File.join(CREW_META_PATH, "#{pkg.name}.filelist")) + puts "Unable to remove package #{pkg.name} as it does not have a filelist.".lightred + return + end + + # Perform any operations required prior to package removal. + pkg.preremove + + # Remove the files and directories installed by the package. + Dir.chdir CREW_CONFIG_PATH do + # Remove all files installed by the package. + File.foreach(File.join(CREW_META_PATH, "#{pkg.name}.filelist"), chomp: true) do |line| + next unless line.start_with?(CREW_PREFIX) + if system("grep --exclude #{pkg.name}.filelist -Fxq #{line} ./meta/*.filelist") + puts "#{line} is in another package. It will not be removed during the removal of #{pkg.name}.".orange + else + puts "Removing file #{line}".yellow if verbose + FileUtils.remove_file line + end + end + + # Remove all directories installed by the package. + File.foreach(File.join(CREW_META_PATH, "#{pkg.name}.directorylist"), chomp: true) do |line| + next unless Dir.exist?(line) && Dir.empty?(line) && line.include?(CREW_PREFIX) + puts "Removing directory #{line}".yellow if verbose + Dir.rmdir line + end + + # Remove the file and directory lists. + FileUtils.remove_file File.join(CREW_META_PATH, "#{pkg.name}.filelist") + FileUtils.remove_file File.join(CREW_META_PATH, "#{pkg.name}.directorylist") + end + + # Remove the package from the list of installed packages in device.json. + puts "Removing package #{pkg_name} from device.json".yellow if verbose + device_json['installed_packages'].delete_if { |entry| entry['name'] == pkg.name } + + # Update device.json with our changes. + File.write File.join(CREW_CONFIG_PATH, 'device.json'), JSON.pretty_generate(JSON.parse(device_json.to_json)) + + # Perform any operations required after package removal. + pkg.remove + + puts "#{pkg.name} removed!".lightgreen + end +end diff --git a/lib/const.rb b/lib/const.rb index cc7298383..3f42c6584 100644 --- a/lib/const.rb +++ b/lib/const.rb @@ -1,7 +1,7 @@ # lib/const.rb # Defines common constants used in different parts of crew -CREW_VERSION = '1.46.2' +CREW_VERSION = '1.46.3' # kernel architecture KERN_ARCH = `uname -m`.chomp @@ -307,10 +307,6 @@ PY_SETUP_INSTALL_OPTIONS = "#{PY_SETUP_INSTALL_OPTIONS_NO_SVEM} --single PY3_BUILD_OPTIONS = '--wheel --no-isolation' PY3_INSTALLER_OPTIONS = "--destdir=#{CREW_DEST_DIR} --compile-bytecode 2 dist/*.whl" -CREW_ESSENTIAL_FILES = `LD_TRACE_LOADED_OBJECTS=1 #{CREW_PREFIX}/bin/ruby`.scan(/\t([^ ]+)/).flatten + - %w[libzstd.so.1 libstdc++.so.6] -CREW_ESSENTIAL_FILES.uniq! - CREW_LICENSE = <<~LICENSESTRING Copyright (C) 2013-2024 Chromebrew Authors @@ -348,7 +344,7 @@ CREW_DOCOPT = <<~DOCOPT crew postinstall [options] [-v|--verbose] ... crew prop [] crew reinstall [options] [-k|--keep] [-s|--source] [-S|--recursive-build] [-v|--verbose] ... - crew remove [options] [-v|--verbose] ... + crew remove [-v|--verbose] ... crew search [options] [-v|--verbose] [ ...] crew sysinfo [-v|--verbose] crew test [-v|--verbose] [ ...] diff --git a/lib/fixup.rb b/lib/fixup.rb index b56589bde..39a033d46 100644 --- a/lib/fixup.rb +++ b/lib/fixup.rb @@ -128,14 +128,14 @@ pkg_update_arr.each do |pkg| print "\nWould you like to remove deprecated package #{pkg[:pkg_name].capitalize}? [y/N] " case $stdin.gets.chomp.downcase when 'y', 'yes' - @in_fixup = true - begin - remove pkg[:pkg_name] - rescue NoMethodError # This won't work the first time crew update happens, since this requires an update to crew. - puts "Please rerun 'crew update' to allow for removal of #{pkg[:pkg_name].capitalize}.".orange - puts "#{pkg[:pkg_name].capitalize} not removed.".lightblue + # Create a minimal Package object and pass it to Command.remove + pkg_object = Package + pkg_object.instance_eval do + self.name = pkg[:pkg_name] + def self.preremove; end + def self.remove; end end - @in_fixup = false + Command.remove(pkg_object, @opt_verbose) else puts "#{pkg[:pkg_name].capitalize} not removed.".lightblue end