Class: SC::Manifest

Inherits:
HashStruct show all
Defined in:
lib/sproutcore/models/manifest.rb

Overview

A Manifest describes all of the files that should be found inside of a single bundle/language. A Manifest can have global properties assigned to it which will be used by the manifest entries themselves. This is largly defined by the manifest build tasks.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from HashStruct

#[], #[]=, #deep_clone, #has_options?, #merge, #merge!, #method_missing

Constructor Details

#initialize(target, opts) ⇒ Manifest

Returns a new instance of Manifest.



27
28
29
30
31
# File 'lib/sproutcore/models/manifest.rb', line 27

def initialize(target, opts)
  super(opts)
  @target = target 
  @entries = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class SC::HashStruct

Instance Attribute Details

#targetObject (readonly)

Returns the value of attribute target.



19
20
21
# File 'lib/sproutcore/models/manifest.rb', line 19

def target
  @target
end

Instance Method Details

#add_composite(filename, opts = {}) ⇒ Object

Creates a composite entry with the passed filename. Expects you to a source_entries option. This automatically hides the source entries unless you pass the :hide_entries => false option.



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/sproutcore/models/manifest.rb', line 167

def add_composite(filename, opts = {})
  should_hide_entries = opts.delete(:hide_entries)
  should_hide_entries = true if should_hide_entries.nil?
  
  opts[:filename] = filename
  opts[:source_entries] ||= []
  opts[:composite] = true
  @entries << (ret = ManifestEntry.new(self, opts)).prepare!
  
  ret.source_entries.each { |entry| entry.hide! } if should_hide_entries
  return ret 
end

#add_entry(filename, opts = {}) ⇒ Object

Creates a new manifest entry with the passed options. Will setup extra tracking needed by entry.

Params

opts

the options you want to set on the entry

Returns

the new manifest entry



158
159
160
161
162
# File 'lib/sproutcore/models/manifest.rb', line 158

def add_entry(filename, opts = {})
  opts[:filename] = filename
  @entries << (ret = ManifestEntry.new(self, opts)).prepare!
  return ret 
end

#add_transform(entry, opts = {}) ⇒ Object

Creates an entry with will apply a build task to the source entry. Use this method when you need to apply a build task to an entry to convert it into another format or to perform some kind of incremental build.

Params

entry

the entry that should be the source of the transform

Options

You can assign any options you like and they will be copied onto the new entry. The following options, however, have special meaning:

:build_task:: name the new build task you use. otherwise uses copy :ext:: the new file extension. if you don't override, the build_path staging_path and filename will all be adjusted to have this ext. :hide_entry:: the source entry will be hidden unless set to false

Returns

the new ManifestEntry



198
199
200
201
202
203
204
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
234
235
236
237
238
# File 'lib/sproutcore/models/manifest.rb', line 198

def add_transform(entry, opts ={})
  should_hide_entries = opts.delete(:hide_entries) || opts.delete(:hide_entry)
  should_hide_entries = true if should_hide_entries.nil?

  # Clone important properties to new transform...
  opts = HashStruct.new(opts)
  %w(filename build_path url).each do |key|
    opts[key] ||= entry[key]
  end
  
  # generate a unique staging path.  If the original entry has its 
  # staging_path set == to source_root (optimization for build:copy), then
  # first rebase staging path against the staging root.
  if (staging_path = entry.staging_path) == entry.source_path
    staging_path = File.join(self.staging_root, entry.filename) 
  end
  opts.staging_path ||= unique_staging_path(staging_path)
  
  # copy other useful entries
  opts.source_entry   = entry
  opts.source_entries = [entry]
  opts.composite      = true
  opts.transform      = true # make .transform? = true
  
  # Normalize to new extension if provided.  else copy ext from entry...
  if opts.ext
    %w(filename build_path staging_path url).each do |key|
      opts[key] = opts[key].ext(opts.ext)
    end
    opts.ext = opts.ext.to_s
  else
    opts.ext = entry.ext
  end

  # Create new entry and hide old one
  @entries << (ret = ManifestEntry.new(self, opts)).prepare!
  entry.hide! if should_hide_entries
  
  # done!
  return ret 
end

#build!Object

Builds the manifest if it has not been built yet.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/sproutcore/models/manifest.rb', line 76

def build!
  prepare!
  if !@is_built
    @is_built = true
    if target.buildfile.task_defined? 'manifest:build'
      target.buildfile.invoke 'manifest:build',
        :manifest => self,
        :target => self.target,
        :config => self.target.config,
        :project => self.target.project
    end
  end
  return self
end

#entries(opts = {}) ⇒ Object



21
22
23
24
25
# File 'lib/sproutcore/models/manifest.rb', line 21

def entries(opts={})
  include_hidden = opts[:hidden] || false
  return @entries if include_hidden
  @entries.reject { |e| e.hidden? }
end

#entry_for(filename, opts = {}) ⇒ Object

Finds the first visible entry with the specified filename. You may also pass any number of additional options which will be used to further restrict your search. If you pass :hidden => true only hidden entries will be returned. Otherwise, only visible entries will be returned.

You may also include the name of the target you would like to search. The target name should be relative to the target you are requesting from.

Examples

entry = manifest.entry_for('javascript.js')
=> returns local javascript.js entry

entry = manifest.entry_for('sproutcore:javascript.js')
=> returns entry for javascript.js in 'sproutcore' bundle

entry = manifest.entry_for('sproutcore/costello:javascript.js')

Params

filename

the filename to search

Options

:hidden:: if true, include hidden entries

Returns

the manifest entry



268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/sproutcore/models/manifest.rb', line 268

def entry_for(filename, opts = {})
  target_name, filename = filename.split(':')
  if filename.nil?  # no targetname given...
    manifest = self
    filename = target_name
  else
    manifest = target.target_for(target_name).manifest_for(self.variation)
    manifest.build!
  end
  
  manifest.entries(:hidden => opts[:hidden]).find do |entry| 
    (entry.filename == filename) && entry.has_options?(opts)
  end
end

#find_entry(fragment, opts = {}, seen = nil) ⇒ Object

Attempts to find any entry matching the specified static URL fragment. the fragment you pass may contain only a portion of the url, and it may exclude the file extension if you choose. The filter will select the entry with the broadest match possible.

This is the root search method used by static_url().



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/sproutcore/models/manifest.rb', line 290

def find_entry(fragment, opts = {}, seen=nil)
  
  extname = File.extname(fragment)
  rootname = fragment.sub(/#{extname}$/, '')
  entry_extname = entry_rootname = nil

  ret = entries(:hidden => opts[:hidden]).reject do |entry|
    if entry.has_options?(opts)
      entry_extname = File.extname(entry.filename)
      entry_rootname = entry.filename.sub(/#{entry_extname}$/,'')
      ext_match = (extname.nil? || extname.size == 0) || (entry_extname == extname)
    else
      ext_match = false
    end
    !(ext_match && (/#{rootname}$/ =~ entry_rootname))
  end

  ret = ret.first

  # if no match was found, search the same manifests in required targets
  if ret.nil?
    seen = Set.new if seen.nil?
    seen << self.target
    self.target.expand_required_targets.each do |t|
      next if seen.include?(t) # avoid recursion

      manifest = t.manifest_for(self.variation).build!
      ret = manifest.find_entry(fragment, opts, seen)
      break unless ret.nil?
    end
  end
  return ret
end

#inspectObject



33
34
35
36
37
38
# File 'lib/sproutcore/models/manifest.rb', line 33

def inspect
  opts = variation.dup
  opts[:target] = target.target_name
  desc = opts.keys.sort { |a,b| a.to_s <=> b.to_s }.map { |k| [k, opts[k]].join("=") }.join(" ")
  "SC::Manifest(#{desc})"
end

#load(hash) ⇒ Object

Loads a hash into the manifest, replacing whatever contents are already here.

Params

hash

the hash loaded from disk

Returns

Manifest (self)



140
141
142
143
144
145
146
147
# File 'lib/sproutcore/models/manifest.rb', line 140

def load(hash)
  merge!(hash)
  entry_hashes = self.delete(:entries) || []
  @entries = entry_hashes.map do |opts|
    ManifestEntry.new(self, opts)
  end
  return self 
end

#prepare!Object

Invoked just before a manifest is built. If you load a manifest file this method will not be invoked.

Returns

self



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/sproutcore/models/manifest.rb', line 44

def prepare!
  if !@is_prepared
    @is_prepared = true
    target.prepare!
    if target.buildfile.task_defined? 'manifest:prepare'
      target.buildfile.invoke 'manifest:prepare',
        :manifest => self, 
        :target => self.target, 
        :config => self.target.config,
        :project => self.target.project
    end
  end 
  return self
end

#prepared?Boolean

Returns:

  • (Boolean)


59
# File 'lib/sproutcore/models/manifest.rb', line 59

def prepared?; @is_prepared || false; end

#reset_entries!Object

Resets the manifest entries. this is called before a build is performed. This will reset only the entries, none of the other props.

Returns

Manifest (self)



97
98
99
100
101
# File 'lib/sproutcore/models/manifest.rb', line 97

def reset_entries!
  @is_built = false
  @entries = []
  return self
end

#to_hash(opts = {}) ⇒ Object

Returns the manifest as a hash that can be serialized to json or yaml



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/sproutcore/models/manifest.rb', line 104

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

  # Always include entries unless they are explicitly excluded
  ret[:entries] = entries(opts).map { |e| e.to_hash(opts) }
  
  if except_keys = opts[:except]
    filtered = {}
    ret.each do |key, value|
      filtered[key] = value unless except_keys.include?(key)
    end
    ret = filtered
  end

  # always add target name. needed to reload
  ret[:target_name] = target.target_name
  return ret
end

#unique_staging_path(path) ⇒ Object

Finds a unique staging path starting with the root proposed staging path.



326
327
328
329
330
331
332
# File 'lib/sproutcore/models/manifest.rb', line 326

def unique_staging_path(path)
  paths = entries(:hidden => true).map { |e| e.staging_path }
  while paths.include?(path)
    path = path.sub(/(__\$[0-9]+)?(\.\w+)?$/,"__$#{next_staging_uuid}\\2")
  end
  return path
end

#variationObject

Returns the options that select the current variation. The current implementation is hardcoded to return the language, but this may be generalized in the future.

You can use this method to select the same manifest in other targets.

Examples

other_manifest = other_target.manifest_for(my_manifest.variation)


71
72
73
# File 'lib/sproutcore/models/manifest.rb', line 71

def variation
  return { :language => self.language }
end