"use strict"; const Promise = require("bluebird"); const path = require("path"); const chalk = require("chalk"); const pad = require("pad"); const yargs = require("yargs"); const nanoid = require("nanoid"); const fs = Promise.promisifyAll(require("fs")); const ldd = require("./lib/ldd"); const findPackages = require("./lib/find-packages"); const generateEnvironment = require("./lib/generate-environment"); const nixBuild = require("./lib/nix-build"); const runProgram = require("./lib/run-program"); let argv = yargs .boolean("run") .argv; function printPackages(groupedPackages) { let packageNameWidth = Object.keys(groupedPackages).reduce((highest, pkg) => Math.max(highest, pkg.length), 0); Object.keys(groupedPackages).sort().forEach((pkg) => { console.log(` ${chalk.bold(pad(pkg, packageNameWidth))} ${groupedPackages[pkg].join(", ")}`); }); } function groupPackages(packages) { let grouped = {}; packages.forEach((pkg) => { if (grouped[pkg.package] == null) { grouped[pkg.package] = []; } grouped[pkg.package].push(pkg.library); }); return grouped; } let target = argv._[0]; Promise.try(() => { if (target == null) { throw new Error("Must specify a binary to analyze"); } else { return ldd(target); } }).then((libraries) => { let missingLibraries = libraries .filter((item) => item.location == null) .map((item) => item.library); return Promise.try(() => { return findPackages(missingLibraries) }).then((groupedResults) => { return Object.entries(groupedResults).map(([ library, pkg ]) => { return { library, package: pkg }; }); }); }).then((results) => { let groupedPackages = groupPackages(results); let binaryName = path.basename(target); console.log(""); console.log(chalk.cyan(`DepFish has guessed the following set of dependencies for ${chalk.bold(binaryName)}:`)); console.log(""); printPackages(groupedPackages); console.log(""); if (argv.run) { console.log(chalk.cyan(`Preparing to run ${chalk.bold(binaryName)}...`)); let buildExpression = generateEnvironment({ binaryName: binaryName, targetBinary: target, packages: Object.keys(groupedPackages) .concat([ "systemd" ]) /* Hack for libudev SIGTRAP issue; this may need to be detected interactively in the future */ }); let expressionPath = `/tmp/depfish-expr-${nanoid()}`; return Promise.try(() => { return fs.writeFileAsync(expressionPath, buildExpression); }).then(() => { console.log("Expression path:", expressionPath); return nixBuild(expressionPath); }).then((outPath) => { console.log("Build path:", outPath); return runProgram(`${outPath}/bin/${binaryName}`); }); } });