lib/multi_sync/sources/manifest_source.rb
require 'yaml'
require 'json'
require 'multi_sync/source'
require 'multi_sync/resources/local_resource'
module MultiSync
class ManifestSource < Source
def files
files = []
# create a local_resource from each file
# making sure to skip any that do not match the include/exclude patterns
manifest_hash.each { |key, value|
path = source_dir + key
next if !path.fnmatch?(include.to_s) || path.fnmatch?(exclude.to_s || '')
file = path_to_local_resource(path, mtime: value['mtime'], digest: value['digest'], content_length: value['size'])
files << file
}
files.sort
end
private
def manifest_hash
manifest_hash = {}
# ::ActionView::Base has a shortcut to the manifest file
# otherwise lets hunt down that manifest file!
if defined?(::ActionView::Base) && ::ActionView::Base.respond_to?(:assets_manifest)
manifest_hash = ::ActionView::Base.assets_manifest.files
else
manifest_path = Dir.glob(source_dir + 'manifest*.{json,yaml,yml}').max { |f| File.ctime(f) }
manifest_hash = parse_manifest(manifest_path)
end
manifest_hash
end
def parse_manifest(manifest_path)
manifest_hash = {}
manifest_data = File.read(manifest_path)
# manifest files can be YAML or JSON but Sprockets::Manifest isn't backwards compatible with that in mind :(
case File.extname(manifest_path)
when '.json'
manifest_hash = JSON.load(manifest_data)
when '.yml', '.yaml'
manifest_hash = YAML.load(manifest_data)
else
fail ArgumentError, "Unknown manifest type: #{manifest_path}"
end
# different versions of Sprockets have different manifest layouts, lets try and work around this by checking for the presence of "files" and "assets" in the manifest first
# else we know it must be an old manifest file, so its root is "files"
if manifest_hash.key?('files') || manifest_hash.key?('assets')
manifest_hash = manifest_hash['files']
else
# index.* files are special and should be ignored from sync
# something which seems to only happen in older versions of Sprockets
manifest_hash.delete_if { |key, _|
key.include?('/index.')
}
# lets manipulate this older manifest to appear similiar to the newer manifest's "files"
modified_manifest_hash = {}
manifest_hash.each { |key, value|
modified_manifest_hash[value] = {
'logical_path' => key,
'mtime' => nil,
'size' => nil,
'digest' => nil
}
}
manifest_hash = modified_manifest_hash
end
manifest_hash
end
end
end