| require "set" |
| |
| module Jekyll |
| # Handles the cleanup of a site's destination before it is built. |
| class Cleaner |
| HIDDEN_FILE_REGEX = %r!\/\.{1,2}$! |
| attr_reader :site |
| |
| def initialize(site) |
| @site = site |
| end |
| |
| # Cleans up the site's destination directory |
| def cleanup! |
| FileUtils.rm_rf(obsolete_files) |
| FileUtils.rm_rf(metadata_file) unless @site.incremental? |
| end |
| |
| private |
| |
| # Private: The list of files and directories to be deleted during cleanup process |
| # |
| # Returns an Array of the file and directory paths |
| def obsolete_files |
| (existing_files - new_files - new_dirs + replaced_files).to_a |
| end |
| |
| # Private: The metadata file storing dependency tree and build history |
| # |
| # Returns an Array with the metdata file as the only item |
| def metadata_file |
| [site.regenerator.metadata_file] |
| end |
| |
| # Private: The list of existing files, apart from those included in |
| # keep_files and hidden files. |
| # |
| # Returns a Set with the file paths |
| def existing_files |
| files = Set.new |
| regex = keep_file_regex |
| dirs = keep_dirs |
| |
| Utils.safe_glob(site.in_dest_dir, ["**", "*"], File::FNM_DOTMATCH).each do |file| |
| next if file =~ HIDDEN_FILE_REGEX || file =~ regex || dirs.include?(file) |
| files << file |
| end |
| |
| files |
| end |
| |
| # Private: The list of files to be created when 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 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| 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 |
| # |
| # Returns a Set with the file paths |
| def replaced_files |
| 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(site.in_dest_dir(file)) }.flatten.to_set |
| end |
| |
| # Private: Creates a regular expression from the config's keep_files array |
| # |
| # Examples |
| # ['.git','.svn'] with site.dest "/myblog/_site" creates |
| # the following regex: /\A\/myblog\/_site\/(\.git|\/.svn)/ |
| # |
| # Returns the regular expression |
| def keep_file_regex |
| %r!\A#{Regexp.quote(site.dest)}\/(#{Regexp.union(site.keep_files).source})! |
| end |
| end |
| end |