Skip to content

Instantly share code, notes, and snippets.

@kgrz
Last active December 17, 2015 04:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kgrz/5553437 to your computer and use it in GitHub Desktop.
Save kgrz/5553437 to your computer and use it in GitHub Desktop.
This snippet can be used to uninstall all the Gems in your machine except the ones specified in specific Gemfile.locks. Answer to SO question http://stackoverflow.com/a/16479097/465082
require 'bundler'
# Required for Bundler::LockfileParser. This can be empty though.
`touch Gemfile` unless File.exists?("Gemfile")
# Add the paths to the Gemfile.lock files, the gems in which
# need to be protected
dot_lockfiles = [
# Add the dot_file paths you need.
"/path/to/gemfile1.lock",
"/path/to/gemfile2.lock"
# ..and so on...
]
# As the name suggests, the LockfileParser class parses a .lock file
# and generates a parse-tree of Gem specifications, Gem dependencies, Gem sources,
# and Gem platforms.
# These in turn can be obtained by calling #specs, #dependencies, #sources, #platforms etc.
# on the parsed lockfile object.
lockfile_parser = ->(path) do
Bundler::LockfileParser.new(File.read(path))
end
# The #specs method for a Bundler::LockfileParser object
# generates an array of the gem specifications of all the gems
# that are a part of your bundle (the Gemfile). The output of
# the #to_s method is in this form: 'zurb-foundation (4.1.6)'
lockfile_specs = ->(lockfile) do
lockfile.specs.map(&:to_s)
end
# We will use this function to remove the parentheses, commas in a string so that
# string of the form 'zurb-foundation (4.1.1)' can be cleaned up. This returns an Array
# in the form ['zurb-foundation', '4.1.1']
split_and_de_parenthesize = ->(string) do
string.split(" ").map {|x| x.gsub(/\,|\(|\)/, "")}
end
# CAREFUL!!11!!1
# Uninstall command. Replace the #puts function with `gem uninstall #{..the code..}`
uninstaller = ->(string) do
puts string.map(&split_and_de_parenthesize).join(" -v ")
end
# For lack of a better name, I'm using this.
# The #splitter method converts a gem list string in the form 'zurb-foundation (4.1.1, 4.1.6)'
# into two parts and returns an array in the form:
# ['zurb-foundation (4.1.1)', 'zurb-foundation (4.1.6)']
splitter = ->(string) do
# Hattip to @jessitron for suggesting the pattern matching style.
(gem_name, *versions) = string.map(&split_and_de_parenthesize)
versions.map {|x| "#{gem_name} (#{x})"}
end
# The #lazy method is available only in Ruby 2.0 and greater versions. If you're on < Ruby 2.0.0,
# remove the #lazy method and the #to_a method at the end.
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment