UNPKG

igir

Version:

🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.

119 lines (118 loc) • 5.22 kB
import { ProgressBarSymbol } from "../../console/progressBar.js"; import ArchiveFile from "../../models/files/archives/archiveFile.js"; import ArrayUtil from "../../utils/arrayUtil.js"; import FsUtil from "../../utils/fsUtil.js"; import IntlUtil from "../../utils/intlUtil.js"; import Module from "../module.js"; class CandidateArchiveFileHasher extends Module { options; fileFactory; mappableSemaphore; constructor(options, progressBar, fileFactory, mappableSemaphore) { super(progressBar, CandidateArchiveFileHasher.name); this.options = options; this.fileFactory = fileFactory; this.mappableSemaphore = mappableSemaphore; } /** * Hash the {@link ArchiveFile}s. */ // TODO(cememr): this is unnecessary work for files that will be renamed and not copied; we // probably want to delete this file and let CandidateWriter handle things async hash(dat, candidates) { if (candidates.length === 0) { this.prefixedLogger.trace(`${dat.getName()}: no candidates to hash ArchiveFiles for`); return candidates; } if (!this.options.shouldTest() && !this.options.getOverwriteInvalid()) { this.prefixedLogger.trace( `${dat.getName()}: not testing or overwriting invalid files, no need` ); return candidates; } const archiveFileCount = candidates.reduce( (sum, candidate) => sum + candidate.getRomsWithFiles().filter((romWithFiles) => this.romWithFilesNeedsProcessing(romWithFiles)).filter((romWithFiles) => romWithFiles.getInputFile().getFilePath()).reduce(ArrayUtil.reduceUnique(), []).length, 0 ); if (archiveFileCount === 0) { this.prefixedLogger.trace(`${dat.getName()}: no ArchiveFiles to hash`); return candidates; } this.prefixedLogger.trace( `${dat.getName()}: generating ${IntlUtil.toLocaleString(archiveFileCount)} hashed ArchiveFile candidate${archiveFileCount === 1 ? "" : "s"}` ); this.progressBar.setSymbol(ProgressBarSymbol.CANDIDATE_HASHING); this.progressBar.resetProgress(archiveFileCount); const hashedCandidates = this.hashArchiveFiles(dat, candidates); this.prefixedLogger.trace(`${dat.getName()}: done generating hashed ArchiveFile candidates`); return await hashedCandidates; } async hashArchiveFiles(dat, candidates) { return await Promise.all( candidates.map(async (candidate) => { const uniqueInputArchiveFiles = candidate.getRomsWithFiles().filter((rwf) => this.romWithFilesNeedsProcessing(rwf)).map((rwf) => rwf.getInputFile()).filter((inputFile) => inputFile instanceof ArchiveFile).filter(ArrayUtil.filterUniqueMapped((inputFile) => inputFile.getFilePath())); const hashedArchiveFiles = await this.mappableSemaphore.map( uniqueInputArchiveFiles, async (archiveFile) => { this.progressBar.incrementInProgress(); this.prefixedLogger.trace( `${dat.getName()}: ${candidate.getName()}: calculating checksums for: ${archiveFile.toString()}` ); const childBar = this.progressBar.addChildBar({ name: archiveFile.toString(), total: archiveFile.getSize(), progressFormatter: FsUtil.sizeReadable.bind(FsUtil) }); try { const hashedArchiveFile = await this.fileFactory.archiveFileFrom( archiveFile.getArchiveEntry(), archiveFile.getChecksumBitmask(), (progress) => { childBar.setCompleted(progress); } ); this.progressBar.incrementCompleted(); return hashedArchiveFile; } finally { childBar.delete(); } } ); const filePathsToArchiveFiles = hashedArchiveFiles.reduce((map, archiveFile) => { map.set(archiveFile.getFilePath(), archiveFile); return map; }, /* @__PURE__ */ new Map()); const hashedRomsWithFiles = candidate.getRomsWithFiles().map((romWithFiles) => { if (!this.romWithFilesNeedsProcessing(romWithFiles)) { return romWithFiles; } const hashedInputFile = filePathsToArchiveFiles.get( romWithFiles.getInputFile().getFilePath() ); if (hashedInputFile === void 0) { return romWithFiles; } const hashedOutputFile = romWithFiles.getOutputFile().withProps({ size: hashedInputFile.getSize(), crc32: hashedInputFile.getCrc32(), md5: hashedInputFile.getMd5(), sha1: hashedInputFile.getSha1(), sha256: hashedInputFile.getSha256() }); return romWithFiles.withInputFile(hashedInputFile).withOutputFile(hashedOutputFile); }); return candidate.withRomsWithFiles(hashedRomsWithFiles); }) ); } romWithFilesNeedsProcessing(romWithFiles) { if (!(romWithFiles.getInputFile() instanceof ArchiveFile)) { return false; } return !romWithFiles.getInputFile().equals(romWithFiles.getOutputFile()); } } export { CandidateArchiveFileHasher as default }; //# sourceMappingURL=candidateArchiveFileHasher.js.map