MCPcopy Create free account
hub / github.com/Shazbot/WH3-Mod-Manager / createPackWithRenamedFilesWithOptions

Function createPackWithRenamedFilesWithOptions

src/packFileSerializer.ts:3410–3531  ·  view source on GitHub ↗
(
  originalPack: Pack,
  tempPath: string,
  renameMap: Map<string, PackedFile>,
)

Source from the content-addressed store, hash-verified

3408 }
3409};
3410const createPackWithRenamedFilesWithOptions = async (
3411 originalPack: Pack,
3412 tempPath: string,
3413 renameMap: Map<string, PackedFile>,
3414): Promise<void> => {
3415 let outFile: BinaryFile | undefined;
3416 let sourceFileId = -1;
3417 try {
3418 // Create the final list of packed files
3419 const finalPackedFiles: PackedFile[] = [];
3420 // Add all files, using renamed versions where applicable
3421 for (const originalFile of originalPack.packedFiles) {
3422 const renamedFile = renameMap.get(originalFile.name);
3423 if (renamedFile) {
3424 finalPackedFiles.push(renamedFile);
3425 } else {
3426 finalPackedFiles.push(originalFile);
3427 }
3428 }
3429 // Write the new pack file
3430 outFile = new BinaryFile(tempPath, "w", true);
3431 sourceFileId = fs.openSync(originalPack.path, "r");
3432 await outFile.open();
3433 // Write header
3434 await writePackHeader(
3435 outFile,
3436 originalPack.packHeader,
3437 finalPackedFiles,
3438 originalPack.dependencyPacks || [],
3439 );
3440 // Pre-build file lookup map for O(1) instead of O(N) lookups
3441 const originalFileMap = new Map<string, PackedFile>();
3442 for (const pf of originalPack.packedFiles) {
3443 originalFileMap.set(pf.name, pf);
3444 }
3445 // Build reverse lookup for renamed files
3446 const renamedToOriginalMap = new Map<string, string>();
3447 for (const [originalName, renamedFile] of renameMap.entries()) {
3448 renamedToOriginalMap.set(renamedFile.name, originalName);
3449 }
3450 // Sort files by original pack position for sequential disk reads (much faster I/O)
3451 finalPackedFiles.sort((a, b) => {
3452 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
3453 const origA = originalFileMap.get(a.name) || originalFileMap.get(renamedToOriginalMap.get(a.name)!);
3454 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
3455 const origB = originalFileMap.get(b.name) || originalFileMap.get(renamedToOriginalMap.get(b.name)!);
3456 return (origA?.start_pos || 0) - (origB?.start_pos || 0);
3457 });
3458 // Create buffer pool for efficient memory reuse
3459 const bufferPool = new BufferPool();
3460 // Optimized batching for files mostly <1MB
3461 const SMALL_FILE_BATCH_SIZE = 2 * 1024 * 1024; // 2MB batches for small files
3462 const LARGE_FILE_THRESHOLD = 1024 * 1024; // 1MB threshold
3463 let currentBatchSize = 0;
3464 let batchBuffers: { buffer: Buffer; actualSize: number; poolBuffer: Buffer }[] = [];
3465 const flushBatch = async () => {
3466 if (batchBuffers.length > 0) {
3467 // Create array of buffer slices for concatenation

Callers 1

Calls 7

getBufferMethod · 0.95
returnBufferMethod · 0.95
clearMethod · 0.95
writePackHeaderFunction · 0.85
flushBatchFunction · 0.85
closeMethod · 0.80
getMethod · 0.65

Tested by

no test coverage detected