Add GitPluginAdapter and Git render module (#462)
Test plan: Run the following commands: ``` node bin/sourcecredV3.js load-plugin-v3 sourcecred example-github --plugin=git node bin/sourcecredV3.js load-plugin-v3 sourcecred example-github --plugin=github yarn start ``` Then, navigate in-browser to the v3 cred explorer and load data for `sourcecred/example-github`. The following messages are printed to console: ``` GitHub: Loaded graph: 31 nodes, 73 edges. Git: Loaded graph: 15 nodes, 19 edges. Combined: Loaded graph: 44 nodes, 92 edges. ``` Paired with @wchargin
This commit is contained in:
parent
4767dce749
commit
dd063f5203
|
@ -5,6 +5,8 @@ import {StyleSheet, css} from "aphrodite/no-important";
|
|||
|
||||
import LocalStore from "./LocalStore";
|
||||
import {createPluginAdapter as createGithubAdapter} from "../../plugins/github/pluginAdapter";
|
||||
import {createPluginAdapter as createGitAdapter} from "../../plugins/git/pluginAdapter";
|
||||
import {Graph} from "../../core/graph";
|
||||
|
||||
type Props = {};
|
||||
type State = {
|
||||
|
@ -82,11 +84,38 @@ export default class App extends React.Component<Props, State> {
|
|||
console.error(`Invalid repository name: ${JSON.stringify(repoName)}`);
|
||||
return;
|
||||
}
|
||||
createGithubAdapter(repoOwner, repoName).then((githubAdapter) => {
|
||||
const graph = githubAdapter.graph();
|
||||
|
||||
const githubGraphPromise = createGithubAdapter(repoOwner, repoName).then(
|
||||
(githubAdapter) => {
|
||||
const graph = githubAdapter.graph();
|
||||
const nodeCount = Array.from(graph.nodes()).length;
|
||||
const edgeCount = Array.from(graph.edges()).length;
|
||||
console.log(
|
||||
`GitHub: Loaded graph: ${nodeCount} nodes, ${edgeCount} edges.`
|
||||
);
|
||||
return graph;
|
||||
}
|
||||
);
|
||||
|
||||
const gitGraphPromise = createGitAdapter(repoOwner, repoName).then(
|
||||
(gitAdapter) => {
|
||||
const graph = gitAdapter.graph();
|
||||
const nodeCount = Array.from(graph.nodes()).length;
|
||||
const edgeCount = Array.from(graph.edges()).length;
|
||||
console.log(
|
||||
`Git: Loaded graph: ${nodeCount} nodes, ${edgeCount} edges.`
|
||||
);
|
||||
return graph;
|
||||
}
|
||||
);
|
||||
|
||||
Promise.all([gitGraphPromise, githubGraphPromise]).then((graphs) => {
|
||||
const graph = Graph.merge(graphs);
|
||||
const nodeCount = Array.from(graph.nodes()).length;
|
||||
const edgeCount = Array.from(graph.edges()).length;
|
||||
console.log(`Loaded graph: ${nodeCount} nodes, ${edgeCount} edges.`);
|
||||
console.log(
|
||||
`Combined: Loaded graph: ${nodeCount} nodes, ${edgeCount} edges.`
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`plugins/git/render blob snapshots as expected 1`] = `"blob f1f2514ca6d7a6a1a0511957021b1995bf9ace1c"`;
|
||||
|
||||
exports[`plugins/git/render commit snapshots as expected 1`] = `"commit 3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f"`;
|
||||
|
||||
exports[`plugins/git/render tree snapshots as expected 1`] = `"tree 7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed"`;
|
||||
|
||||
exports[`plugins/git/render treeEntry snapshots as expected 1`] = `"entry \\"science.txt\\" in tree 7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed"`;
|
|
@ -0,0 +1,47 @@
|
|||
// @flow
|
||||
import type {
|
||||
PluginAdapter as IPluginAdapter,
|
||||
Renderer as IRenderer,
|
||||
} from "../../app/pluginAdapter";
|
||||
import {Graph} from "../../core/graph";
|
||||
import * as N from "./nodes";
|
||||
import {description} from "./render";
|
||||
|
||||
export async function createPluginAdapter(
|
||||
repoOwner: string,
|
||||
repoName: string
|
||||
): Promise<IPluginAdapter> {
|
||||
const url = `/api/v1/data/data/${repoOwner}/${repoName}/git/graph.json`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
return Promise.reject(response);
|
||||
}
|
||||
const json = await response.json();
|
||||
const graph = Graph.fromJSON(json);
|
||||
return new PluginAdapter(graph);
|
||||
}
|
||||
|
||||
class PluginAdapter implements IPluginAdapter {
|
||||
+_graph: Graph;
|
||||
constructor(graph: Graph) {
|
||||
this._graph = graph;
|
||||
}
|
||||
graph() {
|
||||
return this._graph;
|
||||
}
|
||||
renderer() {
|
||||
return new Renderer();
|
||||
}
|
||||
nodePrefix() {
|
||||
return N._Prefix.base;
|
||||
}
|
||||
}
|
||||
|
||||
class Renderer implements IRenderer {
|
||||
nodeDescription(node) {
|
||||
// This cast is unsound, and might throw at runtime, but won't have
|
||||
// silent failures or cause problems down the road.
|
||||
const address = N.fromRaw((node: any));
|
||||
return description(address);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
// @flow
|
||||
|
||||
import * as N from "./nodes";
|
||||
|
||||
export function description(address: N.StructuredAddress) {
|
||||
switch (address.type) {
|
||||
case "COMMIT":
|
||||
return `commit ${address.hash}`;
|
||||
case "TREE":
|
||||
return `tree ${address.hash}`;
|
||||
case "BLOB":
|
||||
return `blob ${address.hash}`;
|
||||
case "TREE_ENTRY":
|
||||
return `entry ${JSON.stringify(address.name)} in tree ${
|
||||
address.treeHash
|
||||
}`;
|
||||
default:
|
||||
throw new Error(`unknown type: ${(address.type: empty)}`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// @flow
|
||||
|
||||
import * as GN from "./nodes";
|
||||
import {description} from "./render";
|
||||
|
||||
describe("plugins/git/render", () => {
|
||||
const examples = {
|
||||
blob: (): GN.BlobAddress => ({
|
||||
type: GN.BLOB_TYPE,
|
||||
hash: "f1f2514ca6d7a6a1a0511957021b1995bf9ace1c",
|
||||
}),
|
||||
commit: (): GN.CommitAddress => ({
|
||||
type: GN.COMMIT_TYPE,
|
||||
hash: "3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
|
||||
}),
|
||||
tree: (): GN.TreeAddress => ({
|
||||
type: GN.TREE_TYPE,
|
||||
hash: "7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
|
||||
}),
|
||||
treeEntry: (): GN.TreeEntryAddress => ({
|
||||
type: GN.TREE_ENTRY_TYPE,
|
||||
treeHash: "7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
|
||||
name: "science.txt",
|
||||
}),
|
||||
};
|
||||
it("blob snapshots as expected", () => {
|
||||
expect(description(examples.blob())).toMatchSnapshot();
|
||||
});
|
||||
it("commit snapshots as expected", () => {
|
||||
expect(description(examples.commit())).toMatchSnapshot();
|
||||
});
|
||||
it("tree snapshots as expected", () => {
|
||||
expect(description(examples.tree())).toMatchSnapshot();
|
||||
});
|
||||
it("treeEntry snapshots as expected", () => {
|
||||
expect(description(examples.treeEntry())).toMatchSnapshot();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue