Advertisement
Guest User

Untitled

a guest
Feb 27th, 2020
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.58 KB | None | 0 0
  1. #!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby
  2.  
  3. require "English"
  4. require "fileutils"
  5. require "optparse"
  6. require "pathname"
  7.  
  8. # Default options
  9. options = {
  10. :force => false,
  11. :quiet => false,
  12. :dry_run => false,
  13. :skip_cache_and_logs => false,
  14. }
  15.  
  16. # global status to indicate whether there is anything wrong.
  17. @failed = false
  18.  
  19. module Tty
  20. module_function
  21.  
  22. def blue
  23. bold 34
  24. end
  25.  
  26. def red
  27. bold 31
  28. end
  29.  
  30. def reset
  31. escape 0
  32. end
  33.  
  34. def bold(code = 39)
  35. escape "1;#{code}"
  36. end
  37.  
  38. def escape(code)
  39. "\033[#{code}m" if STDOUT.tty?
  40. end
  41. end
  42.  
  43. class Array
  44. def shell_s
  45. cp = dup
  46. first = cp.shift
  47. cp.map { |arg| arg.gsub " ", "\\ " }.unshift(first).join(" ")
  48. end
  49. end
  50.  
  51. class Pathname
  52. def resolved_path
  53. symlink? ? dirname+readlink : self
  54. end
  55.  
  56. def /(other)
  57. self + other.to_s
  58. end
  59.  
  60. def pretty_print
  61. if symlink?
  62. puts to_s + " -> " + resolved_path.to_s
  63. elsif directory?
  64. puts to_s + "/"
  65. else
  66. puts to_s
  67. end
  68. end
  69. end
  70.  
  71. def ohai(*args)
  72. puts "#{Tty.blue}==>#{Tty.bold} #{args.shell_s}#{Tty.reset}"
  73. end
  74.  
  75. def warn(warning)
  76. puts "#{Tty.red}Warning#{Tty.reset}: #{warning.chomp}"
  77. end
  78.  
  79. def system(*args)
  80. return if Kernel.system(*args)
  81.  
  82. warn "Failed during: #{args.shell_s}"
  83. @failed = true
  84. end
  85.  
  86. ####################################################################### script
  87.  
  88. homebrew_prefix_candidates = []
  89.  
  90. OptionParser.new do |opts|
  91. opts.banner = "Homebrew Uninstaller\nUsage: ./uninstall [options]"
  92. opts.summary_width = 16
  93. opts.on("-pPATH", "--path=PATH", "Sets Homebrew prefix. Defaults to /usr/local.") do |p|
  94. homebrew_prefix_candidates << Pathname.new(p)
  95. end
  96. opts.on("--skip-cache-and-logs", "Skips removal of HOMEBREW_CACHE and HOMEBREW_LOGS.") do
  97. options[:skip_cache_and_logs] = true
  98. end
  99. opts.on("-f", "--force", "Uninstall without prompting.") { options[:force] = true }
  100. opts.on("-q", "--quiet", "Suppress all output.") { options[:quiet] = true }
  101. opts.on("-d", "--dry-run", "Simulate uninstall but don't remove anything.") do
  102. options[:dry_run] = true
  103. end
  104. opts.on_tail("-h", "--help", "Display this message.") do
  105. puts opts
  106. exit
  107. end
  108. end.parse!
  109.  
  110. if homebrew_prefix_candidates.empty? # Attempt to locate Homebrew unless `--path` is passed
  111. prefix =
  112. begin
  113. `brew --prefix`
  114. rescue
  115. ""
  116. end
  117. homebrew_prefix_candidates << Pathname.new(prefix.strip) unless prefix.empty?
  118. prefix =
  119. begin
  120. begin
  121. `command -v brew`
  122. rescue
  123. `which brew`
  124. end
  125. rescue
  126. ""
  127. end
  128. homebrew_prefix_candidates << Pathname.new(prefix.strip).dirname.parent unless prefix.empty?
  129. homebrew_prefix_candidates << Pathname.new("/usr/local") # Homebrew default path
  130. homebrew_prefix_candidates << Pathname.new("#{ENV["HOME"]}/.linuxbrew") # Linuxbrew default path
  131. end
  132.  
  133. HOMEBREW_PREFIX = homebrew_prefix_candidates.find do |p|
  134. next unless p.directory?
  135. if p.to_s == "/usr/local" && File.exist?("/usr/local/Homebrew/.git")
  136. next true
  137. end
  138.  
  139. (p/".git").exist? || (p/"bin/brew").executable?
  140. end
  141. abort "Failed to locate Homebrew!" if HOMEBREW_PREFIX.nil?
  142.  
  143. HOMEBREW_REPOSITORY = if (HOMEBREW_PREFIX/".git").exist?
  144. (HOMEBREW_PREFIX/".git").realpath.dirname
  145. elsif (HOMEBREW_PREFIX/"bin/brew").exist?
  146. (HOMEBREW_PREFIX/"bin/brew").realpath.dirname.parent
  147. end
  148. abort "Failed to locate Homebrew!" if HOMEBREW_REPOSITORY.nil?
  149.  
  150. HOMEBREW_CELLAR = if (HOMEBREW_PREFIX/"Cellar").exist?
  151. HOMEBREW_PREFIX/"Cellar"
  152. else
  153. HOMEBREW_REPOSITORY/"Cellar"
  154. end
  155.  
  156. gitignore =
  157. begin
  158. (HOMEBREW_REPOSITORY/".gitignore").read
  159. rescue Errno::ENOENT
  160. `curl -fsSL https://raw.githubusercontent.com/Homebrew/brew/master/.gitignore`
  161. end
  162. abort "Failed to fetch Homebrew .gitignore!" if gitignore.empty?
  163.  
  164. homebrew_files = gitignore.split("\n")
  165. .select { |line| line.start_with? "!" }
  166. .map { |line| line.chomp("/").gsub(%r{^!?/}, "") }
  167. .reject { |line| %w[bin share share/doc].include?(line) }
  168. .map { |p| HOMEBREW_REPOSITORY/p }
  169. if HOMEBREW_PREFIX.to_s != HOMEBREW_REPOSITORY.to_s
  170. homebrew_files << HOMEBREW_REPOSITORY
  171. homebrew_files += %w[
  172. bin/brew
  173. etc/bash_completion.d/brew
  174. share/doc/homebrew
  175. share/man/man1/brew.1
  176. share/man/man1/brew-cask.1
  177. share/zsh/site-functions/_brew
  178. share/zsh/site-functions/_brew_cask
  179. var/homebrew
  180. ].map { |p| HOMEBREW_PREFIX/p }
  181. else
  182. homebrew_files << HOMEBREW_REPOSITORY/".git"
  183. end
  184. homebrew_files << HOMEBREW_CELLAR
  185. homebrew_files << HOMEBREW_PREFIX/"Caskroom"
  186.  
  187. unless options[:skip_cache_and_logs]
  188. homebrew_files += %W[
  189. #{ENV["HOME"]}/Library/Caches/Homebrew
  190. #{ENV["HOME"]}/Library/Logs/Homebrew
  191. /Library/Caches/Homebrew
  192. #{ENV["HOME"]}/.cache/Homebrew
  193. #{ENV["HOMEBREW_CACHE"]}
  194. #{ENV["HOMEBREW_LOGS"]}
  195. ].map { |p| Pathname.new(p) }
  196. end
  197.  
  198. if RUBY_PLATFORM.to_s.downcase.include? "darwin"
  199. homebrew_files += %W[
  200. /Applications
  201. #{ENV["HOME"]}/Applications
  202. ].map { |p| Pathname.new(p) }.select(&:directory?).map do |p|
  203. p.children.select do |app|
  204. app.resolved_path.to_s.start_with? HOMEBREW_CELLAR.to_s
  205. end
  206. end.flatten
  207. end
  208.  
  209. homebrew_files = homebrew_files.select(&:exist?).sort
  210.  
  211. unless options[:quiet]
  212. warn "This script #{options[:dry_run] ? "would" : "will"} remove:"
  213. homebrew_files.each(&:pretty_print)
  214. end
  215.  
  216. if STDIN.tty? && (!options[:force] && !options[:dry_run])
  217. STDERR.print "Are you sure you want to uninstall Homebrew? This will remove your installed packages! [y/N] "
  218. abort unless gets.rstrip =~ /y|yes/i
  219. end
  220.  
  221. ohai "Removing Homebrew installation..." unless options[:quiet]
  222. paths = %w[Frameworks bin etc include lib opt sbin share var]
  223. .map { |p| HOMEBREW_PREFIX/p }
  224. .select(&:exist?)
  225. .map(&:to_s)
  226. if paths.any?
  227. args = %w[-E] + paths + %w[-regex .*/info/([^.][^/]*\.info|dir)]
  228. if options[:dry_run]
  229. args << "-print"
  230. else
  231. args += %w[-exec /bin/bash -c]
  232. args << "/usr/bin/install-info --delete --quiet {} \"$(dirname {})/dir\""
  233. args << ";"
  234. end
  235. puts "Would delete:" if options[:dry_run]
  236. system "/usr/bin/find", *args
  237. args = paths + %w[-type l -lname */Cellar/*]
  238. if options[:dry_run]
  239. args << "-print"
  240. else
  241. args += %w[-exec unlink {} ;]
  242. end
  243. puts "Would delete:" if options[:dry_run]
  244. system "/usr/bin/find", *args
  245. end
  246.  
  247. homebrew_files.each do |file|
  248. if options[:dry_run]
  249. puts "Would delete #{file}"
  250. else
  251. begin
  252. FileUtils.rm_rf(file)
  253. rescue => e
  254. warn "Failed to delete #{file}"
  255. puts e.message
  256. @failed = true
  257. end
  258. end
  259. end
  260.  
  261. # Invalidate sudo timestamp before exiting
  262. at_exit { Kernel.system "/usr/bin/sudo", "-k" }
  263.  
  264. def sudo(*args)
  265. ohai "/usr/bin/sudo", *args
  266. system "/usr/bin/sudo", *args
  267. end
  268.  
  269. ohai "Removing empty directories..." unless options[:quiet]
  270. paths = %w[bin etc include lib opt sbin share var
  271. Caskroom Cellar Homebrew Frameworks]
  272. .map { |p| HOMEBREW_PREFIX/p }
  273. .select(&:exist?)
  274. .map(&:to_s)
  275. if paths.any?
  276. args = paths + %w[-name .DS_Store]
  277. if options[:dry_run]
  278. args << "-print"
  279. else
  280. args << "-delete"
  281. end
  282. puts "Would delete:" if options[:dry_run]
  283. sudo "/usr/bin/find", *args
  284. args = paths + %w[-depth -type d -empty]
  285. if options[:dry_run]
  286. args << "-print"
  287. else
  288. args += %w[-exec rmdir {} ;]
  289. end
  290. puts "Would remove directories:" if options[:dry_run]
  291. sudo "/usr/bin/find", *args
  292. end
  293.  
  294. if options[:dry_run]
  295. exit
  296. else
  297. if HOMEBREW_PREFIX.to_s != "/usr/local" && HOMEBREW_PREFIX.exist?
  298. sudo "rmdir", HOMEBREW_PREFIX.to_s
  299. end
  300. if HOMEBREW_PREFIX.to_s != HOMEBREW_REPOSITORY.to_s && HOMEBREW_REPOSITORY.exist?
  301. sudo "rmdir", HOMEBREW_REPOSITORY.to_s
  302. end
  303. end
  304.  
  305. unless options[:quiet]
  306. if @failed
  307. warn "Homebrew partially uninstalled (but there were steps that failed)!"
  308. puts "To finish uninstalling rerun this script with `sudo`."
  309. else
  310. ohai "Homebrew uninstalled!"
  311. end
  312. end
  313.  
  314. residual_files = []
  315. residual_files.concat(HOMEBREW_REPOSITORY.children) if HOMEBREW_REPOSITORY.exist?
  316. residual_files.concat(HOMEBREW_PREFIX.children) if HOMEBREW_PREFIX.exist?
  317. residual_files.uniq!
  318.  
  319. unless residual_files.empty? || options[:quiet]
  320. puts "The following possible Homebrew files were not deleted:"
  321. residual_files.each(&:pretty_print)
  322. puts "You may wish to remove them yourself.\n"
  323. end
  324.  
  325. exit 1 if @failed
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement