From 8d88ea937b1a802ddd4bbab7a2d98db579259cd1 Mon Sep 17 00:00:00 2001 From: William Chargin Date: Thu, 28 May 2020 19:01:03 -0700 Subject: [PATCH] sc2: add graph subcommand (#1811) Summary: Paired with @decentralion. Test Plan: Follow the test plan for #1810, then additionally run ``` (cd /tmp/test-instance && node "$OLDPWD/bin/sc2.js" graph) ``` and note that the `output/graphs/...` directory has a graph JSON file. wchargin-branch: cli2-graph --- src/cli2/graph.js | 55 ++++++++++++++++++++++++++++++++++++++++++ src/cli2/sourcecred.js | 3 +++ 2 files changed, 58 insertions(+) create mode 100644 src/cli2/graph.js diff --git a/src/cli2/graph.js b/src/cli2/graph.js new file mode 100644 index 0000000..e48e724 --- /dev/null +++ b/src/cli2/graph.js @@ -0,0 +1,55 @@ +// @flow + +import fs from "fs-extra"; +import sortBy from "lodash.sortby"; +import stringify from "json-stable-stringify"; +import {join as pathJoin} from "path"; + +import {CascadingReferenceDetector} from "../core/references/cascadingReferenceDetector"; +import type {Command} from "./command"; +import { + makePluginDir, + loadInstanceConfig, + pluginDirectoryContext, +} from "./common"; +import {toJSON as weightedGraphToJSON} from "../core/weightedGraph"; + +function die(std, message) { + std.err("fatal: " + message); + return 1; +} + +const graphCommand: Command = async (args, std) => { + if (args.length !== 0) { + die(std, "usage: sourcecred graph"); + } + const baseDir = process.cwd(); + const config = await loadInstanceConfig(baseDir); + const graphOutputPrefix = ["output", "graphs"]; + + const rd = await buildReferenceDetector(baseDir, config); + for (const [name, plugin] of config.bundledPlugins) { + const dirContext = pluginDirectoryContext(baseDir, name); + const graph = await plugin.graph(dirContext, rd); + const serializedGraph = stringify(weightedGraphToJSON(graph)); + const outputDir = makePluginDir(baseDir, graphOutputPrefix, name); + const outputPath = pathJoin(outputDir, "graph.json"); + await fs.writeFile(outputPath, serializedGraph); + } + return 0; +}; + +async function buildReferenceDetector(baseDir, config) { + const rds = []; + for (const [name, plugin] of sortBy( + [...config.bundledPlugins], + ([k, _]) => k + )) { + const dirContext = pluginDirectoryContext(baseDir, name); + const rd = await plugin.referenceDetector(dirContext); + rds.push(rd); + } + return new CascadingReferenceDetector(rds); +} + +export default graphCommand; diff --git a/src/cli2/sourcecred.js b/src/cli2/sourcecred.js index 72b854f..43c0e8b 100644 --- a/src/cli2/sourcecred.js +++ b/src/cli2/sourcecred.js @@ -3,6 +3,7 @@ import type {Command} from "./command"; import load from "./load"; +import graph from "./graph"; const sourcecred: Command = async (args, std) => { if (args.length === 0) { @@ -12,6 +13,8 @@ const sourcecred: Command = async (args, std) => { switch (args[0]) { case "load": return load(args.slice(1), std); + case "graph": + return graph(args.slice(1), std); default: std.err("fatal: unknown command: " + JSON.stringify(args[0])); return 1;