lib/nanoc3/base/item_rep.rb in nanoc3-3.1.0b2 vs lib/nanoc3/base/item_rep.rb in nanoc3-3.1.0rc1
- old
+ new
@@ -18,10 +18,24 @@
# The compilation-related events have one parameters (the item
# representation); the filtering-related events have two (the item
# representation, and a symbol containing the filter class name).
class ItemRep
+ # The descriptive strings for each outdatedness reason. This hash is used
+ # by the {#outdatedness_reason} method.
+ OUTDATEDNESS_REASON_DESCRIPTIONS = {
+ :no_mtime => 'No file modification time is available.',
+ :forced => 'All pages are recompiled because of a `--force` flag given to the compilation command.',
+ :no_raw_path => 'The routing rules do not specify a path where this item should be written to, i.e. the item representation will never be written to the output directory.',
+ :not_written => 'This item representation has not yet been written to the output directory (but it does have a path).',
+ :source_modified => 'The source file of this item has been modified since the last time this item representation was compiled.',
+ :layouts_outdated => 'The source of one or more layouts has been modified since the last time this item representation was compiled.',
+ :code_outdated => 'The code snippets in the `lib/` directory have been modified since the last time this item representation was compiled.',
+ :config_outdated => 'The site configuration has been modified since the last time this item representation was compiled.',
+ :rules_outdated => 'The rules file has been modified since the last time this item representation was compiled.',
+ }
+
# @return [Nanoc3::Item] The item to which this rep belongs
attr_reader :item
# @return [Symbol] The representation's unique name
attr_reader :name
@@ -103,50 +117,78 @@
@created = false
@written = false
@force_outdated = false
end
- # @return [Boolean] true if this item rep's output file is outdated and
- # must be regenerated, false otherwise
- def outdated?
- # Outdated if we don't know
- return true if @item.mtime.nil?
+ # Calculates the reason why this item representation is outdated. The
+ # output will be a hash with a `:type` key, containing the reason why the
+ # item is outdated in the form of a symbol, and a `:description` key,
+ # containing a descriptive string that can be printed if necessary.
+ #
+ # For documentation on the types that this method can return, check the
+ # {OUTDATEDNESS_REASON_DESCRIPTIONS} hash in this class.
+ #
+ # @return [Hash, nil] A hash containing the reason why this item rep is
+ # outdated, both in the form of a symbol and as a descriptive string, or
+ # nil if the item representation is not outdated.
+ def outdatedness_reason
+ # Get reason symbol
+ reason = lambda do
+ # Outdated if we don't know
+ return :no_mtime if @item.mtime.nil?
- # Outdated if the dependency tracker says so
- return true if @force_outdated
+ # Outdated if the dependency tracker says so
+ return :forced if @force_outdated
- # Outdated if compiled file doesn't exist
- return true if self.raw_path.nil?
- return true if !File.file?(self.raw_path)
+ # Outdated if compiled file doesn't exist (yet)
+ return :no_raw_path if self.raw_path.nil?
+ return :not_written if !File.file?(self.raw_path)
- # Get compiled mtime
- compiled_mtime = File.stat(self.raw_path).mtime
+ # Get compiled mtime
+ compiled_mtime = File.stat(self.raw_path).mtime
- # Outdated if file too old
- return true if @item.mtime > compiled_mtime
+ # Outdated if file too old
+ return :source_modified if @item.mtime > compiled_mtime
- # Outdated if layouts outdated
- return true if @item.site.layouts.any? do |l|
- l.mtime.nil? || l.mtime > compiled_mtime
- end
+ # Outdated if layouts outdated
+ return :layouts_outdated if @item.site.layouts.any? do |l|
+ l.mtime.nil? || l.mtime > compiled_mtime
+ end
- # Outdated if code outdated
- return true if @item.site.code_snippets.any? do |cs|
- cs.mtime.nil? || cs.mtime > compiled_mtime
- end
+ # Outdated if code outdated
+ return :code_outdated if @item.site.code_snippets.any? do |cs|
+ cs.mtime.nil? || cs.mtime > compiled_mtime
+ end
- # Outdated if config outdated
- return true if @item.site.config_mtime.nil?
- return true if @item.site.config_mtime > compiled_mtime
+ # Outdated if config outdated
+ return :config_outdated if @item.site.config_mtime.nil?
+ return :config_outdated if @item.site.config_mtime > compiled_mtime
- # Outdated if rules outdated
- return true if @item.site.rules_mtime.nil?
- return true if @item.site.rules_mtime > compiled_mtime
+ # Outdated if rules outdated
+ return :rules_outdated if @item.site.rules_mtime.nil?
+ return :rules_outdated if @item.site.rules_mtime > compiled_mtime
- return false
+ return nil
+ end[]
+
+ # Build reason symbol and description
+ if reason.nil?
+ nil
+ else
+ {
+ :type => reason,
+ :description => OUTDATEDNESS_REASON_DESCRIPTIONS[reason]
+ }
+ end
end
+ # @return [Boolean] true if this item rep's output file is outdated and
+ # must be regenerated, false otherwise
+ def outdated?
+ !outdatedness_reason.nil?
+ end
+
# @return [Hash] The assignments that should be available when compiling
# the content.
def assigns
if self.binary?
content_or_filename_assigns = { :filename => @filenames[:last] }
@@ -352,11 +394,11 @@
#
# @return [String, nil] The difference between the old and new compiled
# content in `diff(1)` format, or nil if there is no previous compiled
# content
def diff
- # TODO allow binary diffs
+ return nil if !@item.site.config[:enable_output_diff]
if self.binary?
nil
else
@diff_thread.join if @diff_thread
@@ -407,13 +449,9 @@
end
end
end
def diff_strings(a, b)
- # TODO Rewrite this string-diffing method in pure Ruby. It should not
- # use the "diff" executable, because this will most likely not work on
- # operating systems without it, such as Windows.
-
require 'tempfile'
require 'open3'
# Create files
Tempfile.open('old') do |old_file|