"use strict"; const Promise = require("bluebird"); const escapeStringRegexp = require("escape-string-regexp"); const execFileAsync = require("./exec-file-async"); function groupBySearchQuery(queries, results) { let queryResults = {}; queries.forEach((query) => { queryResults[query] = []; }); results.forEach((result) => { let found = false; for (let query of queries) { if (result.storePath.endsWith(query)) { queryResults[query].push(result); found = true; break; } } if (found === false) { throw new Error(`Encountered result without matching query: ${result.storePath}`); } }); return queryResults; } module.exports = function nixLocate(libraries) { return Promise.try(() => { /* NOTE: This uses the regex capabilities of `nix-locate` to do a batch search; this is much, *much* faster than running `nix-locate` for each individual library. */ let combinedLibraries = libraries.map((query) => escapeStringRegexp(query)).join("|"); return execFileAsync("nix-locate", [ "--top-level", "--whole-name", "--at-root", "--regex", `/lib/(${combinedLibraries})` ]); }).then(({ stdout, stderr }) => { let results = stdout.split("\n").filter((line) => { return (line.trim().length > 0); }).map((line) => { let match = /^(\S+)\s+([0-9,]+)\s+([a-z]+)\s+(.+)$/.exec(line); if (match == null) { throw new Error(`Encountered unexpected output from nix-locate: ${line}`); } else { let attribute = (match[1].endsWith(".out")) ? match[1].split(".").slice(0, -1).join(".") : match[1]; return { attribute: attribute, storePath: match[4] }; } }); return groupBySearchQuery(libraries, results); }); };