Add `createMinimalGraph` for a tiny git graph (#689)
This implements the approach suggested in [1]. Instead of forking the git plugin entirely, we'll fork the createGraph method and the pluginAdapter so that we have instances that produce a lightweight git graph. createMinimalGraph is a fork of createGraph that only adds commit nodes and has_parent edges. New unit tests ensure that only the whitelisted nodes and edges appear. Supersedes #683 and #684. Test plan: `yarn test` [1]: https://github.com/sourcecred/sourcecred/issues/627#issuecomment-413623784
This commit is contained in:
parent
ae6e269d9d
commit
a460704ea8
|
@ -0,0 +1,148 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`plugins/git/createMinimalGraph createMinimalGraph processes a simple repository 1`] = `
|
||||||
|
Array [
|
||||||
|
Object {
|
||||||
|
"type": "sourcecred/graph",
|
||||||
|
"version": "0.4.0",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"edges": Array [
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"HAS_PARENT",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"69c5aad50eec8f2a0a07c988c3b283a6490eb45b",
|
||||||
|
],
|
||||||
|
"dstIndex": 1,
|
||||||
|
"srcIndex": 0,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"HAS_PARENT",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"69c5aad50eec8f2a0a07c988c3b283a6490eb45b",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"e8b7a8f19701cd5a25e4a097d513ead60e5f8bcc",
|
||||||
|
],
|
||||||
|
"dstIndex": 6,
|
||||||
|
"srcIndex": 1,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"HAS_PARENT",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"8d287c3bfbf8455ef30187bf5153ffc1b6eef268",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"c08ee3a4edea384d5291ffcbf06724a13ed72325",
|
||||||
|
],
|
||||||
|
"dstIndex": 3,
|
||||||
|
"srcIndex": 2,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"HAS_PARENT",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"c08ee3a4edea384d5291ffcbf06724a13ed72325",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"c2b51945e7457546912a8ce158ed9d294558d294",
|
||||||
|
],
|
||||||
|
"dstIndex": 4,
|
||||||
|
"srcIndex": 3,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"HAS_PARENT",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"d160cca97611e9dfed642522ad44408d0292e8ea",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"8d287c3bfbf8455ef30187bf5153ffc1b6eef268",
|
||||||
|
],
|
||||||
|
"dstIndex": 2,
|
||||||
|
"srcIndex": 5,
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"HAS_PARENT",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"e8b7a8f19701cd5a25e4a097d513ead60e5f8bcc",
|
||||||
|
"2",
|
||||||
|
"COMMIT",
|
||||||
|
"d160cca97611e9dfed642522ad44408d0292e8ea",
|
||||||
|
],
|
||||||
|
"dstIndex": 5,
|
||||||
|
"srcIndex": 6,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"nodes": Array [
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"69c5aad50eec8f2a0a07c988c3b283a6490eb45b",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"8d287c3bfbf8455ef30187bf5153ffc1b6eef268",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"c08ee3a4edea384d5291ffcbf06724a13ed72325",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"c2b51945e7457546912a8ce158ed9d294558d294",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"d160cca97611e9dfed642522ad44408d0292e8ea",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"e8b7a8f19701cd5a25e4a097d513ead60e5f8bcc",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
`;
|
|
@ -0,0 +1,41 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import {Graph} from "../../core/graph";
|
||||||
|
|
||||||
|
import * as GT from "./types";
|
||||||
|
import * as GN from "./nodes";
|
||||||
|
import * as GE from "./edges";
|
||||||
|
|
||||||
|
export function createMinimalGraph(repository: GT.Repository): Graph {
|
||||||
|
const creator = new MinimalGraphCreator();
|
||||||
|
creator.addRepository(repository);
|
||||||
|
return creator.graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MinimalGraphCreator {
|
||||||
|
+graph: Graph;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.graph = new Graph();
|
||||||
|
}
|
||||||
|
|
||||||
|
addNode(a: GN.StructuredAddress) {
|
||||||
|
this.graph.addNode(GN.toRaw(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
addRepository(repository: GT.Repository) {
|
||||||
|
for (const commitHash of Object.keys(repository.commits)) {
|
||||||
|
this.addCommit(repository.commits[commitHash]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addCommit(commit: GT.Commit) {
|
||||||
|
const node: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: commit.hash};
|
||||||
|
this.graph.addNode(GN.toRaw(node));
|
||||||
|
for (const parentHash of commit.parentHashes) {
|
||||||
|
const parent: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: parentHash};
|
||||||
|
this.graph.addNode(GN.toRaw(parent));
|
||||||
|
this.graph.addEdge(GE.createEdge.hasParent(node, parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import cloneDeep from "lodash.clonedeep";
|
||||||
|
|
||||||
|
import {createMinimalGraph} from "./createMinimalGraph";
|
||||||
|
import {GraphView} from "./graphView";
|
||||||
|
import {_Prefix as NodePrefix} from "./nodes";
|
||||||
|
import {_Prefix as EdgePrefix} from "./edges";
|
||||||
|
import {NodeAddress, EdgeAddress} from "../../core/graph";
|
||||||
|
|
||||||
|
const makeData = () => cloneDeep(require("./example/example-git"));
|
||||||
|
|
||||||
|
describe("plugins/git/createMinimalGraph", () => {
|
||||||
|
describe("createMinimalGraph", () => {
|
||||||
|
it("processes a simple repository", () => {
|
||||||
|
expect(createMinimalGraph(makeData())).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("satisfies the GraphView invariants", () => {
|
||||||
|
const graph = createMinimalGraph(makeData());
|
||||||
|
expect(() => new GraphView(graph)).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("only has commit nodes and has_parent edges", () => {
|
||||||
|
const graph = createMinimalGraph(makeData());
|
||||||
|
for (const n of graph.nodes()) {
|
||||||
|
if (!NodeAddress.hasPrefix(n, NodePrefix.commit)) {
|
||||||
|
throw new Error("Found non-commit node");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const {address} of graph.edges()) {
|
||||||
|
if (!EdgeAddress.hasPrefix(address, EdgePrefix.hasParent)) {
|
||||||
|
throw new Error("Found non-has-parent edge");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue