"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const canLink = require("can-link");
const fs = require("mz/fs");
const os = require("os");
const path = require("path");
const pathAbsolute = require("path-absolute");
const pathTemp = require("path-temp");
const rootLinkTarget = require("root-link-target");
const touch = require("touch");
const STORE_VERSION = 'v3';
async function default_1(pkgRoot, storePath) {
    if (!storePath || isHomepath(storePath)) {
        const relStorePath = storePath ? storePath.substr(2) : '.pnpm-store';
        return await storePathRelativeToHome(pkgRoot, relStorePath);
    }
    const storeBasePath = pathAbsolute(storePath, pkgRoot);
    if (storeBasePath.endsWith(`${path.sep}${STORE_VERSION}`)) {
        return storeBasePath;
    }
    return path.join(storeBasePath, STORE_VERSION);
}
exports.default = default_1;
async function storePathRelativeToHome(pkgRoot, relStore) {
    const tempFile = pathTemp(pkgRoot);
    await fs.mkdir(path.dirname(tempFile), { recursive: true });
    await touch(tempFile);
    const homedir = getHomedir();
    if (await canLink(tempFile, pathTemp(homedir))) {
        await fs.unlink(tempFile);
        // If the project is on the drive on which the OS home directory
        // then the store is placed in the home directory
        return path.join(homedir, relStore, STORE_VERSION);
    }
    try {
        let mountpoint = await rootLinkTarget(tempFile);
        // Usually, it is disallowed to write files into the drive's root.
        // So we create an empty directory and try to link there.
        // The store will be a directory anyway.
        const mountpointParent = path.join(mountpoint, '..');
        if (!dirsAreEqual(mountpointParent, mountpoint) && await canLinkToSubdir(tempFile, mountpointParent)) {
            mountpoint = mountpointParent;
        }
        // If linking works only in the project folder
        // then prefer to place the store inside the homedir
        if (dirsAreEqual(pkgRoot, mountpoint)) {
            return path.join(homedir, relStore, STORE_VERSION);
        }
        return path.join(mountpoint, relStore, STORE_VERSION);
    }
    catch (err) {
        // this is an unlikely situation but if there is no way to find
        // a linkable place on the disk, create the store in homedir
        return path.join(homedir, relStore, STORE_VERSION);
    }
    finally {
        await fs.unlink(tempFile);
    }
}
async function canLinkToSubdir(fileToLink, dir) {
    let result = false;
    try {
        const tmpDir = pathTemp(dir);
        await fs.mkdir(tmpDir, { recursive: true });
        result = await canLink(fileToLink, pathTemp(tmpDir));
        await fs.rmdir(tmpDir);
    }
    catch (err) {
        return false;
    }
    return result;
}
function dirsAreEqual(dir1, dir2) {
    return path.relative(dir1, dir2) === '.';
}
function getHomedir() {
    const home = os.homedir();
    if (!home)
        throw new Error('Could not find the homedir');
    return home;
}
function isHomepath(filepath) {
    return filepath.indexOf('~/') === 0 || filepath.indexOf('~\\') === 0;
}
//# sourceMappingURL=index.js.map