lib/logical-construct/resolving-task.rb in logical-construct-0.0.1.localtesting vs lib/logical-construct/resolving-task.rb in logical-construct-0.0.1
- old
+ new
@@ -1,7 +1,8 @@
require 'rake/task'
require 'mattock/task'
+require 'logical-construct/satisfiable-task'
module LogicalConstruct
#Ensures that all it's deps are satisfied before proceeding - the action for
#ResolvingTasks is all about satisfying deps.
#
@@ -15,24 +16,126 @@
# and #execute if needed
#
#So, of note: you'll only get invoked once, ever
#You'll only be executed if #needed?
#Deps will get invoked (ish) even if not #needed?
- #
+ module SatisfiableManager
+ def default_configuration(*configurables)
+ super
+ self.satisfiables = configurables.find_all do |conf|
+ conf.is_a? SatisfiableTask
+ end.map{|sat| sat.rake_task}
+ end
+
+ def define
+ super
+ satisfiables.each do |sat|
+ sat.enhance([rake_task.name])
+ end
+ end
+
+ def add_satisfiable(task)
+ task = task.rake_task if task.respond_to? :rake_task
+ satisfiables << task
+ task.enhance([rake_task.name])
+ end
+ end
+
+ require 'yaml'
+ require 'digest'
+ module ResolutionProtocol
+ def digest
+ @digest ||= Digest::SHA2.new
+ end
+
+ def file_checksum(path)
+ generate_checksum(File::read(path))
+ end
+
+ def generate_checksum(data)
+ digest.reset
+ digest << data
+ digest.hexdigest
+ end
+
+ def web_path(task_name)
+ "/" + task_name.gsub(":", "/")
+ end
+ end
+
class ResolvingTask < Rake::Task
include Mattock::TaskMixin
+ include SatisfiableManager
+ setting :satisfiables, []
+
def needed?
- prerequisite_tasks.any?{|task| task.needed?}
+ !unsatisfied.empty?
end
- def unsatisfied_prerequisites
- prerequisite_tasks.find_all{|task| task.needed?}
+ def unsatisfied
+ satisfiables.find_all{|task| task.needed?}
end
def execute(args=nil)
super
if needed?
- raise "Task #{name} failed to satisfy: #{unsatisfied_prerequisites.inspect}"
+ raise "Task #{name} failed to satisfy: #{unsatisfied.inspect}"
end
+ end
+ end
+
+ class Manifest < SatisfiableTask
+ include SatisfiableManager
+ include ResolutionProtocol
+
+ setting :satisfiables, []
+ nil_field :manifest
+
+ default_taskname "Manifest"
+
+ def invalid_checksum(checksum, path)
+ return false unless File::exists?(path)
+ return true if checksum.nil? or checksum.empty?
+ return checksum != file_checksum(path)
+ end
+
+ def needed?
+ manifest.nil?
+ end
+
+ def fulfill(data)
+ self.manifest = YAML::load(data)
+ satisfiables.each do |sat|
+ path = sat.target_path
+ checksum = manifest[sat.name]
+ if invalid_checksum(checksum, path)
+ File::rename(path, path + ".invalid")
+ end
+ end
+ end
+ end
+
+ class GenerateManifest < Mattock::Task
+ include ResolutionProtocol
+ setting :hash, {}
+ setting :resolutions
+ setting :receiving_name
+
+ def default_configuration(resolution_host)
+ super
+ self.resolutions = resolution_host.resolutions
+ end
+
+ def data_checksum(path, data)
+ hash[path] = generate_checksum(data)
+ end
+
+ def action
+ resolutions.each_pair do |destination, data|
+ data = data.call if data.respond_to? :call
+ data = data.read if data.respond_to? :read
+ hash[destination] = generate_checksum(data)
+ end
+ resolutions[receiving_name] = YAML::dump(hash)
end
end
end