[Compiler] Rewrite of the watch command that adds the following improvements:

1. For robustness, recompile is now based on comparison of corresponding css/sass file timestamps.
2. If a sass file is removed, the corresponding css file is automatically deleted.
3. CSS files will be automatically recompiled if removed. It is no longer necessary to resave the sass file.
4. First time compile is not performed if not necessary.
This commit is contained in:
Chris Eppstein 2009-06-27 18:29:47 -07:00
parent 15ebbfef30
commit 0a232bd922
4 changed files with 51 additions and 33 deletions

View File

@ -73,6 +73,13 @@ module Compass
end end
end end
def remove(file_name)
if File.exists?(file_name)
File.unlink file_name
logger.record :remove, basename(file_name)
end
end
def basename(file) def basename(file)
relativize(file) {|f| File.basename(file)} relativize(file) {|f| File.basename(file)}
end end

View File

@ -21,12 +21,12 @@ module Compass
end end
end end
def new_compiler_instance(options = {}) def new_compiler_instance(additional_options = {})
Compass::Compiler.new(working_path, Compass::Compiler.new(working_path,
projectize(Compass.configuration.sass_dir), projectize(Compass.configuration.sass_dir),
projectize(Compass.configuration.css_dir), projectize(Compass.configuration.css_dir),
Compass.sass_engine_options.merge(:quiet => options[:quiet], Compass.sass_engine_options.merge(:quiet => options[:quiet],
:force => options[:force]).merge(options)) :force => options[:force]).merge(additional_options))
end end
end end

View File

@ -7,45 +7,44 @@ module Compass
module Commands module Commands
class WatchProject < UpdateProject class WatchProject < UpdateProject
attr_accessor :last_update_time attr_accessor :last_update_time, :last_sass_files
def perform def perform
puts ">>> Compiling all stylesheets." Signal.trap("INT") do
super puts ""
self.last_update_time = most_recent_update_time exit 0
puts ">>> Compass is now watching for changes. Press Ctrl-C to Stop." end
puts ">>> Compass is watching for changes. Press Ctrl-C to Stop."
loop do loop do
# TODO: Make this efficient by using filesystem monitoring. # TODO: Make this efficient by using filesystem monitoring.
compiler = new_compiler_instance(:quiet => true)
remove_obsolete_css(compiler)
recompile(compiler)
sleep 1
end
end
def remove_obsolete_css(compiler)
sass_files = compiler.sass_files
deleted_sass_files = (last_sass_files || []) - sass_files
deleted_sass_files.each do |deleted_sass_file|
css_file = compiler.corresponding_css_file(deleted_sass_file)
remove(css_file) if File.exists?(css_file)
end
self.last_sass_files = sass_files
end
def recompile(compiler)
if file = compiler.out_of_date?
begin begin
sleep 1 puts ">>> Change detected to: #{file}"
rescue Interrupt compiler.run
puts "" rescue StandardError => e
exit 0 ::Compass::Exec.report_error(e, options)
end
file, t = should_update?
if t
begin
puts ">>> Change detected to: #{file}"
super
rescue StandardError => e
::Compass::Exec.report_error(e, options)
end
self.last_update_time = t
end end
end end
end end
def most_recent_update_time
Dir.glob(separate("#{projectize(Compass.configuration.sass_dir)}/**/*.sass")).map {|sass_file| File.stat(sass_file).mtime}.max
end
def should_update?
t = most_recent_update_time
if t > last_update_time
file = Dir.glob(separate("#{projectize(Compass.configuration.sass_dir)}/**/*.sass")).detect {|sass_file| File.stat(sass_file).mtime >= t}
[file, t]
end
end
end end
end end
end end

View File

@ -22,13 +22,25 @@ module Compass
end end
def css_files def css_files
@css_files ||= sass_files.map{|sass_file| "#{to}/#{stylesheet_name(sass_file)}.css"} @css_files ||= sass_files.map{|sass_file| corresponding_css_file(sass_file)}
end
def corresponding_css_file(sass_file)
"#{to}/#{stylesheet_name(sass_file)}.css"
end end
def target_directories def target_directories
css_files.map{|css_file| File.dirname(css_file)}.uniq.sort.sort_by{|d| d.length } css_files.map{|css_file| File.dirname(css_file)}.uniq.sort.sort_by{|d| d.length }
end end
def out_of_date?
sass_files.zip(css_files).each do |sass_filename, css_filename|
return sass_filename unless File.exists?(css_filename)
return sass_filename if File.stat(sass_filename).mtime > File.stat(css_filename).mtime
end
false
end
def run def run
Compass.configure_sass_plugin! Compass.configure_sass_plugin!
target_directories.each do |dir| target_directories.each do |dir|