mirror of
https://gitee.com/ineo6/homebrew-install.git
synced 2025-06-15 01:39:15 +08:00
326 lines
8.3 KiB
Ruby
Executable File
326 lines
8.3 KiB
Ruby
Executable File
#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby
|
|
|
|
require "English"
|
|
require "fileutils"
|
|
require "optparse"
|
|
require "pathname"
|
|
|
|
# Default options
|
|
options = {
|
|
:force => false,
|
|
:quiet => false,
|
|
:dry_run => false,
|
|
:skip_cache_and_logs => false,
|
|
}
|
|
|
|
# global status to indicate whether there is anything wrong.
|
|
@failed = false
|
|
|
|
module Tty
|
|
module_function
|
|
|
|
def blue
|
|
bold 34
|
|
end
|
|
|
|
def red
|
|
bold 31
|
|
end
|
|
|
|
def reset
|
|
escape 0
|
|
end
|
|
|
|
def bold(code = 39)
|
|
escape "1;#{code}"
|
|
end
|
|
|
|
def escape(code)
|
|
"\033[#{code}m" if STDOUT.tty?
|
|
end
|
|
end
|
|
|
|
class Array
|
|
def shell_s
|
|
cp = dup
|
|
first = cp.shift
|
|
cp.map { |arg| arg.gsub " ", "\\ " }.unshift(first).join(" ")
|
|
end
|
|
end
|
|
|
|
class Pathname
|
|
def resolved_path
|
|
symlink? ? dirname+readlink : self
|
|
end
|
|
|
|
def /(other)
|
|
self + other.to_s
|
|
end
|
|
|
|
def pretty_print
|
|
if symlink?
|
|
puts to_s + " -> " + resolved_path.to_s
|
|
elsif directory?
|
|
puts to_s + "/"
|
|
else
|
|
puts to_s
|
|
end
|
|
end
|
|
end
|
|
|
|
def ohai(*args)
|
|
puts "#{Tty.blue}==>#{Tty.bold} #{args.shell_s}#{Tty.reset}"
|
|
end
|
|
|
|
def warn(warning)
|
|
puts "#{Tty.red}Warning#{Tty.reset}: #{warning.chomp}"
|
|
end
|
|
|
|
def system(*args)
|
|
return if Kernel.system(*args)
|
|
|
|
warn "Failed during: #{args.shell_s}"
|
|
@failed = true
|
|
end
|
|
|
|
####################################################################### script
|
|
|
|
homebrew_prefix_candidates = []
|
|
|
|
OptionParser.new do |opts|
|
|
opts.banner = "Homebrew Uninstaller\nUsage: ./uninstall [options]"
|
|
opts.summary_width = 16
|
|
opts.on("-pPATH", "--path=PATH", "Sets Homebrew prefix. Defaults to /usr/local.") do |p|
|
|
homebrew_prefix_candidates << Pathname.new(p)
|
|
end
|
|
opts.on("--skip-cache-and-logs", "Skips removal of HOMEBREW_CACHE and HOMEBREW_LOGS.") do
|
|
options[:skip_cache_and_logs] = true
|
|
end
|
|
opts.on("-f", "--force", "Uninstall without prompting.") { options[:force] = true }
|
|
opts.on("-q", "--quiet", "Suppress all output.") { options[:quiet] = true }
|
|
opts.on("-d", "--dry-run", "Simulate uninstall but don't remove anything.") do
|
|
options[:dry_run] = true
|
|
end
|
|
opts.on_tail("-h", "--help", "Display this message.") do
|
|
puts opts
|
|
exit
|
|
end
|
|
end.parse!
|
|
|
|
if homebrew_prefix_candidates.empty? # Attempt to locate Homebrew unless `--path` is passed
|
|
prefix =
|
|
begin
|
|
`brew --prefix`
|
|
rescue
|
|
""
|
|
end
|
|
homebrew_prefix_candidates << Pathname.new(prefix.strip) unless prefix.empty?
|
|
prefix =
|
|
begin
|
|
begin
|
|
`command -v brew`
|
|
rescue
|
|
`which brew`
|
|
end
|
|
rescue
|
|
""
|
|
end
|
|
homebrew_prefix_candidates << Pathname.new(prefix.strip).dirname.parent unless prefix.empty?
|
|
homebrew_prefix_candidates << Pathname.new("/usr/local") # Homebrew default path
|
|
homebrew_prefix_candidates << Pathname.new("#{ENV["HOME"]}/.linuxbrew") # Linuxbrew default path
|
|
end
|
|
|
|
HOMEBREW_PREFIX = homebrew_prefix_candidates.find do |p|
|
|
next unless p.directory?
|
|
if p.to_s == "/usr/local" && File.exist?("/usr/local/Homebrew/.git")
|
|
next true
|
|
end
|
|
|
|
(p/".git").exist? || (p/"bin/brew").executable?
|
|
end
|
|
abort "Failed to locate Homebrew!" if HOMEBREW_PREFIX.nil?
|
|
|
|
HOMEBREW_REPOSITORY = if (HOMEBREW_PREFIX/".git").exist?
|
|
(HOMEBREW_PREFIX/".git").realpath.dirname
|
|
elsif (HOMEBREW_PREFIX/"bin/brew").exist?
|
|
(HOMEBREW_PREFIX/"bin/brew").realpath.dirname.parent
|
|
end
|
|
abort "Failed to locate Homebrew!" if HOMEBREW_REPOSITORY.nil?
|
|
|
|
HOMEBREW_CELLAR = if (HOMEBREW_PREFIX/"Cellar").exist?
|
|
HOMEBREW_PREFIX/"Cellar"
|
|
else
|
|
HOMEBREW_REPOSITORY/"Cellar"
|
|
end
|
|
|
|
gitignore =
|
|
begin
|
|
(HOMEBREW_REPOSITORY/".gitignore").read
|
|
rescue Errno::ENOENT
|
|
`curl -fsSL https://raw.githubusercontent.com/Homebrew/brew/master/.gitignore`
|
|
end
|
|
abort "Failed to fetch Homebrew .gitignore!" if gitignore.empty?
|
|
|
|
homebrew_files = gitignore.split("\n")
|
|
.select { |line| line.start_with? "!" }
|
|
.map { |line| line.chomp("/").gsub(%r{^!?/}, "") }
|
|
.reject { |line| %w[bin share share/doc].include?(line) }
|
|
.map { |p| HOMEBREW_REPOSITORY/p }
|
|
if HOMEBREW_PREFIX.to_s != HOMEBREW_REPOSITORY.to_s
|
|
homebrew_files << HOMEBREW_REPOSITORY
|
|
homebrew_files += %w[
|
|
bin/brew
|
|
etc/bash_completion.d/brew
|
|
share/doc/homebrew
|
|
share/man/man1/brew.1
|
|
share/man/man1/brew-cask.1
|
|
share/zsh/site-functions/_brew
|
|
share/zsh/site-functions/_brew_cask
|
|
var/homebrew
|
|
].map { |p| HOMEBREW_PREFIX/p }
|
|
else
|
|
homebrew_files << HOMEBREW_REPOSITORY/".git"
|
|
end
|
|
homebrew_files << HOMEBREW_CELLAR
|
|
homebrew_files << HOMEBREW_PREFIX/"Caskroom"
|
|
|
|
unless options[:skip_cache_and_logs]
|
|
homebrew_files += %W[
|
|
#{ENV["HOME"]}/Library/Caches/Homebrew
|
|
#{ENV["HOME"]}/Library/Logs/Homebrew
|
|
/Library/Caches/Homebrew
|
|
#{ENV["HOME"]}/.cache/Homebrew
|
|
#{ENV["HOMEBREW_CACHE"]}
|
|
#{ENV["HOMEBREW_LOGS"]}
|
|
].map { |p| Pathname.new(p) }
|
|
end
|
|
|
|
if RUBY_PLATFORM.to_s.downcase.include? "darwin"
|
|
homebrew_files += %W[
|
|
/Applications
|
|
#{ENV["HOME"]}/Applications
|
|
].map { |p| Pathname.new(p) }.select(&:directory?).map do |p|
|
|
p.children.select do |app|
|
|
app.resolved_path.to_s.start_with? HOMEBREW_CELLAR.to_s
|
|
end
|
|
end.flatten
|
|
end
|
|
|
|
homebrew_files = homebrew_files.select(&:exist?).sort
|
|
|
|
unless options[:quiet]
|
|
warn "This script #{options[:dry_run] ? "would" : "will"} remove:"
|
|
homebrew_files.each(&:pretty_print)
|
|
end
|
|
|
|
if STDIN.tty? && (!options[:force] && !options[:dry_run])
|
|
STDERR.print "Are you sure you want to uninstall Homebrew? This will remove your installed packages! [y/N] "
|
|
abort unless gets.rstrip =~ /y|yes/i
|
|
end
|
|
|
|
ohai "Removing Homebrew installation..." unless options[:quiet]
|
|
paths = %w[Frameworks bin etc include lib opt sbin share var]
|
|
.map { |p| HOMEBREW_PREFIX/p }
|
|
.select(&:exist?)
|
|
.map(&:to_s)
|
|
if paths.any?
|
|
args = %w[-E] + paths + %w[-regex .*/info/([^.][^/]*\.info|dir)]
|
|
if options[:dry_run]
|
|
args << "-print"
|
|
else
|
|
args += %w[-exec /bin/bash -c]
|
|
args << "/usr/bin/install-info --delete --quiet {} \"$(dirname {})/dir\""
|
|
args << ";"
|
|
end
|
|
puts "Would delete:" if options[:dry_run]
|
|
system "/usr/bin/find", *args
|
|
args = paths + %w[-type l -lname */Cellar/*]
|
|
if options[:dry_run]
|
|
args << "-print"
|
|
else
|
|
args += %w[-exec unlink {} ;]
|
|
end
|
|
puts "Would delete:" if options[:dry_run]
|
|
system "/usr/bin/find", *args
|
|
end
|
|
|
|
homebrew_files.each do |file|
|
|
if options[:dry_run]
|
|
puts "Would delete #{file}"
|
|
else
|
|
begin
|
|
FileUtils.rm_rf(file)
|
|
rescue => e
|
|
warn "Failed to delete #{file}"
|
|
puts e.message
|
|
@failed = true
|
|
end
|
|
end
|
|
end
|
|
|
|
# Invalidate sudo timestamp before exiting
|
|
at_exit { Kernel.system "/usr/bin/sudo", "-k" }
|
|
|
|
def sudo(*args)
|
|
ohai "/usr/bin/sudo", *args
|
|
system "/usr/bin/sudo", *args
|
|
end
|
|
|
|
ohai "Removing empty directories..." unless options[:quiet]
|
|
paths = %w[bin etc include lib opt sbin share var
|
|
Caskroom Cellar Homebrew Frameworks]
|
|
.map { |p| HOMEBREW_PREFIX/p }
|
|
.select(&:exist?)
|
|
.map(&:to_s)
|
|
if paths.any?
|
|
args = paths + %w[-name .DS_Store]
|
|
if options[:dry_run]
|
|
args << "-print"
|
|
else
|
|
args << "-delete"
|
|
end
|
|
puts "Would delete:" if options[:dry_run]
|
|
sudo "/usr/bin/find", *args
|
|
args = paths + %w[-depth -type d -empty]
|
|
if options[:dry_run]
|
|
args << "-print"
|
|
else
|
|
args += %w[-exec rmdir {} ;]
|
|
end
|
|
puts "Would remove directories:" if options[:dry_run]
|
|
sudo "/usr/bin/find", *args
|
|
end
|
|
|
|
if options[:dry_run]
|
|
exit
|
|
else
|
|
if HOMEBREW_PREFIX.to_s != "/usr/local" && HOMEBREW_PREFIX.exist?
|
|
sudo "rmdir", HOMEBREW_PREFIX.to_s
|
|
end
|
|
if HOMEBREW_PREFIX.to_s != HOMEBREW_REPOSITORY.to_s && HOMEBREW_REPOSITORY.exist?
|
|
sudo "rmdir", HOMEBREW_REPOSITORY.to_s
|
|
end
|
|
end
|
|
|
|
unless options[:quiet]
|
|
if @failed
|
|
warn "Homebrew partially uninstalled (but there were steps that failed)!"
|
|
puts "To finish uninstalling rerun this script with `sudo`."
|
|
else
|
|
ohai "Homebrew uninstalled!"
|
|
end
|
|
end
|
|
|
|
residual_files = []
|
|
residual_files.concat(HOMEBREW_REPOSITORY.children) if HOMEBREW_REPOSITORY.exist?
|
|
residual_files.concat(HOMEBREW_PREFIX.children) if HOMEBREW_PREFIX.exist?
|
|
residual_files.uniq!
|
|
|
|
unless residual_files.empty? || options[:quiet]
|
|
puts "The following possible Homebrew files were not deleted:"
|
|
residual_files.each(&:pretty_print)
|
|
puts "You may wish to remove them yourself.\n"
|
|
end
|
|
|
|
exit 1 if @failed
|