Responsible for remembering dependencies between items. It is used to speed up compilation by only letting an item be recompiled when it is outdated or any of its dependencies (or dependencies’ dependencies, etc) is outdated.
The dependencies tracked by the dependency tracker are not dependencies based on an item’s content. When one item uses an attribute of another item, then this is also treated as a dependency. While dependencies based on an item’s content (handled in {Nanoc3::Compiler}) cannot be mutually recursive, the more general dependencies in Nanoc3::DependencyTracker can (e.g. item A can use an attribute of item B and vice versa without problems).
The dependency tracker remembers the dependency information between runs. Dependency information is stored in the `tmp/dependencies` file. This file also contains a version number; when a dependencies file with an incompatible version is found, it is ignored.
The version of the file format used to store dependencies.
@return [Array<Nanoc3::Item>] The list of items that is being tracked by the dependency tracker
Creates a new dependency tracker for the given items.
@param [Array<Nanoc3::Item>] item The list of items whose dependencies should be managed
# File lib/nanoc3/base/dependency_tracker.rb, line 40 def initialize(items) @items = items @filename = 'tmp/dependencies' @graph = Nanoc3::DirectedGraph.new([ nil ] + @items) @previous_items = [] end
Returns the direct dependencies for `item`.
The direct dependencies of `item` include the items that, when outdated will cause `item` to be marked as outdated. Indirect dependencies will not be returned (e.g. if A depends on B which depends on C, then the direct dependencies of A do not include C).
@param [Nanoc3::Item] item The item for which to fetch the direct predecessors
@return [Array<Nanoc3::Item>] The direct predecessors of the given item
# File lib/nanoc3/base/dependency_tracker.rb, line 94 def direct_predecessors_of(item) @graph.direct_predecessors_of(item).compact end
Returns the direct inverse dependencies for `item`.
The direct inverse dependencies of `item` include the items that will be marked as outdated when`+item` is outdated. Indirect dependencies will not be returned (e.g. if A depends on B which depends on C, then the direct inverse dependencies of C do not include A).
@param [Nanoc3::Item] item The item for which to fetch the direct successors
@return [Array<Nanoc3::Item>] The direct successors of the given item
# File lib/nanoc3/base/dependency_tracker.rb, line 122 def direct_successors_of(item) @graph.direct_successors_of(item).compact end
Empties the list of dependencies for the given item. This is necessary before recompiling the given item, because otherwise old dependencies will stick around and new dependencies will appear twice. This function removes all incoming edges for the given vertex.
@param [Nanoc3::Item] item The item for which to forget all dependencies
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 242 def forget_dependencies_for(item) @graph.delete_edges_to(item) end
Loads the dependency graph from the file specified by the {filename} attribute. This method will overwrite an existing dependency graph.
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 173 def load_graph # Create new graph @graph = Nanoc3::DirectedGraph.new([ nil ] + @items) # Get store return if !File.file?(self.filename) store = PStore.new(self.filename) # Load dependencies store.transaction do # Verify version return if store[:version] != STORE_VERSION # Load vertices @previous_items = store[:vertices].map do |v| @items.find { |i| i.identifier == v } end # Load edges store[:edges].each do |edge| from_index, to_index = *edge from, to = @previous_items[from_index], @previous_items[to_index] @graph.add_edge(from, to) end end end
@deprecated Use {propagate_outdatedness} instead.
# File lib/nanoc3/base/dependency_tracker.rb, line 263 def mark_outdated_items propagate_outdatedness end
Returns all dependencies (direct and indirect) for `item`.
The dependencies of `item` include the items that, when outdated, will cause `item` to be marked as outdated.
@param [Nanoc3::Item] item The item for which to fetch all direct and indirect predecessors
@return [Array<Nanoc3::Item>] The predecessors of the given item
# File lib/nanoc3/base/dependency_tracker.rb, line 107 def predecessors_of(item) @graph.predecessors_of(item).compact end
Prints the dependency graph in human-readable form.
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 249 def print_graph @items.each do |item| puts "#{item.inspect} depends on:" predecessors = direct_predecessors_of(item) predecessors.each do |pred| puts " #{pred.inspect}" end puts " (nothing!)" if predecessors.empty? puts end end
Traverses the dependency graph and marks all items that (directly or indirectly) depend on an outdated item as outdated.
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 204 def propagate_outdatedness # Unmark everything @items.each { |i| i.outdated_due_to_dependencies = false } # Mark new items as outdated added_items = @items - @previous_items added_items.each { |i| i.outdated_due_to_dependencies = true } # Mark successors of nil as outdated self.successors_of(nil).each do |i| i.outdated_due_to_dependencies = true end # Mark successors of outdated items as outdated require 'set' unprocessed = @items.select { |i| i.outdated? } seen = Set.new(unprocessed) until unprocessed.empty? item = unprocessed.shift self.direct_successors_of(item).each do |successor| next if seen.include?(successor) seen << successor successor.outdated_due_to_dependencies = true unprocessed << successor end end end
Records a dependency from `src` to `dst` in the dependency graph. When `dst` is oudated, `src` will also become outdated.
@param [Nanoc3::Item] src The source of the dependency, i.e. the item that will become outdated if dst is outdated
@param [Nanoc3::Item] dst The destination of the dependency, i.e. the item that will cause the source to become outdated if the destination is outdated
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 150 def record_dependency(src, dst) # Warning! dst and src are *reversed* here! @graph.add_edge(dst, src) unless src == dst end
Starts listening for dependency messages (`:visit_started` and `:visit_ended`) and start recording dependencies.
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 51 def start # Initialize dependency stack. An item will be pushed onto this stack # when it is visited. Therefore, an item on the stack always depends on # all items pushed above it. @stack = [] # Register start of visits Nanoc3::NotificationCenter.on(:visit_started, self) do |item| # Record possible dependency unless @stack.empty? $stderr.puts "*** Recording dependency on #{item.inspect}" if $DEBUG self.record_dependency(@stack[-1], item) end @stack.push(item) end # Register end of visits Nanoc3::NotificationCenter.on(:visit_ended, self) do |item| @stack.pop end end
Stop listening for dependency messages and stop recording dependencies.
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 77 def stop # Unregister Nanoc3::NotificationCenter.remove(:visit_started, self) Nanoc3::NotificationCenter.remove(:visit_ended, self) end
Stores the dependency graph into the file specified by the {filename} attribute.
@return [void]
# File lib/nanoc3/base/dependency_tracker.rb, line 159 def store_graph FileUtils.mkdir_p(File.dirname(self.filename)) store = PStore.new(self.filename) store.transaction do store[:version] = STORE_VERSION store[:vertices] = @graph.vertices.map { |i| i && i.identifier } store[:edges] = @graph.edges end end
Returns all inverse dependencies (direct and indirect) for `item`.
The inverse dependencies of `item` include the items that will be marked as outdated when `item` is outdated.
@param [Nanoc3::Item] item The item for which to fetch all direct and indirect successors
@return [Array<Nanoc3::Item>] The successors of the given item
# File lib/nanoc3/base/dependency_tracker.rb, line 135 def successors_of(item) @graph.successors_of(item).compact end
Generated with the Darkfish Rdoc Generator 2.