class SC::ManifestEntry

A manifest entry describes a single item that can be built by the build system. A manifest entry can be assigned any properties you like during the manifest build process.

A ManifestEntry must have at least the following properties to build:

bundle::       owner bundle
build_rule::   name of the task to invoke to build this entry
build_path::   absolute path to place built files
staging_path:: absolute path to place staging files
source_path::  absolute path to source file
source_paths:: arrays of source paths to use for build. alt to single
is_hidden:: if true, entry is not included in build

Constants

BUILD_DIRECTIVES_REGEX

Attributes

manifest[RW]

The owner manifest

Public Class Methods

new(manifest, opts={}) click to toggle source
Calls superclass method SC::HashStruct::new
# File lib/sproutcore/models/manifest_entry.rb, line 28
def initialize(manifest, opts={})
  @manifest = manifest
  super(opts)
end

Public Instance Methods

build!() click to toggle source

Invokes the entry's build task to build to its build path. If the entry has source entries, they will be staged first.

# File lib/sproutcore/models/manifest_entry.rb, line 258
def build!
  build_to self[:build_path]
end
cacheable_url() click to toggle source

Returns a URL with a possible timestamp token appended to the end of the entry if the target's timestamp_url config is set, or with a randomly assigned domain name prepended if hyper-domaining is turned on. Otherwise returns the URL itself.

# File lib/sproutcore/models/manifest_entry.rb, line 167
def cacheable_url
  ret = self[:url]
  ret = [ret, self.timestamp].join('?') if target.config[:timestamp_urls]
  ret = SC.attach_prefix(ret)
  if target.config[:hyper_domaining]
    ret = [self.hyperdomain_prefix(ret), ret].join('')
  end
  return ret
end
clean!() click to toggle source

Removes the build and staging files for this entry so the next build will rebuild.

Returns

self
# File lib/sproutcore/models/manifest_entry.rb, line 273
def clean!
  FileUtils.rm(self[:build_path]) if File.exist?(self[:build_path])
  FileUtils.rm(self[:staging_path]) if File.exist?(self[:staging_path])
  return self
end
composite!() click to toggle source

Marks the entry as composite. Returns self

# File lib/sproutcore/models/manifest_entry.rb, line 111
def composite!; self[:composite] = true; self; end
composite?() click to toggle source

true if the manifest entry represents a composite resource built from one or more source entries. Composite resources will have their source_entries staged before the entry itself is built to staged.

# File lib/sproutcore/models/manifest_entry.rb, line 108
def composite?; self[:composite]; end
discover_build_directives!() click to toggle source

Scans the source paths for standard build directives and annotates the entry accordingly. You should only call this method on entries representing CSS or JavaScript resources. It will yield undefined results on all other file types.

# File lib/sproutcore/models/manifest_entry.rb, line 229
def discover_build_directives!

  target.begin_attr_changes

  self[:required] = []
  entry = self.transform? ? self[:source_entry] : self
  entry.scan_source(BUILD_DIRECTIVES_REGEX) do |matches|
    # strip off any file ext
    filename = matches[2].ext ''
    case matches[0]
    when 'sc_require'
      self[:required] << filename
    when 'require'
      self[:required] << filename
    when 'sc_resource'
      self[:resource] = filename
    end
  end

  target.end_attr_changes

end
dynamic?() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 124
def dynamic?; self[:dynamic]; end
extension() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 113
def extension
  @extension ||= File.extname(self[:filename])
end
extensionless_filename() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 37
def extensionless_filename
  @extensionless_filename ||= normalized_filename.ext("")
end
hidden?() click to toggle source

true if the current manifest entry should not be included in the build. The entry may still be used as an input for other entries and it may still be referenced directly

# File lib/sproutcore/models/manifest_entry.rb, line 97
def hidden?; self[:hidden] ||= false; end
hide!() click to toggle source

Sets the entry's hidden? property to true

# File lib/sproutcore/models/manifest_entry.rb, line 100
def hide!
  self[:hidden] = true
  self
end
hyperdomain_prefix(url) click to toggle source

If the hyper_domaining config is an array of strings, this will select one of them based on the hash of the URL, and provide an absolute URL to the entry. The hyperdomain includes the protocol. (http://, etc)

# File lib/sproutcore/models/manifest_entry.rb, line 180
def hyperdomain_prefix(url)
  hyperdomains = target.config.hyper_domaining
  index = url.hash % hyperdomains.length

  return "#{hyperdomains[index]}"
end
inline_contents() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 289
def inline_contents
  unless File.exists?(self[:staging_path])

    # stage source entries if needed...
    (self.source_entries || []).each { |e| e.stage! } if composite?

    # get build task and build it
    buildfile = manifest.target.buildfile
    if !buildfile.task_defined?(self.build_task)
      raise "Could not build entry #{self.filename} because build task '#{self.build_task}' is not defined"
    end

    buildfile.invoke 'build:minify:inline_javascript',
      :entry => self,
      :manifest => self.manifest,
      :target => self.manifest.target,
      :config => self.manifest.target.config,
      :project => self.manifest.target.project,
      :src_path => self[:source_path],
      :src_paths => self[:source_paths],
      :dst_path => self[:staging_path]
    end
  File.readlines(self[:staging_path])
end
inspect() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 61
def inspect
  "SC::ManifestEntry(#{self[:filename]}, build_task=>#{self[:build_task]}, entry_type=>#{self[:entry_type]}, is_hidden=>#{self.hidden?})"
end
inspect_build_state() click to toggle source

Diagnostic function. Indicates what will happen if you called build

# File lib/sproutcore/models/manifest_entry.rb, line 280
def inspect_build_state
  inspect_build_to self[:build_path]
end
inspect_staging_state() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 284
def inspect_staging_state
  inspect_build_to self[:staging_path]
end
normalized_filename() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 33
def normalized_filename
  @normalized_filename = self[:filename].to_s.downcase
end
prepare!() click to toggle source

invoked whenever the manifest entry is first created. This will invoke the entry:prepare task if defined.

# File lib/sproutcore/models/manifest_entry.rb, line 43
def prepare!
  if !@is_prepared
    @is_prepared = true
    buildfile = manifest.target.buildfile
    if buildfile.task_defined? 'entry:prepare'
      buildfile.invoke 'entry:prepare',
        :entry => self,
        :manifest => self.manifest,
        :target => self.manifest.target,
        :config => self.manifest.target.config,
        :project => self.manifest.target.project
    end
  end
  return self
end
prepared?() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 59
def prepared?; @is_prepared || false; end
rootname() click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 117
def rootname
  @rootname ||= self[:filename].sub(/#{extension}$/, '')
end
scan_source(regexp) { |result| ... } click to toggle source

Scans the source paths (first staging any source entries) for the passed regex. Your block will be executed with each line that matched. Returns the results of each block

Example

entry.extract_content(/require\((.+)\)/) { |line| $1 }
# File lib/sproutcore/models/manifest_entry.rb, line 196
def scan_source(regexp, &block)
  if entries = self[:source_entries]
    entries.each { |entry| entry.stage! }
  end

  if paths = self[:source_paths]
    paths.each do |path|
      next unless File.exist?(path)

      # fine all directives in the source.  use file cache to make this
      # fast later on.
      begin
        results = target.file_attr('scan_source', path) do
          File.read(path).scan(regexp)
        end
      rescue ArgumentError
        puts path
        raise
      end

      results.each { |result| yield(result) }

    end
  end
end
stage!() click to toggle source

Builds an entry into its staging path. This method can be invoked on any entry whose output is required by another entry to be built.

# File lib/sproutcore/models/manifest_entry.rb, line 264
def stage!
  build_to self[:staging_path]
end
target() click to toggle source

The owner target

# File lib/sproutcore/models/manifest_entry.rb, line 127
def target; @target ||= manifest.target; end
targets() click to toggle source

deferred_modules targets, only applicable to module_info entries

# File lib/sproutcore/models/manifest_entry.rb, line 130
def targets; self[:targets]; end
timestamp() click to toggle source

Returns a timestamp for when this file was last changed. This will reach back to the source entries, finding the latest original entry.

# File lib/sproutcore/models/manifest_entry.rb, line 138
def timestamp
  if dynamic? # MUST check for this first...
    timestamps = targets.map do |t|
      timestamps2 = t.manifest_for(variation).build!.entries.map do |e|
        ts = e.timestamp
        ts.nil? ? 0 : ts
      end
      timestamps2.max
    end
    timestamps.max

  elsif composite?
    self[:source_entries].map { |e| e.timestamp || 0 }.max || Time.now.to_i

  elsif self[:timestamp]
    # for certain entries, such as the Chance entry, we can't use composite entry
    # but still need to have a timestamp to prevent caching. To do this, we allow
    # the entry to specify the timestamp directly; it will calculate it on its own.
    self[:timestamp]

  else
    File.exist?(self[:source_path]) ? File.mtime(self[:source_path]).to_i : 0
  end
end
to_hash(opts={}) click to toggle source
Calls superclass method SC::HashStruct#to_hash
# File lib/sproutcore/models/manifest_entry.rb, line 65
def to_hash(opts={})
  ret = super()
  if ret[:source_entries]
    ret[:source_entries] = ret[:source_entries].map { |e| e.to_hash(opts)}
  end

  if only_keys = opts[:only]
    filtered = {}
    ret.each do |key, value|
      filtered[key] = value if only_keys.include?(key)
    end
    ret = filtered
  end

  if except_keys = opts[:except]
    filtered = {}
    ret.each do |key, value|
      filtered[key] = value unless except_keys.include?(key)
    end
    ret = filtered
  end

  return ret
end
variation() click to toggle source

variation for deferred_modules targets, only applicable to module_info entries

# File lib/sproutcore/models/manifest_entry.rb, line 134
def variation; self[:variation]; end

Private Instance Methods

build_to(dst_path) click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 333
def build_to(dst_path)
  if self[:build_task].nil?
    raise "no build task defined for #{self.filename}"
  end

  # stage source entries if needed...
  (self[:source_entries] || []).each { |e| e.stage! } if composite?

  # get build task and build it
  buildfile = manifest.target.buildfile
  if !buildfile.task_defined?(self[:build_task])
    raise "Could not build entry #{self[:filename]} because build task '#{self[:build_task]}' is not defined"
  end

  buildfile.invoke self[:build_task],
    :entry => self,
    :manifest => self.manifest,
    :target => self.manifest.target,
    :config => self.manifest.target.config,
    :project => self.manifest.target.project,
    :src_path => self[:source_path],
    :src_paths => self[:source_paths],
    :dst_path => dst_path

  return self
end
inspect_build_to(dst_path) click to toggle source
# File lib/sproutcore/models/manifest_entry.rb, line 316
def inspect_build_to(dst_path)
  return "#{filename}: dst #{dst_path} not found" if !File.exist?(dst_path)
  dst_mtime = File.mtime(dst_path).to_i
  self.source_paths.each do |path|
    if path.nil?
      puts "WARN: nil path in #{filename}"
      next
    end

    return "#{filename}: src #{path} not found" if !File.exist?(path)

    src_mtime = File.mtime(path).to_i
    return "#{filename}: src #{path} is newer [#{dst_mtime} < #{src_mtime}]" if dst_mtime < src_mtime
  end
  return "#{filename}: will not build"
end