2022-11-27 14:14:26 +03:00
|
|
|
#!/usr/bin/ruby
|
|
|
|
require 'fileutils'
|
|
|
|
require 'rubygems'
|
|
|
|
|
|
|
|
fu = FileUtils::Verbose
|
2024-03-15 07:55:47 +03:00
|
|
|
|
2022-11-27 14:14:26 +03:00
|
|
|
until ARGV.empty?
|
|
|
|
case ARGV.first
|
|
|
|
when '--'
|
|
|
|
ARGV.shift
|
|
|
|
break
|
2024-03-15 08:12:08 +03:00
|
|
|
when '-n', '--dry-run', '--dryrun'
|
|
|
|
## -n, --dry-run Don't remove
|
2022-11-27 14:14:26 +03:00
|
|
|
fu = FileUtils::DryRun
|
|
|
|
when /\A--make=/
|
|
|
|
# just to run when `make -n`
|
|
|
|
when /\A--mflags=(.*)/
|
|
|
|
fu = FileUtils::DryRun if /\A-\S*n/ =~ $1
|
2023-01-16 13:20:20 +03:00
|
|
|
when /\A--gem[-_]platform=(.*)/im
|
2024-03-15 07:55:47 +03:00
|
|
|
## --gem-platform=PLATFORM Platform in RubyGems style
|
2023-01-16 13:20:20 +03:00
|
|
|
gem_platform = $1
|
|
|
|
ruby_platform = nil
|
|
|
|
when /\A--ruby[-_]platform=(.*)/im
|
2024-03-15 07:55:47 +03:00
|
|
|
## --ruby-platform=PLATFORM Platform in Ruby style
|
2023-01-16 13:20:20 +03:00
|
|
|
ruby_platform = $1
|
|
|
|
gem_platform = nil
|
|
|
|
when /\A--ruby[-_]version=(.*)/im
|
2024-03-15 07:55:47 +03:00
|
|
|
## --ruby-version=VERSION Ruby version to keep
|
2023-01-16 13:20:20 +03:00
|
|
|
ruby_version = $1
|
2024-01-09 05:09:11 +03:00
|
|
|
when /\A--only=(?:(curdir|srcdir)|all)\z/im
|
2024-03-15 07:55:47 +03:00
|
|
|
## --only=(curdir|srcdir|all) Specify directory to remove gems from
|
2024-01-09 05:09:11 +03:00
|
|
|
only = $1&.downcase
|
2024-01-09 05:11:53 +03:00
|
|
|
when /\A--all\z/im
|
2024-03-15 07:55:47 +03:00
|
|
|
## --all Remove all gems not only bundled gems
|
2024-01-09 05:11:53 +03:00
|
|
|
all = true
|
2024-03-15 07:55:47 +03:00
|
|
|
when /\A--help\z/im
|
|
|
|
## --help Print this message
|
|
|
|
puts "Usage: #$0 [options] [srcdir]"
|
|
|
|
File.foreach(__FILE__) do |line|
|
|
|
|
line.sub!(/^ *## /, "") or next
|
|
|
|
break if line.chomp!.empty?
|
|
|
|
opt, desc = line.split(/ {2,}/, 2)
|
|
|
|
printf " %-28s %s\n", opt, desc
|
|
|
|
end
|
|
|
|
exit
|
2022-11-27 14:14:26 +03:00
|
|
|
when /\A-/
|
|
|
|
raise "#{$0}: unknown option: #{ARGV.first}"
|
|
|
|
else
|
|
|
|
break
|
|
|
|
end
|
2024-03-15 07:55:47 +03:00
|
|
|
##
|
2022-11-27 14:14:26 +03:00
|
|
|
ARGV.shift
|
|
|
|
end
|
|
|
|
|
2024-01-09 09:14:06 +03:00
|
|
|
gem_platform ||= Gem::Platform.new(ruby_platform).to_s if ruby_platform
|
2023-01-16 13:20:20 +03:00
|
|
|
|
2022-11-27 14:14:26 +03:00
|
|
|
class Removal
|
2022-12-21 14:52:55 +03:00
|
|
|
attr_reader :base
|
|
|
|
|
2022-11-27 14:14:26 +03:00
|
|
|
def initialize(base = nil)
|
|
|
|
@base = (File.join(base, "/") if base)
|
|
|
|
@remove = {}
|
|
|
|
end
|
|
|
|
|
|
|
|
def prefixed(name)
|
|
|
|
@base ? File.join(@base, name) : name
|
|
|
|
end
|
|
|
|
|
|
|
|
def stripped(name)
|
|
|
|
if @base && name.start_with?(@base)
|
|
|
|
name[@base.size..-1]
|
|
|
|
else
|
|
|
|
name
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def slash(name)
|
|
|
|
name.sub(%r[[^/]\K\z], '/')
|
|
|
|
end
|
|
|
|
|
|
|
|
def exist?(name)
|
|
|
|
!@remove.fetch(name) {|k| @remove[k] = !File.exist?(prefixed(name))}
|
|
|
|
end
|
|
|
|
def directory?(name)
|
|
|
|
!@remove.fetch(slash(name)) {|k| @remove[k] = !File.directory?(prefixed(name))}
|
|
|
|
end
|
|
|
|
|
|
|
|
def unlink(name)
|
|
|
|
@remove[stripped(name)] = :rm_f
|
|
|
|
end
|
|
|
|
def rmdir(name)
|
|
|
|
@remove[slash(stripped(name))] = :rm_rf
|
|
|
|
end
|
|
|
|
|
|
|
|
def glob(pattern, *rest)
|
|
|
|
Dir.glob(prefixed(pattern), *rest) {|n|
|
|
|
|
yield stripped(n)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2024-01-09 08:27:46 +03:00
|
|
|
def sorted
|
|
|
|
@remove.sort_by {|k, | [-k.count("/"), k]}
|
|
|
|
end
|
|
|
|
|
2022-11-27 14:14:26 +03:00
|
|
|
def each_file
|
2024-01-09 08:27:46 +03:00
|
|
|
sorted.each {|k, v| yield prefixed(k) if v == :rm_f}
|
2022-11-27 14:14:26 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
def each_directory
|
2024-01-09 08:27:46 +03:00
|
|
|
sorted.each {|k, v| yield prefixed(k) if v == :rm_rf}
|
2022-11-27 14:14:26 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
srcdir = Removal.new(ARGV.shift)
|
2022-12-21 14:52:55 +03:00
|
|
|
curdir = !srcdir.base || File.identical?(srcdir.base, ".") ? srcdir : Removal.new
|
2022-11-27 14:14:26 +03:00
|
|
|
|
2024-01-09 08:52:44 +03:00
|
|
|
bundled = File.readlines("#{srcdir.base}gems/bundled_gems").
|
|
|
|
grep(/^(\w\S+)\s+\S+(?:\s+\S+\s+(\S+))?/) {$~.captures}.to_h rescue nil
|
2024-01-09 05:11:53 +03:00
|
|
|
|
2022-11-27 14:14:26 +03:00
|
|
|
srcdir.glob(".bundle/gems/*/") do |dir|
|
2024-01-09 05:11:53 +03:00
|
|
|
base = File.basename(dir)
|
2024-01-09 08:52:44 +03:00
|
|
|
next if !all && bundled && !bundled.key?(base[/\A.+(?=-)/])
|
2024-01-09 05:11:53 +03:00
|
|
|
unless srcdir.exist?("gems/#{base}.gem")
|
2022-11-27 14:14:26 +03:00
|
|
|
srcdir.rmdir(dir)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-01-09 08:52:44 +03:00
|
|
|
srcdir.glob(".bundle/.timestamp/*.revision") do |file|
|
|
|
|
unless bundled&.fetch(File.basename(file, ".revision"), nil)
|
|
|
|
srcdir.unlink(file)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-27 14:14:26 +03:00
|
|
|
srcdir.glob(".bundle/specifications/*.gemspec") do |spec|
|
|
|
|
unless srcdir.directory?(".bundle/gems/#{File.basename(spec, '.gemspec')}/")
|
|
|
|
srcdir.unlink(spec)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
curdir.glob(".bundle/specifications/*.gemspec") do |spec|
|
|
|
|
unless srcdir.directory?(".bundle/gems/#{File.basename(spec, '.gemspec')}")
|
|
|
|
curdir.unlink(spec)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
curdir.glob(".bundle/gems/*/") do |dir|
|
2022-12-12 11:05:37 +03:00
|
|
|
base = File.basename(dir)
|
|
|
|
unless curdir.exist?(".bundle/specifications/#{base}.gemspec") or
|
|
|
|
curdir.exist?("#{dir}/.bundled.#{base}.gemspec")
|
2022-11-27 14:14:26 +03:00
|
|
|
curdir.rmdir(dir)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
curdir.glob(".bundle/{extensions,.timestamp}/*/") do |dir|
|
2024-01-09 09:14:06 +03:00
|
|
|
unless gem_platform and File.fnmatch?(gem_platform, File.basename(dir))
|
2022-11-27 14:14:26 +03:00
|
|
|
curdir.rmdir(dir)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-01-09 09:14:06 +03:00
|
|
|
if gem_platform
|
|
|
|
curdir.glob(".bundle/{extensions,.timestamp}/#{gem_platform}/*/") do |dir|
|
|
|
|
unless ruby_version and File.fnmatch?(ruby_version, File.basename(dir, '-static'))
|
|
|
|
curdir.rmdir(dir)
|
|
|
|
end
|
2022-11-27 14:14:26 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-01-09 09:14:06 +03:00
|
|
|
if ruby_version
|
|
|
|
curdir.glob(".bundle/extensions/#{gem_platform || '*'}/#{ruby_version}/*/") do |dir|
|
|
|
|
unless curdir.exist?(".bundle/specifications/#{File.basename(dir)}.gemspec")
|
|
|
|
curdir.rmdir(dir)
|
|
|
|
end
|
2022-11-27 14:14:26 +03:00
|
|
|
end
|
|
|
|
|
2024-01-09 09:14:06 +03:00
|
|
|
curdir.glob(".bundle/.timestamp/#{gem_platform || '*'}/#{ruby_version}/.*.time") do |stamp|
|
|
|
|
dir = stamp[%r[/\.([^/]+)\.time\z], 1].gsub('.-.', '/')[%r[\A[^/]+/[^/]+]]
|
|
|
|
unless curdir.directory?(File.join(".bundle", dir))
|
|
|
|
curdir.unlink(stamp)
|
|
|
|
end
|
2022-11-27 14:14:26 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-01-09 05:09:11 +03:00
|
|
|
unless only == "curdir"
|
|
|
|
srcdir.each_file {|f| fu.rm_f(f)}
|
|
|
|
srcdir.each_directory {|d| fu.rm_rf(d)}
|
|
|
|
end
|
|
|
|
unless only == "srcdir" or curdir.equal?(srcdir)
|
2022-12-21 14:52:55 +03:00
|
|
|
curdir.each_file {|f| fu.rm_f(f)}
|
|
|
|
curdir.each_directory {|d| fu.rm_rf(d)}
|
|
|
|
end
|