diff --git a/lib/jekyll/command.rb b/lib/jekyll/command.rb index 62a532f6..654f0ae3 100644 --- a/lib/jekyll/command.rb +++ b/lib/jekyll/command.rb @@ -19,19 +19,29 @@ module Jekyll super(base) end - # Listing of all directories (globbed to include subfiles and folders) + # Paths to ignore for the watch option # - # source - the source path - # destination - the destination path + # options - A Hash of options passed to the command # - # Returns an Array of directory globs in the source, excluding the destination - def globs(source, destination) - Dir.chdir(source) do - dirs = Dir['*'].select { |x| File.directory?(x) } - dirs -= [destination, File.expand_path(destination), File.basename(destination)] - dirs = dirs.map { |x| "#{x}/**/*" } - dirs += ['*'] + # Returns a list of relative paths from source that should be ignored + def ignore_paths(options) + source = options['source'] + destination = options['destination'] + config_files = Configuration[options].config_files(options) + paths = config_files + Array(destination) + ignored = [] + + source_abs = Pathname.new(source).expand_path + paths.each do |p| + path_abs = Pathname.new(p).expand_path + begin + rel_path = path_abs.relative_path_from(source_abs).to_s + ignored << Regexp.new(Regexp.escape(rel_path)) unless rel_path.start_with?('../') + rescue ArgumentError + # Could not find a relative path + end end + ignored end # Run Site#process and catch errors diff --git a/lib/jekyll/commands/build.rb b/lib/jekyll/commands/build.rb index 816c5b3f..1374b0ef 100644 --- a/lib/jekyll/commands/build.rb +++ b/lib/jekyll/commands/build.rb @@ -56,20 +56,9 @@ module Jekyll def watch(site, options) require 'listen' - source = options['source'] - destination = options['destination'] - - begin - dest = Pathname.new(destination).relative_path_from(Pathname.new(source)).to_s - ignored = Regexp.new(Regexp.escape(dest)) - rescue ArgumentError - # Destination is outside the source, no need to ignore it. - ignored = nil - end - listener = Listen.to( - source, - :ignore => ignored, + options['source'], + :ignore => ignore_paths(options), :force_polling => options['force_polling'] ) do |modified, added, removed| t = Time.now.strftime("%Y-%m-%d %H:%M:%S") diff --git a/test/test_command.rb b/test/test_command.rb index ef5b04b0..23f23379 100644 --- a/test/test_command.rb +++ b/test/test_command.rb @@ -1,38 +1,35 @@ require 'helper' class TestCommand < Test::Unit::TestCase - context "when calling .globs" do - context "when non-default dest & source dirs" do - setup do - @source = source_dir - @dest = dest_dir - directory_with_contents(@dest) - @globs = Command.globs(@source, @dest) - end - should "return an array without the destination dir" do - assert @globs.is_a?(Array) - assert !@globs.include?(@dest) - end - teardown do - clear_dest - end - end - context "when using default dest dir" do - setup do - @source = test_dir - @dest = test_dir('_site') - directory_with_contents(@dest) - @globs = Command.globs(@source, @dest) - end - should "return an array without the destination dir" do - assert @globs.is_a?(Array) - assert !@globs.include?(@dest) - @globs.each do |glob| - assert !glob.include?(File.basename(@dest)) + context "when calling .ignore_paths" do + context "when source is absolute" do + setup { @source = source_dir } + should "return an array with regex for destination" do + absolute = source_dir('dest') + relative = Pathname.new(source_dir('dest')).relative_path_from(Pathname.new('.').expand_path).to_s + [absolute, relative].each do |dest| + config = build_configs("source" => @source, "destination" => dest) + assert Command.ignore_paths(config).include?(/dest/), "failed with destination: #{dest}" end end - teardown do - FileUtils.rm_r(@dest) + end + context "when source is relative" do + setup { @source = Pathname.new(source_dir).relative_path_from(Pathname.new('.').expand_path).to_s } + should "return an array with regex for destination" do + absolute = source_dir('dest') + relative = Pathname.new(source_dir('dest')).relative_path_from(Pathname.new('.').expand_path).to_s + [absolute, relative].each do |dest| + config = build_configs("source" => @source, "destination" => dest) + assert Command.ignore_paths(config).include?(/dest/), "failed with destination: #{dest}" + end + end + end + context "multiple config files" do + should "return an array with regex for config files" do + config = build_configs("config"=> ["_config.yaml", "_config2.yml"]) + ignore_paths = Command.ignore_paths(config) + assert ignore_paths.include?(/_config\.yaml/), 'did not include _config.yaml' + assert ignore_paths.include?(/_config2\.yml/), 'did not include _config2.yml' end end end