Class: Distillery::Vault
- Inherits:
-
Object
- Object
- Distillery::Vault
- Includes:
- Enumerable
- Defined in:
- lib/distillery/vault.rb
Constant Summary collapse
- CHECKSUMS =
List of ROM checksums
ROM::CHECKSUMS
- ARCHIVES =
List of archives extensions
ROMArchive::EXTENSIONS
- IGNORE_FILES =
List of files to be ignored
Set[ '.dat', '.missing', '.baddump', '.extra' ]
- IGNORE_DIRS =
List of directories to be ignored
Set[ '.roms', '.games', '.trash' ]
- DIR_PRUNING =
Directory pruning
Set[ '.dat' ]
Class Method Summary collapse
-
.from_dir(dir, depth: nil) {|file, dir:| ... } ⇒ Object
Potential ROM from directory.
-
.from_glob(glob, basedir: :guess) {|file, dir:| ... } ⇒ Object
Potential ROM from glob.
Instance Method Summary collapse
-
#&(o) ⇒ Vault
Construct a new ROM vault as the intersection.
-
#-(o) ⇒ Vault
Constuct a new ROM vault as the difference.
-
#<<(rom) ⇒ Object
Add ROM.
-
#add_from_dir(dir, depth: nil, archives: ARCHIVES) {|file, dir| ... } ⇒ self
Add ROM from directory.
-
#add_from_file(file, basedir = nil, archives: ARCHIVES) ⇒ self
Add ROM from file.
-
#add_from_glob(glob, basedir: :guess, archives: ARCHIVES) {|file, dir| ... } ⇒ self
Add ROM from glob.
-
#add_rom(rom) ⇒ Object
Add ROM.
-
#cksummatch(query) ⇒ Array<ROM>?
Return list of matching ROMs.
-
#dump(compact: false) {|group, entries| ... } ⇒ self
Dumping of ROM vault entries.
-
#each {|rom| ... } ⇒ self, Enumerator
Iterate over each ROM.
- #empty? ⇒ Boolean
-
#headered ⇒ Integer, ...
Check if we have some headered ROM.
-
#initialize(roms = []) ⇒ Vault
constructor
A new instance of Vault.
-
#match(query) {|rom| ... } ⇒ Array<ROM>?
Return list of matching ROMs.
-
#rommatch(rom) ⇒ Array<ROM>?
Return list of matching ROMs.
-
#save(dir, part: :all, subdir: false, pristine: false, force: false) {|rom| ... } ⇒ self
Save ROM to filesystem.
- #size ⇒ Integer
-
#with_partial_checksum ⇒ Array<ROM>?
List of ROM with loosely defined (ie: with some missing checksum).
Constructor Details
Class Method Details
.from_dir(dir, depth: nil) {|file, dir:| ... } ⇒ Object
file in IGNORE_FILES, directory in IGNORE_DIRS, directories holding a DIR_PRUNING file or starting with a dot are ignored
Potential ROM from directory.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# 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 |
.from_glob(glob, basedir: :guess) {|file, dir:| ... } ⇒ Object
file in IGNORE_FILES, directory in IGNORE_DIRS, directories holding a DIR_PRUNING file or starting with a dot are ignored
Potential ROM from glob
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# 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 |
Instance Method Details
#&(o) ⇒ Vault
Construct a new ROM vault as the intersection
149 150 151 |
# File 'lib/distillery/vault.rb', line 149 def &(o) Vault::new(@roms.select {|rom| o.match(rom) }) end |
#-(o) ⇒ Vault
Constuct a new ROM vault as the difference
159 160 161 |
# File 'lib/distillery/vault.rb', line 159 def -(o) Vault::new(@roms.reject {|rom| o.match(rom) }) end |
#<<(rom) ⇒ Object
Add ROM
170 171 172 |
# File 'lib/distillery/vault.rb', line 170 def <<(rom) add_rom(rom) end |
#add_from_dir(dir, depth: nil, archives: ARCHIVES) {|file, dir| ... } ⇒ self
file in IGNORE_FILES, directory in IGNORE_DIRS, directories holding a DIR_PRUNING file or starting with a dot are ignored
Add ROM from directory.
238 239 240 241 242 243 244 |
# 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_from_file(file, basedir = nil, archives: ARCHIVES) ⇒ self
Add ROM from file
213 214 215 216 217 218 219 220 221 |
# 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_from_glob(glob, basedir: :guess, archives: ARCHIVES) {|file, dir| ... } ⇒ self
file in IGNORE_FILES, directory in IGNORE_DIRS, directories holding a DIR_PRUNING file or starting with a dot are ignored
Add ROM from glob
262 263 264 265 266 267 268 |
# 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(rom) ⇒ Object
Add ROM
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# 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 |
#cksummatch(query) ⇒ Array<ROM>?
Return list of matching ROMs.
302 303 304 305 306 307 308 309 |
# 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 |
#dump(compact: false) {|group, entries| ... } ⇒ self
Dumping of ROM vault entries
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# 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 |
#each {|rom| ... } ⇒ self, Enumerator
Iterate over each ROM
139 140 141 142 |
# File 'lib/distillery/vault.rb', line 139 def each block_given? ? @roms.each {|r| yield(r) } : @roms.each end |
#empty? ⇒ Boolean
124 125 126 |
# File 'lib/distillery/vault.rb', line 124 def empty? @roms.empty? end |
#headered ⇒ Integer, ...
Check if we have some headered ROM.
286 287 288 289 290 291 292 293 |
# 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 |
#match(query) {|rom| ... } ⇒ Array<ROM>?
Return list of matching ROMs.
333 334 335 336 337 338 339 |
# 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 |
#rommatch(rom) ⇒ Array<ROM>?
Return list of matching ROMs.
318 319 320 |
# File 'lib/distillery/vault.rb', line 318 def rommatch(rom) self.cksummatch(rom.cksums) end |
#save(dir, part: :all, subdir: false, pristine: false, force: false) {|rom| ... } ⇒ self
Save ROM to filesystem
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# 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 |
#size ⇒ Integer
129 130 131 |
# File 'lib/distillery/vault.rb', line 129 def size @roms.size end |
#with_partial_checksum ⇒ Array<ROM>?
List of ROM with loosely defined (ie: with some missing checksum)
275 276 277 |
# File 'lib/distillery/vault.rb', line 275 def with_partial_checksum @roms.select {|rom| rom.missing_checksums? } end |