From 7602fd04bfe1424574ea26aa517d3556089a658b Mon Sep 17 00:00:00 2001 From: Maher Sallam Date: Fri, 4 May 2012 16:45:44 -0700 Subject: [PATCH 1/5] Replace the Listen plugin with an implementation of the Listen callback Conflicts: lib/sass/plugin/listener.rb vendor/listen --- lib/sass/plugin/compiler.rb | 96 ++++++++++++++++++++----------------- lib/sass/plugin/listener.rb | 58 ---------------------- 2 files changed, 53 insertions(+), 101 deletions(-) delete mode 100644 lib/sass/plugin/listener.rb diff --git a/lib/sass/plugin/compiler.rb b/lib/sass/plugin/compiler.rb index 3b99f216a5..2006301c4d 100644 --- a/lib/sass/plugin/compiler.rb +++ b/lib/sass/plugin/compiler.rb @@ -187,6 +187,9 @@ def update_stylesheets(individual_files = []) Sass::Plugin.checked_for_updates = true staleness_checker = StalenessChecker.new(engine_options) + # Remove deleted files + individual_files = individual_files.select { |files| File.exists?(files.first) } + template_location_array.each do |template_location, css_location| Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file| # Get the relative path to the file @@ -252,52 +255,59 @@ def watch(individual_files = []) end end + templates_paths = template_locations # cache the locations + individual_files_hash = individual_files.inject({}) do |h, files| + parent = File.dirname(files.first) + (h[parent] ||= []) << files unless templates_paths.include?(parent) + h + end + directories = templates_paths + individual_files_hash.keys + # TODO: Keep better track of what depends on what # so we don't have to run a global update every time anything changes. - Sass::Plugin::Listener.new do |l| - template_location_array.each do |template_location, css_location| - l.directory(template_location, { - :modified => lambda do |base, relative| - next if relative !~ /\.s[ac]ss$/ - run_template_modified File.join(base, relative) - update_stylesheets(individual_files) - end, - - :added => lambda do |base, relative| - next if relative !~ /\.s[ac]ss$/ - run_template_created File.join(base, relative) - update_stylesheets(individual_files) - end, - - :removed => lambda do |base, relative| - next if relative !~ /\.s[ac]ss$/ - run_template_deleted File.join(base, relative) - css = File.join(css_location, relative.gsub(/\.s[ac]ss$/, '.css')) - try_delete_css css - update_stylesheets(individual_files) - end - }) - end + listener = Listen::MultiListener.new(*directories, :relative_paths => true) do |modified, added, removed| + modified.each do |f| + parent = File.dirname(f) + if individual_files_hash[parent] + next if individual_files_hash[parent].first != f + else + next if f !~ /\.s[ac]ss$/ + end + run_template_modified(f) + end unless modified.empty? + + added.each do |f| + parent = File.dirname(f) + if individual_files_hash[parent] + next if individual_files_hash[parent].first != f + else + next if f !~ /\.s[ac]ss$/ + end + run_template_created(f) + end unless added.empty? + + removed.each do |f| + parent = File.dirname(f) + if individual_files_hash[parent] + next if individual_files_hash[parent].first != f + try_delete_css individual_files_hash[parent][1] + else + next if f !~ /\.s[ac]ss$/ + try_delete_css f.gsub(/\.s[ac]ss$/, '.css') + end + run_template_deleted(f) + end unless removed.empty? + + update_stylesheets(individual_files) + end - individual_files.each do |template, css| - l.file(template, { - :modified => lambda do - run_template_modified template - update_stylesheets(individual_files) - end, - - :added => lambda do - run_template_created template - update_stylesheets(individual_files) - end, - - :removed => lambda do - run_template_deleted template - try_delete_css css - update_stylesheets(individual_files) - end - }) - end + # Setup extra options for the listener + listener.force_polling(true).ignore(%r{\.sass-cache/.*}) + + begin + listener.start + rescue Exception => e + raise e unless e.is_a?(Interrupt) end end diff --git a/lib/sass/plugin/listener.rb b/lib/sass/plugin/listener.rb deleted file mode 100644 index 54752a9066..0000000000 --- a/lib/sass/plugin/listener.rb +++ /dev/null @@ -1,58 +0,0 @@ -# A wrapper around the Listen gem. Adds support for listening to individual -# files, as well as a somewhat cleaner event dispatch API. -# -# @private -class Sass::Plugin::Listener - def initialize - @directories = {} - yield self - begin - start! - rescue Exception => e - raise e unless e.is_a?(Interrupt) - end - end - - def directory(path, events) - (@directories[File.expand_path(path)] ||= []) << events - end - - def file(path, events) - file_base = File.basename(path) - directory(File.dirname(path), { - :modified => file_event_fn(events[:modified], file_base), - :added => file_event_fn(events[:added], file_base), - :removed => file_event_fn(events[:removed], file_base) - }) - end - - def start! - args = @directories.keys.dup - args << {:force_polling => Sass::Util.windows?} - listener = Listen::MultiListener.new(*args) do |modified, added, removed| - @directories.each do |dir, events| - events.each do |e| - run_events(modified, e[:modified], dir) - run_events(added, e[:added], dir) - run_events(removed, e[:removed], dir) - end - end - end.start - end - - private - - def file_event_fn(event, file_base) - lambda do |dir, base| - next unless event - next unless base == file_base - event.call - end - end - - def run_events(paths, event, dir) - return if paths.empty? || event.nil? - paths.select {|p| p.start_with?(dir)}. - each {|p| event[File.dirname(p), File.basename(p)]} - end -end From 67921a0fc665b7ea7aebe90a02f2ec71af21302a Mon Sep 17 00:00:00 2001 From: Nathan Weizenbaum Date: Fri, 4 May 2012 16:49:30 -0700 Subject: [PATCH 2/5] Fix some errors. --- lib/sass/plugin/compiler.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sass/plugin/compiler.rb b/lib/sass/plugin/compiler.rb index 2006301c4d..90312ec162 100644 --- a/lib/sass/plugin/compiler.rb +++ b/lib/sass/plugin/compiler.rb @@ -5,7 +5,6 @@ require 'sass/callbacks' require 'sass/plugin/configuration' require 'sass/plugin/staleness_checker' -require 'sass/plugin/listener' module Sass::Plugin @@ -261,11 +260,12 @@ def watch(individual_files = []) (h[parent] ||= []) << files unless templates_paths.include?(parent) h end - directories = templates_paths + individual_files_hash.keys + directories = templates_paths + individual_files_hash.keys + + [{:relative_paths => true}] # TODO: Keep better track of what depends on what # so we don't have to run a global update every time anything changes. - listener = Listen::MultiListener.new(*directories, :relative_paths => true) do |modified, added, removed| + listener = Listen::MultiListener.new(*directories) do |modified, added, removed| modified.each do |f| parent = File.dirname(f) if individual_files_hash[parent] From 28fc862fdc8fcf4afd89ce99be619dfab2f927f4 Mon Sep 17 00:00:00 2001 From: Nathan Weizenbaum Date: Fri, 4 May 2012 16:48:00 -0700 Subject: [PATCH 3/5] Fail loudly when watching non-existent files. --- lib/sass/plugin/compiler.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/sass/plugin/compiler.rb b/lib/sass/plugin/compiler.rb index 90312ec162..4902ea1bb5 100644 --- a/lib/sass/plugin/compiler.rb +++ b/lib/sass/plugin/compiler.rb @@ -186,9 +186,6 @@ def update_stylesheets(individual_files = []) Sass::Plugin.checked_for_updates = true staleness_checker = StalenessChecker.new(engine_options) - # Remove deleted files - individual_files = individual_files.select { |files| File.exists?(files.first) } - template_location_array.each do |template_location, css_location| Sass::Util.glob(File.join(template_location, "**", "[^_]*.s[ca]ss")).sort.each do |file| # Get the relative path to the file From e29c9f72f4d6b2c0e3069af39f956426b1419995 Mon Sep 17 00:00:00 2001 From: Nathan Weizenbaum Date: Fri, 4 May 2012 16:56:30 -0700 Subject: [PATCH 4/5] Style changes. --- lib/sass/plugin/compiler.rb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/sass/plugin/compiler.rb b/lib/sass/plugin/compiler.rb index 4902ea1bb5..efde859959 100644 --- a/lib/sass/plugin/compiler.rb +++ b/lib/sass/plugin/compiler.rb @@ -251,13 +251,13 @@ def watch(individual_files = []) end end - templates_paths = template_locations # cache the locations + template_paths = template_locations # cache the locations individual_files_hash = individual_files.inject({}) do |h, files| parent = File.dirname(files.first) - (h[parent] ||= []) << files unless templates_paths.include?(parent) + (h[parent] ||= []) << files unless template_paths.include?(parent) h end - directories = templates_paths + individual_files_hash.keys + + directories = template_paths + individual_files_hash.keys + [{:relative_paths => true}] # TODO: Keep better track of what depends on what @@ -265,35 +265,35 @@ def watch(individual_files = []) listener = Listen::MultiListener.new(*directories) do |modified, added, removed| modified.each do |f| parent = File.dirname(f) - if individual_files_hash[parent] - next if individual_files_hash[parent].first != f + if files = individual_files_hash[parent] + next unless files.first == f else - next if f !~ /\.s[ac]ss$/ + next unless f =~ /\.s[ac]ss$/ end run_template_modified(f) - end unless modified.empty? + end added.each do |f| parent = File.dirname(f) - if individual_files_hash[parent] - next if individual_files_hash[parent].first != f + if files = individual_files_hash[parent] + next unless files.first == f else - next if f !~ /\.s[ac]ss$/ + next unless f =~ /\.s[ac]ss$/ end run_template_created(f) - end unless added.empty? + end removed.each do |f| parent = File.dirname(f) - if individual_files_hash[parent] - next if individual_files_hash[parent].first != f - try_delete_css individual_files_hash[parent][1] + if files = individual_files_hash[parent] + next unless files.first == f + try_delete_css files[1] else - next if f !~ /\.s[ac]ss$/ + next unless f =~ /\.s[ac]ss$/ try_delete_css f.gsub(/\.s[ac]ss$/, '.css') end run_template_deleted(f) - end unless removed.empty? + end update_stylesheets(individual_files) end From a3031856b22bc834a5417dedecb038b7be9b9e3e Mon Sep 17 00:00:00 2001 From: Nathan Weizenbaum Date: Fri, 4 May 2012 16:57:30 -0700 Subject: [PATCH 5/5] Don't force polling. We want to be able to use other Listen plugins if we're using the Listen gem. --- lib/sass/plugin/compiler.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/sass/plugin/compiler.rb b/lib/sass/plugin/compiler.rb index efde859959..e84b4be40e 100644 --- a/lib/sass/plugin/compiler.rb +++ b/lib/sass/plugin/compiler.rb @@ -298,9 +298,6 @@ def watch(individual_files = []) update_stylesheets(individual_files) end - # Setup extra options for the listener - listener.force_polling(true).ignore(%r{\.sass-cache/.*}) - begin listener.start rescue Exception => e