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:
Dandelion Mané 2018-08-16 11:38:36 -07:00 committed by GitHub
parent ae6e269d9d
commit a460704ea8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 227 additions and 0 deletions

View File

@ -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",
],
],
},
]
`;

View File

@ -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));
}
}
}

View File

@ -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");
}
}
});
});
});