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:
parent
ace9911001
commit
f91954be76
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue