Class: Nanoc3::DependencyTracker

### Home Classes Methods

### In Files

- lib/nanoc3/base/dependency_tracker.rb

### Parent

Object

### Methods

- ::new
- #direct_predecessors_of
- #direct_successors_of
- #forget_dependencies_for
- #load_graph
- #mark_outdated_items
- #predecessors_of
- #print_graph
- #propagate_outdatedness
- #record_dependency
- #start
- #stop
- #store_graph
- #successors_of

### Files

- ChangeLog
- LICENSE

### Class/Module Index

Quicksearch

- Nanoc3
- Nanoc3::ArrayExtensions
- Nanoc3::CLI
- Nanoc3::CLI::Base
- Nanoc3::CLI::Commands
- Nanoc3::CLI::Commands::Autocompile
- Nanoc3::CLI::Commands::Compile
- Nanoc3::CLI::Commands::CreateItem
- Nanoc3::CLI::Commands::CreateLayout
- Nanoc3::CLI::Commands::CreateSite
- Nanoc3::CLI::Commands::Debug
- Nanoc3::CLI::Commands::Help
- Nanoc3::CLI::Commands::Info
- Nanoc3::CLI::Commands::Update
- Nanoc3::CLI::Commands::View
- Nanoc3::CLI::Logger
- Nanoc3::CodeSnippet
- Nanoc3::Compiler
- Nanoc3::CompilerDSL
- Nanoc3::Context
- Nanoc3::DataSource
- Nanoc3::DataSources
- Nanoc3::DataSources::Delicious
- Nanoc3::DataSources::Filesystem
- Nanoc3::DataSources::FilesystemCombined
- Nanoc3::DataSources::FilesystemCompact
- Nanoc3::DataSources::FilesystemUnified
- Nanoc3::DataSources::FilesystemVerbose
- Nanoc3::DataSources::LastFM
- Nanoc3::DataSources::Twitter
- Nanoc3::DependencyTracker
- Nanoc3::DirectedGraph
- Nanoc3::Errors
- Nanoc3::Errors::CannotDetermineFilter
- Nanoc3::Errors::CannotLayoutBinaryItem
- Nanoc3::Errors::CannotUseBinaryFilter
- Nanoc3::Errors::CannotUseTextualFilter
- Nanoc3::Errors::DataNotYetAvailable
- Nanoc3::Errors::Generic
- Nanoc3::Errors::NoMatchingCompilationRuleFound
- Nanoc3::Errors::NoMatchingRoutingRuleFound
- Nanoc3::Errors::NoRulesFileFound
- Nanoc3::Errors::RecursiveCompilation
- Nanoc3::Errors::UnknownDataSource
- Nanoc3::Errors::UnknownFilter
- Nanoc3::Errors::UnknownLayout
- Nanoc3::Errors::UnmetDependency
- Nanoc3::Extra
- Nanoc3::Extra::AutoCompiler
- Nanoc3::Extra::CHiCk
- Nanoc3::Extra::CHiCk::CacheController
- Nanoc3::Extra::CHiCk::Client
- Nanoc3::Extra::CHiCk::RackClient
- Nanoc3::Extra::Context
- Nanoc3::Extra::Deployers
- Nanoc3::Extra::Deployers::Rsync
- Nanoc3::Extra::FileProxy
- Nanoc3::Extra::TimeExtensions
- Nanoc3::Extra::VCS
- Nanoc3::Extra::VCSes
- Nanoc3::Extra::VCSes::Bazaar
- Nanoc3::Extra::VCSes::Dummy
- Nanoc3::Extra::VCSes::Git
- Nanoc3::Extra::VCSes::Mercurial
- Nanoc3::Extra::VCSes::Subversion
- Nanoc3::Extra::Validators
- Nanoc3::Extra::Validators::Links
- Nanoc3::Extra::Validators::Links::EachPairEnumerator
- Nanoc3::Extra::Validators::W3C
- Nanoc3::Filter
- Nanoc3::Filters
- Nanoc3::Filters::BlueCloth
- Nanoc3::Filters::CodeRay
- Nanoc3::Filters::ColorizeSyntax
- Nanoc3::Filters::ERB
- Nanoc3::Filters::Erubis
- Nanoc3::Filters::Haml
- Nanoc3::Filters::Kramdown
- Nanoc3::Filters::Less
- Nanoc3::Filters::Markaby
- Nanoc3::Filters::Maruku
- Nanoc3::Filters::RDiscount
- Nanoc3::Filters::RDoc
- Nanoc3::Filters::Rainpress
- Nanoc3::Filters::RedCloth
- Nanoc3::Filters::RelativizePaths
- Nanoc3::Filters::RubyPants
- Nanoc3::Filters::Sass
- Nanoc3::HashExtensions
- Nanoc3::Helpers
- Nanoc3::Helpers::Blogging
- Nanoc3::Helpers::Breadcrumbs
- Nanoc3::Helpers::Capturing
- Nanoc3::Helpers::Filtering
- Nanoc3::Helpers::HTMLEscape
- Nanoc3::Helpers::LinkTo
- Nanoc3::Helpers::Rendering
- Nanoc3::Helpers::Tagging
- Nanoc3::Helpers::Text
- Nanoc3::Helpers::XMLSitemap
- Nanoc3::Item
- Nanoc3::ItemRep
- Nanoc3::Layout
- Nanoc3::NotificationCenter
- Nanoc3::PluginRegistry
- Nanoc3::PluginRegistry::PluginMethods
- Nanoc3::Rule
- Nanoc3::RuleContext
- Nanoc3::Site
- Nanoc3::StringExtensions
- Nanoc3::Tasks
- Nanoc3::Tasks::Clean
- Array
- Enumerable
- Hash
- Object
- OrderedHash
- String
- Time

No matching classes.

# Nanoc3::DependencyTracker

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.

### Constants

STORE_VERSION

  The version of the file format used to store dependencies.

### Attributes

filename[RW]

@return [String] The name of the file in which dependency information is stored

items[R]

@return [Array<Nanoc3::Item>] The list of items that is being tracked by the dependency tracker

### Public Class Methods

new(items) click to toggle source

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

### Public Instance Methods

direct_predecessors_of(item) click to toggle source

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

direct_successors_of(item) click to toggle source

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

forget_dependencies_for(item) click to toggle source

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

load_graph() click to toggle source

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

mark_outdated_items() click to toggle source

@deprecated Use {propagate_outdatedness} instead.

    # File lib/nanoc3/base/dependency_tracker.rb, line 263
    def mark_outdated_items
      propagate_outdatedness
    end

predecessors_of(item) click to toggle source

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

print_graph() click to toggle source

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

propagate_outdatedness() click to toggle source

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

record_dependency(src, dst) click to toggle source

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

start() click to toggle source

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() click to toggle source

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

store_graph() click to toggle source

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

successors_of(item) click to toggle source

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

[Validate]

Generated with the Darkfish Rdoc Generator 2.