Extract a common SOURCECRED_DIRECTORY flag (#227)

Summary:
This solves two problems:

 1. The “output directory” argument to `sourcecred graph` is also the
    input directory to other commands, like `sourcecred analyze`
    (hypothetically). In such cases, it would be nice for the flag to
    have the same name, but clearly `--output-directory` does not always
    make sense.

 2. In addition to storing graphs, we’ll need to store other kinds of
    data: settings, intermediate data for plugins to cache results, etc.
    We should store these under a single umbrella.

With both of these problems in mind, it makes sense to create a
`SOURCECRED_DIRECTORY` flag under which we store all relevant data.

Test Plan:
Run:
```shell
$ yarn backend
$ node bin/sourcecred.js help graph
$ node bin/sourcecred.js graph sourcecred example-github
$ node bin/sourcecred.js graph sourcecred example-github -d /tmp/sorcecrod
$ SOURCECRED_DIRECTORY=/tmp/srccrd node bin/sourcecred.js graph sourcecred example-github
$ for dir in /tmp/{sourcecred,sorcecrod,srccrd}; do find "${dir}"; done
```

wchargin-branch: graph-directory
This commit is contained in:
William Chargin 2018-05-07 17:05:58 -07:00 committed by GitHub
parent 498480db06
commit 0cae9d742d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 20 deletions

View File

@ -4,7 +4,7 @@ import {Command, flags} from "@oclif/command";
import mkdirp from "mkdirp"; import mkdirp from "mkdirp";
import path from "path"; import path from "path";
import {defaultStorageDirectory, pluginNames} from "../common"; import {pluginNames, sourcecredDirectoryFlag} from "../common";
const execDependencyGraph = require("../../tools/execDependencyGraph").default; const execDependencyGraph = require("../../tools/execDependencyGraph").default;
@ -22,8 +22,7 @@ create the contribution graph for a repository
Create the contribution graph for a repository. This creates a Create the contribution graph for a repository. This creates a
contribution graph for each individual plugin, and then combines the contribution graph for each individual plugin, and then combines the
individual graphs into one larger graph. The graphs are stored as JSON individual graphs into one larger graph. The graphs are stored as JSON
files under OUTPUT_DIR/REPO_OWNER/REPO_NAME, where OUTPUT_DIR is files under SOURCECRED_DIRECTORY/graphs/REPO_OWNER/REPO_NAME.
configurable.
`.trim(); `.trim();
static args = [ static args = [
@ -40,12 +39,7 @@ configurable.
]; ];
static flags = { static flags = {
"output-directory": flags.string({ "sourcecred-directory": sourcecredDirectoryFlag(),
short: "o",
description: "directory into which to store graphs",
env: "SOURCECRED_OUTPUT_DIRECTORY",
default: defaultStorageDirectory(),
}),
"github-token": flags.string({ "github-token": flags.string({
description: description:
"a GitHub API token, as generated at " + "a GitHub API token, as generated at " +
@ -58,30 +52,38 @@ configurable.
async run() { async run() {
const { const {
args: {repo_owner: repoOwner, repo_name: repoName}, args: {repo_owner: repoOwner, repo_name: repoName},
flags: {"github-token": token, "output-directory": outputDirectory}, flags: {
"github-token": token,
"sourcecred-directory": sourcecredDirectory,
},
} = this.parse(GraphCommand); } = this.parse(GraphCommand);
graph(outputDirectory, repoOwner, repoName, token); graph(sourcecredDirectory, repoOwner, repoName, token);
} }
} }
function graph( function graph(
outputDirectory: string, sourcecredDirectory: string,
repoOwner: string, repoOwner: string,
repoName: string, repoName: string,
token: string token: string
) { ) {
const scopedDirectory = path.join(outputDirectory, repoOwner, repoName); const graphDirectory = path.join(
console.log("Storing graphs into: " + scopedDirectory); sourcecredDirectory,
mkdirp.sync(scopedDirectory); "graphs",
const tasks = makeTasks(scopedDirectory, {repoOwner, repoName, token}); repoOwner,
repoName
);
console.log("Storing graphs into: " + graphDirectory);
mkdirp.sync(graphDirectory);
const tasks = makeTasks(graphDirectory, {repoOwner, repoName, token});
execDependencyGraph(tasks, {taskPassLabel: "DONE"}).then(({success}) => { execDependencyGraph(tasks, {taskPassLabel: "DONE"}).then(({success}) => {
process.exitCode = success ? 0 : 1; process.exitCode = success ? 0 : 1;
}); });
} }
function makeTasks(outputDirectory, {repoOwner, repoName, token}) { function makeTasks(graphDirectory, {repoOwner, repoName, token}) {
const taskId = (id) => `create-${id}`; const taskId = (id) => `create-${id}`;
const graphFilename = (id) => path.join(outputDirectory, `graph-${id}.json`); const graphFilename = (id) => path.join(graphDirectory, `graph-${id}.json`);
const into = "./src/cli/into.sh"; const into = "./src/cli/into.sh";
return [ return [
...pluginNames().map((id) => ({ ...pluginNames().map((id) => ({
@ -105,7 +107,7 @@ function makeTasks(outputDirectory, {repoOwner, repoName, token}) {
id: "combine", id: "combine",
cmd: [ cmd: [
into, into,
path.join(outputDirectory, "graph.json"), path.join(graphDirectory, "graph.json"),
"node", "node",
"./bin/sourcecred.js", "./bin/sourcecred.js",
"combine", "combine",

View File

@ -1,5 +1,6 @@
// @flow // @flow
import {flags} from "@oclif/command";
import os from "os"; import os from "os";
import path from "path"; import path from "path";
@ -8,6 +9,15 @@ export function pluginNames() {
return ["git", "github"]; return ["git", "github"];
} }
export function defaultStorageDirectory() { function defaultStorageDirectory() {
return path.join(os.tmpdir(), "sourcecred"); return path.join(os.tmpdir(), "sourcecred");
} }
export function sourcecredDirectoryFlag() {
return flags.string({
char: "d",
description: "directory for storing graphs and other SourceCred data",
env: "SOURCECRED_DIRECTORY",
default: () => defaultStorageDirectory(),
});
}