75 lines
1.8 KiB
Ruby
75 lines
1.8 KiB
Ruby
require 'yaml'
|
|
require 'fileutils'
|
|
require 'digest/md5'
|
|
require 'set'
|
|
|
|
module Rscons
|
|
class Cache
|
|
CACHE_FILE = '.rscons'
|
|
|
|
private_class_method :new
|
|
def initialize
|
|
@cache = YAML.load(File.read(CACHE_FILE)) rescue {}
|
|
@lookup_checksums = {}
|
|
@stored_checksums = {}
|
|
end
|
|
|
|
def self.open
|
|
@@cache ||= new
|
|
end
|
|
|
|
def clear
|
|
FileUtils.rm_f(CACHE_FILE)
|
|
initialize
|
|
end
|
|
|
|
def write
|
|
File.open(CACHE_FILE, 'w') do |fh|
|
|
fh.puts(YAML.dump(@cache))
|
|
end
|
|
end
|
|
|
|
def up_to_date?(file, deps = nil)
|
|
return false unless File.exists?(file)
|
|
stored_md5 = @cache[:checksums][file] rescue nil
|
|
return false unless stored_md5
|
|
return false unless lookup_checksum(file) == stored_md5
|
|
cached_deps = @cache[:deps][file] || [] rescue []
|
|
return false if deps and Set.new(cached_deps) != Set.new(deps)
|
|
cached_deps.map {|d| up_to_date?(d)}.all?
|
|
end
|
|
|
|
def register_build(target, deps)
|
|
@cache[:deps] ||= {}
|
|
@cache[:deps][target] = deps
|
|
store_checksum(target)
|
|
deps.each do |dep|
|
|
store_checksum(dep)
|
|
end
|
|
# it is unfortunate to write the file here since many file writes may
|
|
# occur before the final version, but I don't know where else to do so
|
|
write
|
|
end
|
|
|
|
private
|
|
|
|
def lookup_checksum(file)
|
|
@lookup_checksums[file] ||= calculate_checksum(file)
|
|
end
|
|
|
|
def store_checksum(file)
|
|
cs = calculate_checksum(file)
|
|
if @stored_checksums[file] and @stored_checksums[file] != cs
|
|
$stderr.puts "Warning: file #{file.inspect} changed after previously used by builder"
|
|
end
|
|
@cache[:checksums] ||= {}
|
|
@cache[:checksums][file] = cs
|
|
@lookup_checksums[file] = cs
|
|
end
|
|
|
|
def calculate_checksum(file)
|
|
Digest::MD5.hexdigest(File.read(file)).encode(__ENCODING__)
|
|
end
|
|
end
|
|
end
|