diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 3f575837..5ff25deb 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -42,6 +42,7 @@ require 'jekyll/filters' require 'jekyll/static_file' require 'jekyll/errors' require 'jekyll/related_posts' +require 'jekyll/cleaner' # extensions require 'jekyll/plugin' diff --git a/lib/jekyll/cleaner.rb b/lib/jekyll/cleaner.rb new file mode 100644 index 00000000..a933b9e2 --- /dev/null +++ b/lib/jekyll/cleaner.rb @@ -0,0 +1,73 @@ +require 'set' + +module Jekyll + class Site + # Handles the cleanup of a site's destination before the site is built. + class Cleaner + def initialize(site) + @site = site + end + + # Cleans up the site's destination directory + def cleanup! + FileUtils.rm_rf(obsolete_files) + end + + private + + # Private: The list of files and directories to be deleted during the cleanup process + # + # Returns an Array with the file and directory paths + def obsolete_files + (existing_files - new_files - new_dirs + replaced_files).to_a + end + + # Private: The list of existing files, except those included in keep_files and hidden files. + # + # Returns a Set with the file paths + 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 + end + files + end + + # Private: The list of files to be created when the site is built. + # + # Returns a Set with the file paths + def new_files + files = Set.new + @site.each_site_file { |item| files << item.destination(@site.dest) } + files + end + + # Private: The list of directories to be created when the site is built. + # These are the parent directories of the files in #new_files. + # + # Returns a Set with the directory paths + def new_dirs + new_files.map { |file| File.dirname(file) }.to_set + end + + # Private: The list of existing files that will be replaced by a directory during build + # + # Returns a Set with the file paths + def replaced_files + new_dirs.select { |dir| File.file?(dir) }.to_set + end + + # Private: creates a regular expression from the config's keep_files array + # + # Examples + # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ + # + # Returns the regular expression + def keep_file_regex + or_list = @site.keep_files.join("|") + pattern = "\/(#{or_list.gsub(".", "\.")})" + Regexp.new pattern + end + end + end +end \ No newline at end of file diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index f7a8c379..7f2cda2e 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -1,5 +1,3 @@ -require 'set' - module Jekyll class Site attr_accessor :config, :layouts, :posts, :pages, :static_files, @@ -228,43 +226,7 @@ module Jekyll # # Returns nothing. def cleanup - # all files and directories in destination, including hidden ones - dest_files = Set.new - Dir.glob(File.join(self.dest, "**", "*"), File::FNM_DOTMATCH) do |file| - if self.keep_files.length > 0 - dest_files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex - else - dest_files << file unless file =~ /\/\.{1,2}$/ - end - end - - # files to be written - files = Set.new - each_site_file { |item| files << item.destination(self.dest) } - - # adding files' parent directories - dirs = Set.new - files.each { |file| dirs << File.dirname(file) } - files.merge(dirs) - - # files that are replaced by dirs should be deleted - files_to_delete = Set.new - dirs.each { |dir| files_to_delete << dir if File.file?(dir) } - - obsolete_files = dest_files - files + files_to_delete - FileUtils.rm_rf(obsolete_files.to_a) - end - - # Private: creates a regular expression from the keep_files array - # - # Examples - # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ - # - # Returns the regular expression - def keep_file_regex - or_list = self.keep_files.join("|") - pattern = "\/(#{or_list.gsub(".", "\.")})" - Regexp.new pattern + site_cleaner.cleanup! end # Write static files, pages, and posts. @@ -422,5 +384,9 @@ module Jekyll limit = self.posts.length < limit_posts ? self.posts.length : limit_posts self.posts = self.posts[-limit, limit] end + + def site_cleaner + @site_cleaner ||= Cleaner.new(self) + end end end