"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const logger_1 = require("@pnpm/logger");
const rimraf = require("@zkochan/rimraf");
const makeEmptyDir = require("make-empty-dir");
const fs = require("mz/fs");
const path = require("path");
const pathTemp = require("path-temp");
const renameOverwrite = require("rename-overwrite");
const filenameConflictsLogger = logger_1.default('_filename-conflicts');
async function importIndexedDir(importFile, newDir, filenames) {
    const stage = pathTemp(path.dirname(newDir));
    try {
        await tryImportIndexedDir(importFile, stage, filenames);
        await renameOverwrite(stage, newDir);
    }
    catch (err) {
        try {
            await rimraf(stage);
        }
        catch (err) { } // tslint:disable-line:no-empty
        if (err['code'] !== 'EEXIST')
            throw err;
        const { uniqueFileMap, conflictingFileNames } = getUniqueFileMap(filenames);
        if (Object.keys(conflictingFileNames).length === 0)
            throw err;
        filenameConflictsLogger.debug({
            conflicts: conflictingFileNames,
            writingTo: newDir,
        });
        logger_1.globalWarn(`Not all files were linked to "${path.relative(process.cwd(), newDir)}". ` +
            'Some of the files have equal names in different case, ' +
            'which is an issue on case-insensitive filesystems. ' +
            `The conflicting file names are: ${JSON.stringify(conflictingFileNames)}`);
        await importIndexedDir(importFile, newDir, uniqueFileMap);
    }
}
exports.default = importIndexedDir;
async function tryImportIndexedDir(importFile, newDir, filenames) {
    await makeEmptyDir(newDir, { recursive: true });
    const alldirs = new Set();
    Object.keys(filenames)
        .forEach((f) => {
        const dir = path.dirname(f);
        if (dir === '.')
            return;
        alldirs.add(dir);
    });
    await Promise.all(Array.from(alldirs)
        .sort((d1, d2) => d1.length - d2.length) // from shortest to longest
        .map((dir) => fs.mkdir(path.join(newDir, dir), { recursive: true })));
    await Promise.all(Object.entries(filenames)
        .map(async ([f, src]) => {
        const dest = path.join(newDir, f);
        await importFile(src, dest);
    }));
}
function getUniqueFileMap(fileMap) {
    const lowercaseFiles = new Map();
    const conflictingFileNames = {};
    const uniqueFileMap = {};
    for (const filename of Object.keys(fileMap).sort()) {
        const lowercaseFilename = filename.toLowerCase();
        if (lowercaseFiles.has(lowercaseFilename)) {
            conflictingFileNames[filename] = lowercaseFiles.get(lowercaseFilename);
            continue;
        }
        lowercaseFiles.set(lowercaseFilename, filename);
        uniqueFileMap[filename] = fileMap[filename];
    }
    return {
        conflictingFileNames,
        uniqueFileMap,
    };
}
//# sourceMappingURL=importIndexedDir.js.map