class Distillery::Vault
Constants
- ARCHIVES
List of archives extensions
- CHECKSUMS
List of
ROM
checksums- DIR_PRUNING
Directory pruning
- GLOB_PATTERN_REGEX
@!visibility private
- IGNORE_DIRS
List of directories to be ignored
- IGNORE_FILES
List of files to be ignored
Public Class Methods
Potential ROM
from directory. @note file in {IGNORE_FILES}, directory in {IGNORE_DIRS},
directories holding a {DIR_PRUNING} file or starting with a dot are ignored
@param dir [String] path to directory @param depth [Integer,nil] exploration depth
@yieldparam file [String] file being processed @yieldparam dir: [String] directory relative to
# File lib/distillery/vault.rb, line 46 def self.from_dir(dir, depth: nil) Find.find(dir) do |path| basename = File.basename(path) subpath = Pathname(path).relative_path_from(dir).to_s if FileTest.directory?(path) next if path == dir Find.prune if IGNORE_DIRS.include?(basename) Find.prune if basename.start_with?('.') Find.prune if !depth.nil? && subpath.split(File::Separator).size > depth Find.prune if DIR_PRUNING.any? {|f| File.exists?(f) } elsif FileTest.file?(path) next if IGNORE_FILES.include?(basename) yield(subpath, dir: dir) if block_given? end end end
Potential ROM
from glob @note file in {IGNORE_FILES}, directory in {IGNORE_DIRS},
directories holding a {DIR_PRUNING} file or starting with a dot are ignored
@param glob [String] ruby glob @param basedir [:guess,nil] basedir to use when interpreting glob
matching
@yieldparam file [String] file being processed @yieldparam dir: [String] directory relative to
# File lib/distillery/vault.rb, line 77 def self.from_glob(glob, basedir: :guess) if basedir == :guess gentry = glob.split(File::SEPARATOR) idx = gentry.find_index{|entry| entry =~ GLOB_PATTERN_REGEX } gentry = gentry[0,idx] basedir = if gentry.empty? then nil elsif gentry.first.empty? then '/' else File.join(gentry) end end # Build file list (reject ignored files and dirs) lst = Dir[glob].reject {|path| (! FileTest.file?(path)) || IGNORE_FILES.include?(File.basename(path)) || path.split(File::SEPARATOR)[0..-1].any? {|dir| IGNORE_DIRS.include?(dir) || dir.start_with?('.') } } # Build cut list based on directory prunning cutlst = lst.map {|f| File.dirname(f) }.uniq.select {|f| DIR_PRUNING.any? {|p| FileTest.exist?(File.join(f,p)) } } # Apply cut list lst.reject! {|path| cutlst.any? {|cut| path.start_with?("#{cut}#{File::SEPARATOR}") } } # Iterate on list lst.each do |path| subpath = if basedir.nil? then path else Pathname(path).relative_path_from(basedir).to_s end yield(subpath, dir: basedir) if block_given? end end
# File lib/distillery/vault.rb, line 116 def initialize(roms = []) @cksum = Hash[CHECKSUMS.map {|k| [ k, {} ] }] @roms = [] Array(roms).each {|rom| add_rom(rom) } end
Public Instance Methods
Add ROM
from directory. @note file in {IGNORE_FILES}, directory in {IGNORE_DIRS},
directories holding a {DIR_PRUNING} file or starting with a dot are ignored
@param dir [String] path to directory @param depth [Integer,nil] exploration depth @param archives [#include?] archives tester
@yieldparam file [String] file being processed @yieldparam dir [String] directory relative to
@return [self]
# File lib/distillery/vault.rb, line 238 def add_from_dir(dir, depth: nil, archives: ARCHIVES) Vault.from_dir(dir, depth: depth) do | file, dir: | yield(file, dir: dir) if block_given? add_from_file(file, dir, archives: archives) end self end
Add ROM
from file
@param file [String] path to files relative to basedir @param basedir [String,nil] base directory @param archives [#include?] archives tester
@return [self]
# File lib/distillery/vault.rb, line 213 def add_from_file(file, basedir = nil, archives: ARCHIVES) filepath = File.join(*[ basedir, file ].compact) romlist = if ROMArchive.archive?(filepath, archives: archives) then ROMArchive.from_file(filepath).to_a else ROM.from_file(file, basedir) end Array(romlist).each {|rom| add_rom(rom) } end
Add ROM
from glob @note file in {IGNORE_FILES}, directory in {IGNORE_DIRS},
directories holding a {DIR_PRUNING} file or starting with a dot are ignored
@param glob [String] ruby glob @param basedir [:guess,nil] basedir to use when interpreting glob
matching
@param archives [#include?] archives tester
@yieldparam file [String] file being processed @yieldparam dir [String] directory relative to
@return [self]
# File lib/distillery/vault.rb, line 262 def add_from_glob(glob, basedir: :guess, archives: ARCHIVES) Vault.from_dir(glob, basedir: basedir) do | file, dir: | yield(file, dir: dir) if block_given? add_from_file(file, dir, archives: archives) end self end
Add ROM
@param [ROM] rom ROM
to add
@return self
# File lib/distillery/vault.rb, line 181 def add_rom(rom) # Sanity check unless ROM === rom raise ArgumentError, "not a ROM" end # Add it to the list @roms << rom # Keep track of checksums @cksum.each {|type, hlist| hlist.merge!(rom.cksum(type) => rom) {|key, old, new| if Array(old).any? {|r| r.path == new.path} then old else Array(old) + [ new ] end } } # Chainable self end
Return list of matching ROMs.
@param query [Hash{Symbol=>String}] Hash of checksums to match with
@return [Array<ROM>] list of matching ROMs @return [nil] if no match
# File lib/distillery/vault.rb, line 302 def cksummatch(query) CHECKSUMS.each {|type| if (q = query[type]) && (r = @cksum[type][q]) return Array(r) end } return nil end
Dumping of ROM
vault entries
@param compact [Boolean]
@return [self]
@yieldparam group [String] @yieldparam entries [Array<String>]
# File lib/distillery/vault.rb, line 406 def dump(compact: false, &block) self.each.inject({}) {|grp, rom| grp.merge(rom.path.storage => [rom]) {|key, old, new| old + new } }.each {|storage, roms| size = if ROM::Path::Archive === roms.first.path roms.first.path.archive.size end if storage.nil? roms.each {|rom| block.call(rom.path.entry, nil) } else if compact && (size == roms.size) then block.call(storage) else block.call(storage, roms.map {|r| r.path.entry }) end end } self end
Iterate over each ROM
@yieldparam rom [ROM]
@return [self,Enumerator]
# File lib/distillery/vault.rb, line 139 def each block_given? ? @roms.each {|r| yield(r) } : @roms.each end
@return [Boolean]
# File lib/distillery/vault.rb, line 124 def empty? @roms.empty? end
Check if we have some headered ROM
.
@return [Integer] only some ROMs are headered @return [true] all ROMs are headered @return [false] no headered ROM
# File lib/distillery/vault.rb, line 286 def headered size = @roms.select {|rom| rom.headered? }.size if size == 0 then false elsif size == @roms.size then true else size end end
Return list of matching ROMs.
@param query [Hash{Symbol=>String},ROM] Hash of checksums or ROM
to match with
@yieldparam rom [ROM] ROM
that has been saved
@return [Array<ROM>] list of matching ROMs @return [nil] if no match
# File lib/distillery/vault.rb, line 333 def match(query) case query when Hash then self.cksummatch(query) when ROM then self.rommatch(query) else raise ArgumentError end end
Return list of matching ROMs.
@param rom [ROM] ROM
to match with
@return [Array<ROM>] list of matching ROMs @return [nil] if no match
# File lib/distillery/vault.rb, line 318 def rommatch(rom) self.cksummatch(rom.cksums) end
Save ROM
to filesystem
@param dir [String] directory used for saving @param part [:all,:header,:rom] wich part of the ROM
file to save @param subdir [Boolean,Integer,Proc] use subdirectory @param pristine [Boolean] should existing directory be removed @param force [Boolean] remove previous file if necessary
@yieldparam rom [ROM] ROM
saved
@return [self]
# File lib/distillery/vault.rb, line 354 def save(dir, part: :all, subdir: false, pristine: false, force: false, &block) # Directory FileUtils.remove_dir(dir) if pristine # Create clean env Dir.mkdir(dir) unless Dir.exist?(dir) # Ensure directory # Fill directory. # -> We have the physical ROMs, so we have all the checksums # except if the file is an header without rom content @roms.select {|rom| rom.has_content? && !rom.fshash.nil? } .each {|rom| hash = rom.fshash destdir = dir dirpart = case subdir when nil, false then nil when true then hash[0..3] when Integer then hash[0..subdir] when Proc then subdir.call(rom) else raise ArgumentError, "unsupported subdir type" end if dirpart # Update destination directory destdir = File.join(destdir, *dirpart) # Ensure destination directory exists FileUtils.mkdir_p(destdir) end # Destination file dest = File.join(destdir, hash) # If the file exist, it is the right file, as it is # named from it's hash (ie: content) if force || !File.exists?(dest) rom.copy(dest, part: part, force: force) end block.call(rom) if block } self end
@return [Integer]
# File lib/distillery/vault.rb, line 129 def size @roms.size end
List of ROM
with loosely defined (ie: with some missing checksum)
@return [Array<ROM>,nil]
# File lib/distillery/vault.rb, line 275 def with_partial_checksum @roms.select {|rom| rom.missing_checksums? } end
Protected Instance Methods
# File lib/distillery/vault.rb, line 428 def roms @roms end