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
JavaScript
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