cleaner: clean up broken and orphaned symlinks

This commit is contained in:
Jack Nagel 2013-12-21 23:28:04 -06:00
parent f55e93d9fc
commit d19934dcb7
2 changed files with 94 additions and 28 deletions

View File

@ -22,28 +22,36 @@ class Cleaner
f.info.rmtree if f.info.directory? and not f.skip_clean? f.info f.info.rmtree if f.info.directory? and not f.skip_clean? f.info
end end
# Remove empty folders. prune
# We want post-order traversal, so use a stack. end
paths = []
f.prefix.find do |path| private
if path.directory?
if f.skip_clean? path def prune
Find.prune dirs = []
else symlinks = []
paths << path
end @f.prefix.find do |path|
if @f.skip_clean? path
Find.prune
elsif path.symlink?
symlinks << path
elsif path.directory?
dirs << path
end end
end end
paths.reverse_each do |d| dirs.reverse_each do |d|
if d.children.empty? and not f.skip_clean? d if d.children.empty?
puts "rmdir: #{d} (empty)" if ARGV.verbose? puts "rmdir: #{d} (empty)" if ARGV.verbose?
d.rmdir d.rmdir
end end
end end
end
private symlinks.reverse_each do |s|
s.unlink unless s.resolved_path_exists?
end
end
# Set permissions for executables and non-executables # Set permissions for executables and non-executables
def clean_file_permissions path def clean_file_permissions path

View File

@ -63,22 +63,80 @@ class CleanerTests < Test::Unit::TestCase
assert subdir.directory? assert subdir.directory?
end end
def test_fails_to_remove_symlink_when_target_was_pruned_first def test_removes_symlink_when_target_was_pruned_first
mkpath @f.prefix/'b' dir = @f.prefix/'b'
ln_s 'b', @f.prefix/'a' symlink = @f.prefix/'a'
assert_raises(Errno::ENOENT) { Cleaner.new @f }
end
def test_fails_to_remove_symlink_pointing_to_empty_directory dir.mkpath
mkpath @f.prefix/'b' ln_s dir.basename, symlink
ln_s 'b', @f.prefix/'c'
assert_raises(Errno::ENOTDIR) { Cleaner.new @f }
end
def test_fails_to_remove_broken_symlink
ln_s 'target', @f.prefix/'symlink'
Cleaner.new @f Cleaner.new @f
assert @f.prefix.join('symlink').symlink?, "not a symlink"
assert !@f.prefix.join('symlink').exist?, "target exists" assert !dir.exist?
assert !symlink.symlink?
assert !symlink.exist?
end
def test_removes_symlink_pointing_to_empty_directory
dir = @f.prefix/'b'
symlink = @f.prefix/'c'
dir.mkpath
ln_s dir.basename, symlink
Cleaner.new @f
assert !dir.exist?
assert !symlink.symlink?
assert !symlink.exist?
end
def test_removes_broken_symlinks
symlink = @f.prefix/'symlink'
ln_s 'target', symlink
Cleaner.new @f
assert !symlink.symlink?
end
def test_skip_clean_broken_symlink
@f.class.skip_clean 'symlink'
symlink = @f.prefix/'symlink'
ln_s 'target', symlink
Cleaner.new @f
assert symlink.symlink?
end
def test_skip_clean_symlink_pointing_to_empty_directory
@f.class.skip_clean 'c'
dir = @f.prefix/'b'
symlink = @f.prefix/'c'
dir.mkpath
ln_s dir.basename, symlink
Cleaner.new @f
assert !dir.exist?
assert symlink.symlink?
assert !symlink.exist?
end
def test_skip_clean_symlink_when_target_pruned
@f.class.skip_clean 'a'
dir = @f.prefix/'b'
symlink = @f.prefix/'a'
dir.mkpath
ln_s dir.basename, symlink
Cleaner.new @f
assert !dir.exist?
assert symlink.symlink?
assert !symlink.exist?
end end
end end