diff --git a/lib/jekyll/cleaner.rb b/lib/jekyll/cleaner.rb index 583fc844..0aa3cdfd 100644 --- a/lib/jekyll/cleaner.rb +++ b/lib/jekyll/cleaner.rb @@ -30,7 +30,7 @@ module Jekyll def existing_files files = Set.new Dir.glob(File.join(site.dest, "**", "*"), File::FNM_DOTMATCH) do |file| - files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex + files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex || keep_dirs.include?(file) end files end @@ -49,7 +49,19 @@ module Jekyll # # Returns a Set with the directory paths def new_dirs - new_files.map { |file| File.dirname(file) }.to_set + new_files.map { |file| parent_dirs(file) }.flatten.to_set + end + + # Private: The list of parent directories of a given file + # + # Returns an Array with the directory paths + def parent_dirs(file) + parent_dir = File.dirname(file) + if parent_dir == site.dest + [] + else + [parent_dir] + parent_dirs(parent_dir) + end end # Private: The list of existing files that will be replaced by a directory during build @@ -59,6 +71,14 @@ module Jekyll new_dirs.select { |dir| File.file?(dir) }.to_set end + # Private: The list of directories that need to be kept because they are parent directories + # of files specified in keep_files + # + # Returns a Set with the directory paths + def keep_dirs + site.keep_files.map{|file| parent_dirs(File.join(site.dest, file))}.flatten.to_set + end + # Private: Creates a regular expression from the config's keep_files array # # Examples diff --git a/test/test_cleaner.rb b/test/test_cleaner.rb new file mode 100644 index 00000000..e9bcc0f5 --- /dev/null +++ b/test/test_cleaner.rb @@ -0,0 +1,77 @@ +require 'helper' + +class TestCleaner < Test::Unit::TestCase + context "directory in keep_files" do + setup do + clear_dest + stub(Jekyll).configuration do + Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir}) + end + + FileUtils.mkdir_p(dest_dir('to_keep/child_dir')) + FileUtils.touch(File.join(dest_dir('to_keep'), 'index.html')) + FileUtils.touch(File.join(dest_dir('to_keep/child_dir'), 'index.html')) + + @site = Site.new(Jekyll.configuration) + @site.keep_files = ['to_keep/child_dir'] + + @cleaner = Site::Cleaner.new(@site) + @cleaner.cleanup! + end + + teardown do + FileUtils.rm_rf(dest_dir('to_keep')) + end + + should "keep the parent directory" do + assert File.exist?(dest_dir('to_keep')) + end + + should "keep the child directory" do + assert File.exist?(dest_dir('to_keep/child_dir')) + end + + should "keep the file in the directory in keep_files" do + assert File.exist?(File.join(dest_dir('to_keep/child_dir'), 'index.html')) + end + + should "delete the file in the directory not in keep_files" do + assert !File.exist?(File.join(dest_dir('to_keep'), 'index.html')) + end + end + + context "directory containing no files and non-empty directories" do + setup do + clear_dest + stub(Jekyll).configuration do + Jekyll::Configuration::DEFAULTS.merge({'source' => source_dir, 'destination' => dest_dir}) + end + + FileUtils.mkdir_p(source_dir('no_files_inside/child_dir')) + FileUtils.touch(File.join(source_dir('no_files_inside/child_dir'), 'index.html')) + + @site = Site.new(Jekyll.configuration) + @site.process + + @cleaner = Site::Cleaner.new(@site) + @cleaner.cleanup! + end + + teardown do + FileUtils.rm_rf(source_dir('no_files_inside')) + FileUtils.rm_rf(dest_dir('no_files_inside')) + end + + should "keep the parent directory" do + assert File.exist?(dest_dir('no_files_inside')) + end + + should "keep the child directory" do + assert File.exist?(dest_dir('no_files_inside/child_dir')) + end + + should "keep the file" do + assert File.exist?(File.join(dest_dir('no_files_inside/child_dir'), 'index.html')) + end + end +end