class JsDuck::Cache

Reads/writes parsed files in cache.

When writing to cache:

When reading from cache:

Additionally a manifest.txt file is saved into the cache directory, the contents of which is a string like the following:

Ruby: 1.9.3, JSDuck: 5.2.0

This file is consulted before all other cache operations. When the version numbers in there don't match with current Ruby and JSDuck versions, the whole cache gets invalidated - all cached files get deleted. This is to avoid problems with the Marshal file format changes between Ruby versions and parsed data structure changes between JSDuck versions.

After all files have been checked into cache, the files that weren't touched get deleted (using the cleanup method). This ensures that the number of files in cache only grows when more files are added to the documentation.

Attributes

previous_entry[R]

The name of the cache file that was previously read or written. When the read call failed to find the file, it will be nil. But it will always be available after the write call.

Public Class Methods

create(opts) click to toggle source

Factory method to produce a cache object. When caching is disabled, returns a NullObject which emulates a cache that's always empty.

# File lib/jsduck/cache.rb, line 43
def self.create(opts)
  # Check also for cache_dir, which will be nil when output_dir is :stdout
  if opts.cache && opts.cache_dir
    Cache.new(opts)
  else
    Util::NullObject.new(
      :read => nil,
      :write => nil,
      :previous_entry => nil,
      :cleanup => nil
      )
  end
end
new(opts) click to toggle source
# File lib/jsduck/cache.rb, line 62
def initialize(opts)
  @cache_dir = opts.cache_dir
  @manifest_file = @cache_dir + "/manifest.txt"
  @previous_entry = nil

  FileUtils.mkdir_p(@cache_dir) unless File.exists?(@cache_dir)

  # Invalidate the whole cache when it was generated with a
  # different Ruby and/or JSDuck version.
  invalidate_all! unless valid_manifest?
end

Public Instance Methods

cleanup(used_cache_entries) click to toggle source

Given listing of used cache files (those that were either read or written during this jsduck run) removes rest of the files from cache directory that were unused.

# File lib/jsduck/cache.rb, line 98
def cleanup(used_cache_entries)
  used = Set.new(used_cache_entries)

  Dir[@cache_dir + "/*.dat"].each do |file|
    FileUtils.rm_rf(file) unless used.include?(file)
  end
end
read(file_name, file_contents) click to toggle source

Given the name and contents of a source file, reads the already parsed data structure from cache. Returns nil when not found.

# File lib/jsduck/cache.rb, line 76
def read(file_name, file_contents)
  fname = cache_file_name(file_name, file_contents)
  if File.exists?(fname)
    @previous_entry = fname
    File.open(fname, "rb") {|file| Marshal::load(file) }
  else
    @previous_entry = nil
    nil
  end
end
write(file_name, file_contents, data) click to toggle source

Writes parse data into cache under a name generated from the name and contents of a source file.

# File lib/jsduck/cache.rb, line 89
def write(file_name, file_contents, data)
  fname = cache_file_name(file_name, file_contents)
  @previous_entry = fname
  File.open(fname, "wb") {|file| Marshal::dump(data, file) }
end

Private Instance Methods

cache_file_name(file_name, file_contents) click to toggle source
# File lib/jsduck/cache.rb, line 108
def cache_file_name(file_name, file_contents)
  @cache_dir + "/" + md5(file_name + file_contents) + ".dat"
end
current_manifest() click to toggle source
# File lib/jsduck/cache.rb, line 131
def current_manifest
  "Ruby: #{RUBY_VERSION}, JSDuck: #{JsDuck::VERSION}\n"
end
invalidate_all!() click to toggle source
# File lib/jsduck/cache.rb, line 121
def invalidate_all!
  FileUtils.rm_rf(@cache_dir)
  FileUtils.mkdir(@cache_dir)
  save_manifest
end
md5(string) click to toggle source
# File lib/jsduck/cache.rb, line 112
def md5(string)
  Digest::MD5.hexdigest(string)
end
save_manifest() click to toggle source
# File lib/jsduck/cache.rb, line 127
def save_manifest
  File.open(@manifest_file, "w") {|f| f.write(current_manifest) }
end
valid_manifest?() click to toggle source
# File lib/jsduck/cache.rb, line 116
def valid_manifest?
  manifest = File.exists?(@manifest_file) ? Util::IO.read(@manifest_file) : ""
  return manifest == current_manifest
end