Class: Nanoc3::DependencyTracker
- Inherits:
-
Object
- Object
- Nanoc3::DependencyTracker
- Defined in:
- lib/nanoc3/base/dependency_tracker.rb
Overview
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 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.
Constant Summary
- STORE_VERSION =
The version of the file format used to store dependencies.
2
Instance Attribute Summary (collapse)
-
- (String) filename
stored.
-
- (Array<Nanoc3::Item>) items
readonly
by the dependency tracker.
Instance Method Summary (collapse)
-
- (Array<Nanoc3::Item>) direct_predecessors_of(item)
Returns the direct dependencies for
item. -
- (Array<Nanoc3::Item>) direct_successors_of(item)
Returns the direct inverse dependencies for
item. -
- (void) forget_dependencies_for(item)
Empties the list of dependencies for the given item.
-
- (DependencyTracker) initialize(items)
constructor
Creates a new dependency tracker for the given items.
-
- (void) load_graph
Loads the dependency graph from the file specified by the #filename attribute.
-
- (Object) mark_outdated_items
Deprecated
Deprecated.
Use #propagate_outdatedness instead.
-
- (Array<Nanoc3::Item>) predecessors_of(item)
Returns all dependencies (direct and indirect) for
item. -
- (void) print_graph
Prints the dependency graph in human-readable form.
-
- (void) propagate_outdatedness
Traverses the dependency graph and marks all items that (directly or indirectly) depend on an outdated item as outdated.
-
- (void) record_dependency(src, dst)
Records a dependency from
srctodstin the dependency graph. -
- (void) start
Starts listening for dependency messages (
:visit_startedand:visit_ended) and start recording dependencies. -
- (void) stop
Stop listening for dependency messages and stop recording dependencies.
-
- (void) store_graph
Stores the dependency graph into the file specified by the #filename attribute.
-
- (Array<Nanoc3::Item>) successors_of(item)
Returns all inverse dependencies (direct and indirect) for
item.
Constructor Details
- (DependencyTracker) initialize(items)
Creates a new dependency tracker for the given items.
should be managed
41 42 43 44 45 46 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 41 def initialize(items) @items = items @filename = 'tmp/dependencies' @graph = Nanoc3::DirectedGraph.new([ nil ] + @items) @previous_items = [] end |
Instance Attribute Details
- (String) filename
stored
28 29 30 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 28 def filename @filename end |
- (Array<Nanoc3::Item>) items (readonly)
by the dependency tracker
32 33 34 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 32 def items @items end |
Instance Method Details
- (Array<Nanoc3::Item>) direct_predecessors_of(item)
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).
predecessors
95 96 97 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 95 def direct_predecessors_of(item) @graph.direct_predecessors_of(item).compact end |
- (Array<Nanoc3::Item>) direct_successors_of(item)
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).
successors
123 124 125 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 123 def direct_successors_of(item) @graph.direct_successors_of(item).compact end |
- (void) forget_dependencies_for(item)
This method returns an undefined value.
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.
243 244 245 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 243 def forget_dependencies_for(item) @graph.delete_edges_to(item) end |
- (void) load_graph
This method returns an undefined value.
Loads the dependency graph from the file specified by the #filename attribute. This method will overwrite an existing dependency graph.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 174 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 |
- (Object) mark_outdated_items
Use #propagate_outdatedness instead.
264 265 266 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 264 def mark_outdated_items propagate_outdatedness end |
- (Array<Nanoc3::Item>) predecessors_of(item)
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.
indirect predecessors
108 109 110 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 108 def predecessors_of(item) @graph.predecessors_of(item).compact end |
- (void) print_graph
This method returns an undefined value.
Prints the dependency graph in human-readable form.
250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 250 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 |
- (void) propagate_outdatedness
This method returns an undefined value.
Traverses the dependency graph and marks all items that (directly or indirectly) depend on an outdated item as outdated.
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 205 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 |
- (void) record_dependency(src, dst)
This method returns an undefined value.
Records a dependency from src to dst in the dependency graph. When
dst is oudated, src will also become outdated.
that will become outdated if dst is outdated
item that will cause the source to become outdated if the destination is outdated
151 152 153 154 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 151 def record_dependency(src, dst) # Warning! dst and src are *reversed* here! @graph.add_edge(dst, src) unless src == dst end |
- (void) start
This method returns an undefined value.
Starts listening for dependency messages (:visit_started and
:visit_ended) and start recording dependencies.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 52 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 |
- (void) stop
This method returns an undefined value.
Stop listening for dependency messages and stop recording dependencies.
78 79 80 81 82 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 78 def stop # Unregister Nanoc3::NotificationCenter.remove(:visit_started, self) Nanoc3::NotificationCenter.remove(:visit_ended, self) end |
- (void) store_graph
This method returns an undefined value.
Stores the dependency graph into the file specified by the #filename attribute.
160 161 162 163 164 165 166 167 168 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 160 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 |
- (Array<Nanoc3::Item>) successors_of(item)
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.
indirect successors
136 137 138 |
# File 'lib/nanoc3/base/dependency_tracker.rb', line 136 def successors_of(item) @graph.successors_of(item).compact end |