diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index c4143424..2e996308 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -93,24 +93,25 @@ module Jekyll "url" => File.join(@dir, self.url), "content" => self.content }) end + + # Obtain destination path. + # +dest+ is the String path to the destination dir + # + # Returns destination file path. + def destination(dest) + # The url needs to be unescaped in order to preserve the correct filename + path = File.join(dest, @dir, CGI.unescape(self.url)) + path = File.join(path, "index.html") if self.url =~ /\/$/ + path + end # Write the generated page file to the destination directory. - # +dest_prefix+ is the String path to the destination dir - # +dest_suffix+ is a suffix path to the destination dir + # +dest+ is the String path to the destination dir # # Returns nothing - def write(dest_prefix, dest_suffix = nil) - dest = File.join(dest_prefix, @dir) - dest = File.join(dest, dest_suffix) if dest_suffix - FileUtils.mkdir_p(dest) - - # The url needs to be unescaped in order to preserve the correct filename - path = File.join(dest, CGI.unescape(self.url)) - if self.url =~ /\/$/ - FileUtils.mkdir_p(path) - path = File.join(path, "index.html") - end - + def write(dest) + path = destination(dest) + FileUtils.mkdir_p(File.dirname(path)) File.open(path, 'w') do |f| f.write(self.output) end diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index b1a2a63d..7747eff4 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -177,22 +177,25 @@ module Jekyll do_layout(payload, layouts) end + + # Obtain destination path. + # +dest+ is the String path to the destination dir + # + # Returns destination file path. + def destination(dest) + # The url needs to be unescaped in order to preserve the correct filename + path = File.join(dest, CGI.unescape(self.url)) + path = File.join(path, "index.html") if template[/\.html$/].nil? + path + end # Write the generated post file to the destination directory. # +dest+ is the String path to the destination dir # # Returns nothing def write(dest) - FileUtils.mkdir_p(File.join(dest, dir)) - - # The url needs to be unescaped in order to preserve the correct filename - path = File.join(dest, CGI.unescape(self.url)) - - if template[/\.html$/].nil? - FileUtils.mkdir_p(path) - path = File.join(path, "index.html") - end - + path = destination(dest) + FileUtils.mkdir_p(File.dirname(path)) File.open(path, 'w') do |f| f.write(self.output) end diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 331b6c07..55b5c9d4 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -79,6 +79,7 @@ module Jekyll self.read self.generate self.render + self.cleanup self.write end @@ -151,6 +152,36 @@ module Jekyll rescue Errno::ENOENT => e # ignore missing layout dir end + + # Remove orphaned files and empty directories in destination + # + # Returns nothing + def cleanup + # all files and directories in destination, including hidden ones + dest_files = [] + Dir.glob(File.join(self.dest, "**", "*"), File::FNM_DOTMATCH) do |file| + dest_files << file unless file =~ /\/\.{1,2}$/ + end + + # files to be written + files = [] + self.posts.each do |post| + files << post.destination(self.dest) + end + self.pages.each do |page| + files << page.destination(self.dest) + end + self.static_files.each do |sf| + files << sf.destination(self.dest) + end + + # adding files' parent directories + files.each { |file| files << File.dirname(file) unless files.include? File.dirname(file) } + + obsolete_files = dest_files - files + + FileUtils.rm_rf(obsolete_files) + end # Write static files, pages and posts # diff --git a/lib/jekyll/static_file.rb b/lib/jekyll/static_file.rb index 01f8ee62..5509db75 100644 --- a/lib/jekyll/static_file.rb +++ b/lib/jekyll/static_file.rb @@ -52,12 +52,11 @@ module Jekyll # Returns false if the file was not modified since last time (no-op). def write(dest) dest_path = destination(dest) - dest_dir = File.join(dest, @dir) return false if File.exist? dest_path and !modified? @@mtimes[path] = mtime - FileUtils.mkdir_p(dest_dir) + FileUtils.mkdir_p(File.dirname(dest_path)) FileUtils.cp(path, dest_path) true diff --git a/test/test_site.rb b/test/test_site.rb index f18791de..d8d1057e 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -132,6 +132,39 @@ class TestSite < Test::Unit::TestCase assert_equal includes, @site.filter_entries(excludes + includes) end + context 'with orphaned files in destination' do + setup do + clear_dest + @site.process + # generate some orphaned files: + # hidden file + File.open(dest_dir('.htpasswd'), 'w') + # single file + File.open(dest_dir('obsolete.html'), 'w') + # single file in sub directory + FileUtils.mkdir(dest_dir('qux')) + File.open(dest_dir('qux/obsolete.html'), 'w') + # empty directory + FileUtils.mkdir(dest_dir('quux')) + end + + teardown do + FileUtils.rm_f(dest_dir('.htpasswd')) + FileUtils.rm_f(dest_dir('obsolete.html')) + FileUtils.rm_rf(dest_dir('qux')) + FileUtils.rm_f(dest_dir('quux')) + end + + should 'remove orphaned files in destination' do + @site.process + assert !File.exist?(dest_dir('.htpasswd')) + assert !File.exist?(dest_dir('obsolete.html')) + assert !File.exist?(dest_dir('qux')) + assert !File.exist?(dest_dir('quux')) + end + + end + context 'with an invalid markdown processor in the configuration' do should 'not throw an error at initialization time' do bad_processor = 'not a processor name'