Replace `oclif` with `cli` (#744)
Summary: This commit changes the CLI to use the code in `cli` instead of `oclif`. A subsequent commit will remove the dependency on OClif altogether. Resolves #580. Test Plan: Note that `yarn backend; node bin/sourcecred.js help` works. Note that the documentation in the README is still correct. wchargin-branch: cli-replace-oclif
This commit is contained in:
parent
17172c2d96
commit
e71264f5cc
|
@ -27,9 +27,7 @@ module.exports = {
|
|||
// source file, and the key will be the filename of the bundled entry
|
||||
// point within the build directory.
|
||||
backendEntryPoints: {
|
||||
sourcecred: resolveApp("src/oclif/sourcecred.js"),
|
||||
"commands/load": resolveApp("src/oclif/commands/load.js"),
|
||||
cli: resolveApp("src/cli/main.js"),
|
||||
sourcecred: resolveApp("src/cli/main.js"),
|
||||
//
|
||||
fetchAndPrintGithubRepo: resolveApp(
|
||||
"src/plugins/github/bin/fetchAndPrintGithubRepo.js"
|
||||
|
|
|
@ -130,12 +130,5 @@
|
|||
"files": [
|
||||
"/bin",
|
||||
"/build"
|
||||
],
|
||||
"oclif": {
|
||||
"commands": "./bin/commands",
|
||||
"bin": "sourcecred",
|
||||
"plugins": [
|
||||
"@oclif/plugin-help"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// @flow
|
||||
|
||||
// The repoRegistry is written by the CLI load command
|
||||
// (src/oclif/commands/load.js; src/cli/load.js) and is read by the
|
||||
// RepositorySelect component (src/app/credExplorer/RepositorySelect.js)
|
||||
// The repoRegistry is written by the CLI load command (src/cli/load.js)
|
||||
// and is read by the RepositorySelect component
|
||||
// (src/app/credExplorer/RepositorySelect.js)
|
||||
import deepEqual from "lodash.isequal";
|
||||
import {toCompat, fromCompat, type Compatible} from "../../util/compat";
|
||||
import type {Repo} from "../../core/repo";
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import {Command, flags} from "@oclif/command";
|
||||
import mkdirp from "mkdirp";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import stringify from "json-stable-stringify";
|
||||
|
||||
import {loadGithubData} from "../../plugins/github/loadGithubData";
|
||||
import {loadGitData} from "../../plugins/git/loadGitData";
|
||||
import {
|
||||
pluginNames,
|
||||
defaultPlugins,
|
||||
nodeMaxOldSpaceSizeFlag,
|
||||
sourcecredDirectoryFlag,
|
||||
} from "../common";
|
||||
|
||||
import {repoToString, stringToRepo} from "../../core/repo";
|
||||
|
||||
import {
|
||||
toJSON,
|
||||
fromJSON,
|
||||
addRepo,
|
||||
emptyRegistry,
|
||||
REPO_REGISTRY_FILE,
|
||||
} from "../../app/credExplorer/repoRegistry";
|
||||
|
||||
const execDependencyGraph = require("../../tools/execDependencyGraph").default;
|
||||
|
||||
export default class PluginGraphCommand extends Command {
|
||||
static description = "load data required for SourceCred";
|
||||
|
||||
static strict = false;
|
||||
|
||||
static args = [
|
||||
{
|
||||
name: "repos",
|
||||
required: true,
|
||||
description:
|
||||
"GitHub repos to load (one per argument), represented as OWNER/NAME",
|
||||
},
|
||||
];
|
||||
|
||||
static flags = {
|
||||
plugin: flags.string({
|
||||
description:
|
||||
"plugin whose data to load (loads default plugins if not set)",
|
||||
required: false,
|
||||
options: pluginNames(),
|
||||
}),
|
||||
output: flags.string({
|
||||
description:
|
||||
"the GitHub repo under which to store output; " +
|
||||
"required unless exactly one repository is specified",
|
||||
required: false,
|
||||
}),
|
||||
"sourcecred-directory": sourcecredDirectoryFlag(),
|
||||
"max-old-space-size": nodeMaxOldSpaceSizeFlag(),
|
||||
"github-token": flags.string({
|
||||
description:
|
||||
"a GitHub API token, as generated at " +
|
||||
"https://github.com/settings/tokens/new" +
|
||||
"; required only if using the GitHub plugin",
|
||||
env: "SOURCECRED_GITHUB_TOKEN",
|
||||
}),
|
||||
};
|
||||
|
||||
async run() {
|
||||
const {
|
||||
argv,
|
||||
flags: {
|
||||
output: defaultOutput,
|
||||
"github-token": githubToken,
|
||||
"sourcecred-directory": basedir,
|
||||
"max-old-space-size": maxOldSpaceSize,
|
||||
plugin,
|
||||
},
|
||||
} = this.parse(PluginGraphCommand);
|
||||
const repos = argv.map((s) => stringToRepo(s));
|
||||
const outputRepo = (() => {
|
||||
if (defaultOutput != null) {
|
||||
return stringToRepo(defaultOutput);
|
||||
} else if (repos.length === 1) {
|
||||
return repos[0];
|
||||
} else {
|
||||
throw new Error("output repository not specified");
|
||||
}
|
||||
})();
|
||||
if (!plugin) {
|
||||
loadDefaultPlugins({
|
||||
basedir,
|
||||
plugin,
|
||||
outputRepo,
|
||||
repos,
|
||||
githubToken,
|
||||
maxOldSpaceSize,
|
||||
});
|
||||
} else {
|
||||
loadPlugin({basedir, plugin, outputRepo, repos, githubToken});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadDefaultPlugins({
|
||||
basedir,
|
||||
outputRepo,
|
||||
repos,
|
||||
githubToken,
|
||||
maxOldSpaceSize,
|
||||
}) {
|
||||
if (githubToken == null) {
|
||||
// TODO: This check should be abstracted so that plugins can
|
||||
// specify their argument dependencies and get nicely
|
||||
// formatted errors.
|
||||
console.error("fatal: No GitHub token specified. Try `--help'.");
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
const tasks = [
|
||||
...defaultPlugins().map((pluginName) => ({
|
||||
id: `load-${pluginName}`,
|
||||
cmd: [
|
||||
"node",
|
||||
`--max_old_space_size=${maxOldSpaceSize}`,
|
||||
"./bin/sourcecred.js",
|
||||
"load",
|
||||
...repos.map((repo) => repoToString(repo)),
|
||||
"--plugin",
|
||||
pluginName,
|
||||
"--github-token",
|
||||
githubToken,
|
||||
"--output",
|
||||
repoToString(outputRepo),
|
||||
"-d",
|
||||
basedir,
|
||||
"--max-old-space-size",
|
||||
maxOldSpaceSize,
|
||||
],
|
||||
deps: [],
|
||||
})),
|
||||
];
|
||||
execDependencyGraph(tasks, {taskPassLabel: "DONE"}).then(({success}) => {
|
||||
if (success) {
|
||||
addToRepoRegistry({basedir, repo: outputRepo});
|
||||
}
|
||||
process.exitCode = success ? 0 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
function loadPlugin({basedir, plugin, outputRepo, repos, githubToken}) {
|
||||
function scopedDirectory(key) {
|
||||
const directory = path.join(basedir, key, repoToString(outputRepo), plugin);
|
||||
mkdirp.sync(directory);
|
||||
return directory;
|
||||
}
|
||||
const outputDirectory = scopedDirectory("data");
|
||||
const cacheDirectory = scopedDirectory("cache");
|
||||
switch (plugin) {
|
||||
case "github":
|
||||
if (githubToken == null) {
|
||||
// TODO: This check should be abstracted so that plugins can
|
||||
// specify their argument dependencies and get nicely
|
||||
// formatted errors.
|
||||
console.error("fatal: No GitHub token specified. Try `--help'.");
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
} else {
|
||||
loadGithubData({
|
||||
token: githubToken,
|
||||
repos,
|
||||
outputDirectory,
|
||||
cacheDirectory,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "git":
|
||||
loadGitData({repos, outputDirectory, cacheDirectory});
|
||||
break;
|
||||
default:
|
||||
console.error("fatal: Unknown plugin: " + (plugin: empty));
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function addToRepoRegistry(options) {
|
||||
// TODO: Make this function transactional before loading repositories in
|
||||
// parallel.
|
||||
const {basedir, repo} = options;
|
||||
const outputFile = path.join(basedir, REPO_REGISTRY_FILE);
|
||||
let registry = null;
|
||||
if (fs.existsSync(outputFile)) {
|
||||
const contents = fs.readFileSync(outputFile);
|
||||
const registryJSON = JSON.parse(contents.toString());
|
||||
registry = fromJSON(registryJSON);
|
||||
} else {
|
||||
registry = emptyRegistry();
|
||||
}
|
||||
registry = addRepo(repo, registry);
|
||||
|
||||
fs.writeFileSync(outputFile, stringify(toJSON(registry)));
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// @flow
|
||||
|
||||
import {flags} from "@oclif/command";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
|
||||
export type PluginName = "github" | "git";
|
||||
export function pluginNames(): PluginName[] {
|
||||
return ["github", "git"];
|
||||
}
|
||||
|
||||
export function defaultPlugins(): PluginName[] {
|
||||
return ["github", "git"];
|
||||
}
|
||||
|
||||
function defaultStorageDirectory() {
|
||||
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(),
|
||||
});
|
||||
}
|
||||
|
||||
export function nodeMaxOldSpaceSizeFlag() {
|
||||
return flags.integer({
|
||||
description: "--max_old_space_size flag to node; increases available heap",
|
||||
default: 8192,
|
||||
env: "SOURCECRED_NODE_MAX_OLD_SPACE",
|
||||
});
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
// @flow
|
||||
require("../tools/entry");
|
||||
require("@oclif/command")
|
||||
.run()
|
||||
.catch(require("@oclif/errors/handle"));
|
Loading…
Reference in New Issue