RomainMuller/pko

View on GitHub
lib/determine-storage-directory.ts

Summary

Maintainability
A
0 mins
Test Coverage
F
59%
import fs = require('fs-extra');
import path = require('path');
import { debug } from './logging';

/** The parent directory of this module's location */
const installRoot = path.resolve(path.join(__dirname, '..', '..'));
/** The standard name of pko overlay directories */
const overlayName = path.join('.pko');

/**
 * Determines the directory where the overlay is located, using the following workflow:
 *   1. ${PKO_REPOSITORY}
 *   2. Walk up the tree from ${cwd} until:
 *      * A .pko directory is found
 *      * The root of the filesystem is reached
 *   3. Walk up the tree from the module's install location until:
 *      * A .pko directory is found
 *      * The root of the filesystem is reached
 *   4. Bail out in error.
 * @returns the directory where the overlay directory is located.
 */
export async function determineStorageDirectory() {
  let result: string | undefined = process.env.PKO_REPOSITORY;
  if (!result) { result = await findOverlayDirectory(process.cwd()); }
  if (!result) { result = await findOverlayDirectory(installRoot); }
  if (!result) {
    throw new Error(`Unable to locate the ${overlayName} overlay directory, maybe you should set the PKO_REPOSITORY environment variable?`);
  }
  debug(`Storage directory: ${result} (override by setting the PKO_REPOSITORY environment variable)`);
  if (!await fs.pathExists(result)) {
    throw new Error(`Storage directory does not exist: ${result}`);
  }
  return result;
}

/**
 * Search for an overlay directory in a tree structure, walking up from the provided directory.
 * @param dir the directory where the search starts
 * @returns the full path to the overlay directory, or ``undefined`` if the root
 *      of the filesystem is reached without finding one.
 */
async function findOverlayDirectory(dir: string): Promise<string | undefined> {
  const candidate = path.join(dir, overlayName);
  if (await fs.pathExists(candidate)) {
    return path.normalize(candidate);
  }
  const parent = path.normalize(path.resolve(path.join(dir, '..')));
  if (parent !== dir) {
    return await findOverlayDirectory(parent);
  }
  return undefined;
}