Skip to content
This repository has been archived by the owner on Oct 22, 2019. It is now read-only.

Commit

Permalink
optimization: write static file to the destination only if source fil…
Browse files Browse the repository at this point in the history
…e 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!
  • Loading branch information
darwin committed Jun 20, 2010
1 parent ace9911 commit f91954b
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 4 deletions.
56 changes: 52 additions & 4 deletions lib/jekyll/static_file.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Jekyll

class StaticFile
@@mtimes = Hash.new # the cache of last modification times [path] -> mtime

# Initialize a new StaticFile.
# +site+ is the Site
# +base+ is the String path to the <source>
Expand All @@ -15,13 +17,59 @@ def initialize(site, base, dir, name)
@name = name
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
#
# 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)
FileUtils.mkdir_p(File.join(dest, @dir))
FileUtils.cp(File.join(@base, @dir, @name), File.join(dest, @dir, @name))
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.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

Expand Down
58 changes: 58 additions & 0 deletions test/test_site.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,64 @@ class TestSite < Test::Unit::TestCase
assert before_time <= @site.time
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
@site.read_layouts
assert_equal ["default", "simple"].sort, @site.layouts.keys.sort
Expand Down

0 comments on commit f91954b

Please sign in to comment.