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.



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

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


160
161
162
163
164
# File 'lib/sproutcore/models/manifest.rb', line 160

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


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
239
240
241
242
243
244
# File 'lib/sproutcore/models/manifest.rb', line 200

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)
  
  # generate a unique cache path from the staging page.  just sub the 
  # staging root for the cache root
  opts.cache_path ||= unique_cache_path(entry.cache_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

#built?Boolean

Returns:

  • (Boolean)


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

def built?; @is_built; 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


274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/sproutcore/models/manifest.rb', line 274

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().



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
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/sproutcore/models/manifest.rb', line 296

def find_entry(fragment, opts = {}, seen=nil)
  
  entry_extname = entry_rootname = ret = target_name = nil
  
  # optionally you can specify an explicit target name
  split_index = fragment.index(':') # find first index
  unless split_index.nil?
    target_name = '/' + fragment[0..(split_index-1)] if split_index>0
    fragment    = fragment[(split_index+1)..-1] # remove colon
  end
  
  # find the current manifest
  if target_name
    cur_target = self.target.target_for(target_name) || self.target
    cur_manifest = cur_target.manifest_for(self.variation).build!
  else
    cur_manifest = self
  end
  
  extname = File.extname(fragment)
  rootname = fragment.sub(/#{extname}$/, '')

  # look on our own target only if target is named
  ret = cur_manifest.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 << cur_manifest.target
    cur_manifest.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)


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

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)


99
100
101
102
103
# File 'lib/sproutcore/models/manifest.rb', line 99

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



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

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_cache_path(path) ⇒ Object

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



360
361
362
363
364
365
366
# File 'lib/sproutcore/models/manifest.rb', line 360

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

#unique_staging_path(path) ⇒ Object

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



350
351
352
353
354
355
356
# File 'lib/sproutcore/models/manifest.rb', line 350

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