bin/scrub
2012-04-01 17:35:04 -07:00

117 lines
2.5 KiB
Ruby
Executable file

#!/usr/bin/env ruby
require 'digest/sha1'
require 'json'
class Scrubber
class Result
attr_reader :status
attr_reader :failures
def initialize(options)
@status = options[:status]
@failures = options[:failures] || []
end
def ok?
@status == :ok
end
end
def initialize(root_dir)
@root_dir = File.realpath(root_dir)
@failures = []
end
def scrub(dir = @root_dir)
return if File.exist?(File.join(dir, 'noscrub'))
# restore hashes if already scrubbed
hashes =
if File.exist?(hash_filename(dir))
JSON.parse(File.read(hash_filename(dir)))
else
{}
end
# walk the directory
Dir[File.join(dir, '*')].each do |file|
# skip broken symlinks
next if File.symlink?(file) && !File.exist?(file)
# descend into subdirectories
if File.directory?(file)
scrub(file)
# scrub this file
else
basename = File.basename(file)
next if basename == 'scrub.json'
relative_filename = file.sub(@root_dir + '/', '')
hash = sha1(open(file, 'rb') { |f| f.read })
if expected_hash = hashes[basename]
unless hash == expected_hash
@failures << {
:filename => relative_filename,
:hash => hash,
:expected_hash => expected_hash
}
puts "!! #{hash} not ok: #{relative_filename}"
else
puts " * #{hash} ok: #{relative_filename}"
end
else
hashes[basename] = hash
puts " * #{hash} new: #{relative_filename}"
end
end
end
# persist the hashes
File.open(hash_filename(dir), 'w') { |f| f.puts(JSON.fast_generate(hashes)) }
# build and return our result
@result = Result.new(
:status => @failures.length == 0 ? :ok : :fail,
:failures => @failures
)
end
def sha1(s)
Digest::SHA1.hexdigest(s)
end
def hash_filename(dir)
File.join(dir, 'scrub.json')
end
end
def main
if root_dir = ARGV.shift
unless File.directory?(root_dir)
puts "error: #{root_dir} is not directory"
exit 1
end
result = Scrubber.new(root_dir).scrub
unless result.ok?
# report failures
result.failures.sort do |a,b|
a[:filename] <=> b[:filename]
end.each do |failure|
puts "#{failure[:filename]}: expected #{failure[:expected_hash]}, but got #{failure[:hash]}"
end
exit 1
end
else
puts 'Usage: scrub </your/precious/data>'
exit 1
end
end
main if $0 == __FILE__