我想打扫一个小系统房。本质上,
(Gem.all_system_gems - Bundler.referenced_gems(array_of_gemfile_locks)).each do |gem, ver|
`gem uninstall #{gem} -v #{ver}
end
任何这样的 RubyGems/Bundler 方法?或者任何已知/有效的方式来完成同样的事情?
谢谢,本
Bundler has a clean
command to remove unused gems.
bundle clean --force
This will remove all gems that are not needed by the current project.
If you want to keep your system's gem repository clean you should consider using the --path
option with bundle install
. This will allow you to keep project dependencies outside of the system's gem repository.
注意:可能造成严重的脑损伤。
我在这里放了一个版本来解释每个功能。
# gem_cleaner.rb
require 'bundler'
`touch Gemfile` unless File.exists?("Gemfile")
dot_lockfiles = [ "/path/to/gemfile1.lock", "/path/to/gemfile2.lock"
# ..and so on...
]
lockfile_parser = ->(path) do
Bundler::LockfileParser.new(File.read(path))
end
lockfile_specs = ->(lockfile) { lockfile.specs.map(&:to_s) }
de_parenthesize = ->(string) { string.gsub(/\,|\(|\)/, "") }
uninstaller = ->(string) do
`gem uninstall #{string.split(" ").map(&de_parenthesize).join(" -v ")}`
end
splitter = ->(string) do
temp = string.split(" ").map(&de_parenthesize)
gem_name = temp.shift
temp.map {|x| "#{gem_name} (#{x})"}
end
# Remove #lazy and #to_a if on Ruby version < 2.0
gems_to_be_kept = dot_lockfiles.lazy.map(&lockfile_parser).map(&lockfile_specs).to_a.uniq
all_installed_gems = `gem list`.split("\n").map(&splitter).flatten
gems_to_be_uninstalled = all_installed_gems - gems_to_be_kept
gems_to_be_uninstalled.map(&uninstaller)
为什么我这样写这个片段?前几天我碰巧看到了这个: http: //www.confreaks.com/videos/2382-rmw2013-functional-principles-for-oo-development
如果您在 *nix 或 Mac OS 上,您可以将要删除的 gem 的名称放在一个文本文件中。然后运行这个命令:
xargs gem uninstall < path/to/text/file
xargs
是处理长文件列表的好工具。在这种情况下,当它通过 STDIN 管道输入时,它会获取文本文件的内容,并将读取的每一行放入gem uninstall
. 它将继续这样做,直到文本文件用完为止。
此代码基于@Kashyap 回答的内容(Bundler::LockfileParser 是一个不错的发现)。我最终对其进行了一些更改,并想分享我最终使用的内容。
require 'rubygems'
require 'bundler'
LOCK_FILES = %w(/path/to/first/Gemfile.lock /path/to/second/Gemfile.lock)
REVIEWABLE_SHELL_SCRIPT = 'gem_cleaner.csh'
class GemCleaner
def initialize lock_files, output_file
@lock_files = lock_files
@output_file = output_file
end
def lock_file_gems
@lock_files.map do |lock_file|
Bundler::LockfileParser.new(File.read(lock_file)).specs.
map {|s| [s.name, s.version.version] }
end.flatten(1).uniq
end
def installed_gems
Gem::Specification.find_all.map {|s| [s.name, s.version.version] }
end
def gems_to_uninstall
installed_gems - lock_file_gems
end
def create_shell_script
File.open(@output_file, 'w', 0744) do |f|
f.puts "#!/bin/csh"
gems_to_uninstall.sort.each {|g| f.puts "gem uninstall #{g[0]} -v #{g[1]}" }
end
end
end
gc = GemCleaner.new(LOCK_FILES, REVIEWABLE_SHELL_SCRIPT)
gc.create_shell_script
主要区别在于使用 Gem::Specification.find_all 并输出到 shell 脚本,这样我就可以在卸载之前查看 gem。哦,仍然使用老式的 OO 方式。:)
用@Kashyap 留下选定的答案。道具。