optimization: write static file to the destination only if source file timestamp differs

Also make sure static files get regenerated when they are missing in destination.

This is useful in --server --auto mode when it reduces disk/cpu load and also plays nice with xrefresh-server (which was my main motivation) -> soft CSS refresh works again!
This commit is contained in:
Antonin Hildebrand 2010-03-18 03:06:14 +01:00
parent ace9911001
commit f91954be76
2 changed files with 110 additions and 4 deletions

View File

@ -1,6 +1,8 @@
module Jekyll module Jekyll
class StaticFile class StaticFile
@@mtimes = Hash.new # the cache of last modification times [path] -> mtime
# Initialize a new StaticFile. # Initialize a new StaticFile.
# +site+ is the Site # +site+ is the Site
# +base+ is the String path to the <source> # +base+ is the String path to the <source>
@ -15,13 +17,59 @@ module Jekyll
@name = name @name = name
end end
# Write the static file to the destination directory. # Obtains source file path.
#
# Returns source file path.
def path
File.join(@base, @dir, @name)
end
# Obtain destination path.
# +dest+ is the String path to the destination dir # +dest+ is the String path to the destination dir
# #
# Returns nothing # Returns destination file path.
def destination(dest)
File.join(dest, @dir, @name)
end
# Obtain mtime of the source path.
#
# Returns last modifiaction time for this file.
def mtime
File.stat(path).mtime.to_i
end
# Is source path modified?
#
# Returns true if modified since last write.
def modified?
@@mtimes[path] != mtime
end
# Write the static file to the destination directory (if modified).
# +dest+ is the String path to the destination dir
#
# Returns false if the file was not modified since last time (no-op).
def write(dest) def write(dest)
FileUtils.mkdir_p(File.join(dest, @dir)) dest_path = destination(dest)
FileUtils.cp(File.join(@base, @dir, @name), File.join(dest, @dir, @name)) dest_dir = File.join(dest, @dir)
return false if File.exist? dest_path and !modified?
@@mtimes[path] = mtime
FileUtils.mkdir_p(dest_dir)
FileUtils.cp(path, dest_path)
true
end
# Reset the mtimes cache (for testing purposes).
#
# Returns nothing.
def self.reset_cache
@@mtimes = Hash.new
nil
end end
end end

View File

@ -34,6 +34,64 @@ class TestSite < Test::Unit::TestCase
assert before_time <= @site.time assert before_time <= @site.time
end end
should "write only modified static files" do
clear_dest
StaticFile.reset_cache
@site.process
some_static_file = @site.static_files[0].path
dest = File.expand_path(@site.static_files[0].destination(@site.dest))
mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
# need to sleep because filesystem timestamps have best resolution in seconds
sleep 1
@site.process
mtime2 = File.stat(dest).mtime.to_i
assert_equal mtime1, mtime2
# simulate file modification by user
FileUtils.touch some_static_file
sleep 1
@site.process
mtime3 = File.stat(dest).mtime.to_i
assert_not_equal mtime2, mtime3 # must be regenerated!
sleep 1
@site.process
mtime4 = File.stat(dest).mtime.to_i
assert_equal mtime3, mtime4 # no modifications, so must be the same
end
should "write static files if not modified but missing in destination" do
clear_dest
StaticFile.reset_cache
@site.process
some_static_file = @site.static_files[0].path
dest = File.expand_path(@site.static_files[0].destination(@site.dest))
mtime1 = File.stat(dest).mtime.to_i # first run must generate dest file
# need to sleep because filesystem timestamps have best resolution in seconds
sleep 1
@site.process
mtime2 = File.stat(dest).mtime.to_i
assert_equal mtime1, mtime2
# simulate destination file deletion
File.unlink dest
sleep 1
@site.process
mtime3 = File.stat(dest).mtime.to_i
assert_not_equal mtime2, mtime3 # must be regenerated and differ!
sleep 1
@site.process
mtime4 = File.stat(dest).mtime.to_i
assert_equal mtime3, mtime4 # no modifications, so must be the same
end
should "read layouts" do should "read layouts" do
@site.read_layouts @site.read_layouts
assert_equal ["default", "simple"].sort, @site.layouts.keys.sort assert_equal ["default", "simple"].sort, @site.layouts.keys.sort