prune: handle broken app symlinks

Remove broken symlinks from `/Applications` and `~/Applications` that
were previously created by `brew linkapps`, but are no longer valid
because formulae were uninstalled or the provided apps have changed.
This commit is contained in:
Martin Afanasjew 2015-12-08 09:11:33 +01:00
parent b50e950f0e
commit ea38a70395
5 changed files with 25 additions and 8 deletions

View File

@ -1,5 +1,6 @@
require "keg"
require "cmd/tap"
require "cmd/unlinkapps"
module Homebrew
def prune
@ -45,5 +46,7 @@ module Homebrew
print "and #{d} directories " if d > 0
puts "from #{HOMEBREW_PREFIX}"
end unless ARGV.dry_run?
unlinkapps_prune(:dry_run => ARGV.dry_run?, :quiet => true)
end
end

View File

@ -9,22 +9,30 @@ module Homebrew
private
def unlinkapps_prune(opts = {})
opts = opts.merge(:prune => true)
unlinkapps_from_dir(linkapps_target(:local => false), opts)
unlinkapps_from_dir(linkapps_target(:local => true), opts)
end
def unlinkapps_from_dir(target_dir, opts = {})
return unless target_dir.directory?
dry_run = opts.fetch(:dry_run, false)
quiet = opts.fetch(:quiet, false)
apps = Pathname.glob("#{target_dir}/*.app").select do |app|
unlinkapps_unlink?(app)
unlinkapps_unlink?(app, opts)
end
ObserverPathnameExtension.reset_counts!
app_kind = opts.fetch(:prune, false) ? " (broken link)" : ""
apps.each do |app|
app.extend(ObserverPathnameExtension)
if dry_run
puts "Would unlink: #{app}"
puts "Would unlink#{app_kind}: #{app}"
else
puts "Unlinking: #{app}"
puts "Unlinking#{app_kind}: #{app}" unless quiet
app.unlink
end
end
@ -44,12 +52,14 @@ module Homebrew
#{HOMEBREW_PREFIX}/opt/
].freeze
def unlinkapps_unlink?(target_app)
def unlinkapps_unlink?(target_app, opts = {})
# Skip non-symlinks and symlinks that don't point into the Homebrew prefix.
app = "#{target_app.readlink}" if target_app.symlink?
return false unless app && app.start_with?(*UNLINKAPPS_PREFIXES)
if ARGV.named.empty?
if opts.fetch(:prune, false)
!File.exist?(app) # Remove only broken symlinks in prune mode.
elsif ARGV.named.empty?
true
else
ARGV.kegs.any? { |keg| app.start_with?("#{keg}/", "#{keg.opt_record}/") }

View File

@ -340,7 +340,9 @@ With `--verbose` or `-v`, many commands print extra debugging information. Note
* `prune` [`--dry-run`]:
Remove dead symlinks from the Homebrew prefix. This is generally not
needed, but can be useful when doing DIY installations.
needed, but can be useful when doing DIY installations. Also remove broken
app symlinks from `/Applications` and `~/Applications` that were previously
created by `brew linkapps`.
If `--dry-run` or `-n` is passed, show what would be removed, but do not
actually remove anything.

View File

@ -267,7 +267,9 @@ valid version is <code>v1</code>.</p></dd>
<dt><code>pin</code> <var>formulae</var></dt><dd><p>Pin the specified <var>formulae</var>, preventing them from being upgraded when
issuing the <code>brew upgrade</code> command. See also <code>unpin</code>.</p></dd>
<dt><code>prune</code> [<code>--dry-run</code>]</dt><dd><p>Remove dead symlinks from the Homebrew prefix. This is generally not
needed, but can be useful when doing DIY installations.</p>
needed, but can be useful when doing DIY installations. Also remove broken
app symlinks from <code>/Applications</code> and <code>~/Applications</code> that were previously
created by <code>brew linkapps</code>.</p>
<p>If <code>--dry-run</code> or <code>-n</code> is passed, show what would be removed, but do not
actually remove anything.</p></dd>

View File

@ -365,7 +365,7 @@ Pin the specified \fIformulae\fR, preventing them from being upgraded when issui
.
.TP
\fBprune\fR [\fB\-\-dry\-run\fR]
Remove dead symlinks from the Homebrew prefix\. This is generally not needed, but can be useful when doing DIY installations\.
Remove dead symlinks from the Homebrew prefix\. This is generally not needed, but can be useful when doing DIY installations\. Also remove broken app symlinks from \fB/Applications\fR and \fB~/Applications\fR that were previously created by \fBbrew linkapps\fR\.
.
.IP
If \fB\-\-dry\-run\fR or \fB\-n\fR is passed, show what would be removed, but do not actually remove anything\.