graph: add descriptions

This updates the graph `Node` type to include a string description.

The description should be a brief (ideally oneline) string giving
context on what the node is. All planned frontends will support
markdown, so linking to context (e.g. linking to the issue corresponding
to an ISSUE type node) is supported.

This commit updates the Git and GitHub plugins to use the new
description field.

Test plan: `yarn test --full` passes, and I've inspected snapshots and
made sure they look reasonable.
This commit is contained in:
Dandelion Mané 2019-07-04 11:24:24 +01:00
parent e7add05df5
commit 6c5e8b70d6
10 changed files with 102 additions and 28 deletions

View File

@ -1 +1 @@
[{"type":"sourcecred/graph","version":"0.5.0"},{"edges":[{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a","2","COMMIT","ec91adb718a6045b492303f00d8e8beb957dc780"],"dstIndex":4,"srcIndex":0},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a","2","COMMIT","ecc889dc94cf6da17ae6eab5bb7b7155f577519d"],"dstIndex":5,"srcIndex":0},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","6bd1b4c0b719c22c688a74863be07a699b7b9b34","2","COMMIT","c430bd74455105f77215ece51945094ceeee6c86"],"dstIndex":3,"srcIndex":1},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6","2","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a"],"dstIndex":0,"srcIndex":2},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","c430bd74455105f77215ece51945094ceeee6c86","2","COMMIT","6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6"],"dstIndex":2,"srcIndex":3},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","ecc889dc94cf6da17ae6eab5bb7b7155f577519d","2","COMMIT","ec91adb718a6045b492303f00d8e8beb957dc780"],"dstIndex":4,"srcIndex":5}],"nodes":[{"index":0},{"index":1},{"index":2},{"index":3},{"index":4},{"index":5}],"sortedNodeAddresses":[["sourcecred","git","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a"],["sourcecred","git","COMMIT","6bd1b4c0b719c22c688a74863be07a699b7b9b34"],["sourcecred","git","COMMIT","6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6"],["sourcecred","git","COMMIT","c430bd74455105f77215ece51945094ceeee6c86"],["sourcecred","git","COMMIT","ec91adb718a6045b492303f00d8e8beb957dc780"],["sourcecred","git","COMMIT","ecc889dc94cf6da17ae6eab5bb7b7155f577519d"]]}]
[{"type":"sourcecred/graph","version":"0.6.0"},{"edges":[{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a","2","COMMIT","ec91adb718a6045b492303f00d8e8beb957dc780"],"dstIndex":4,"srcIndex":0},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a","2","COMMIT","ecc889dc94cf6da17ae6eab5bb7b7155f577519d"],"dstIndex":5,"srcIndex":0},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","6bd1b4c0b719c22c688a74863be07a699b7b9b34","2","COMMIT","c430bd74455105f77215ece51945094ceeee6c86"],"dstIndex":3,"srcIndex":1},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6","2","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a"],"dstIndex":0,"srcIndex":2},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","c430bd74455105f77215ece51945094ceeee6c86","2","COMMIT","6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6"],"dstIndex":2,"srcIndex":3},{"address":["sourcecred","git","HAS_PARENT","2","COMMIT","ecc889dc94cf6da17ae6eab5bb7b7155f577519d","2","COMMIT","ec91adb718a6045b492303f00d8e8beb957dc780"],"dstIndex":4,"srcIndex":5}],"nodes":[{"description":"0a223346b4e6dec0127b1e6aa892c4ee0424b66a","index":0},{"description":"6bd1b4c0b719c22c688a74863be07a699b7b9b34","index":1},{"description":"6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6","index":2},{"description":"c430bd74455105f77215ece51945094ceeee6c86","index":3},{"description":"ec91adb718a6045b492303f00d8e8beb957dc780","index":4},{"description":"ecc889dc94cf6da17ae6eab5bb7b7155f577519d","index":5}],"sortedNodeAddresses":[["sourcecred","git","COMMIT","0a223346b4e6dec0127b1e6aa892c4ee0424b66a"],["sourcecred","git","COMMIT","6bd1b4c0b719c22c688a74863be07a699b7b9b34"],["sourcecred","git","COMMIT","6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6"],["sourcecred","git","COMMIT","c430bd74455105f77215ece51945094ceeee6c86"],["sourcecred","git","COMMIT","ec91adb718a6045b492303f00d8e8beb957dc780"],["sourcecred","git","COMMIT","ecc889dc94cf6da17ae6eab5bb7b7155f577519d"]]}]

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@ exports[`core/graph toJSON / fromJSON snapshot testing a graph with a dangling e
Array [
Object {
"type": "sourcecred/graph",
"version": "0.5.0",
"version": "0.6.0",
},
Object {
"edges": Array [
@ -33,7 +33,7 @@ exports[`core/graph toJSON / fromJSON snapshot testing a trivial graph 1`] = `
Array [
Object {
"type": "sourcecred/graph",
"version": "0.5.0",
"version": "0.6.0",
},
Object {
"edges": Array [
@ -54,9 +54,11 @@ Array [
],
"nodes": Array [
Object {
"description": "dst",
"index": 0,
},
Object {
"description": "src",
"index": 1,
},
],
@ -76,7 +78,7 @@ exports[`core/graph toJSON / fromJSON snapshot testing an advanced graph 1`] = `
Array [
Object {
"type": "sourcecred/graph",
"version": "0.5.0",
"version": "0.6.0",
},
Object {
"edges": Array [
@ -120,18 +122,23 @@ Array [
],
"nodes": Array [
Object {
"description": "dst",
"index": 0,
},
Object {
"description": "halfIsolated",
"index": 1,
},
Object {
"description": "isolated",
"index": 2,
},
Object {
"description": "loop",
"index": 3,
},
Object {
"description": "src",
"index": 5,
},
],

View File

@ -15,7 +15,7 @@ Array [
"graphJSON": Array [
Object {
"type": "sourcecred/graph",
"version": "0.5.0",
"version": "0.6.0",
},
Object {
"edges": Array [
@ -59,18 +59,23 @@ Array [
],
"nodes": Array [
Object {
"description": "dst",
"index": 0,
},
Object {
"description": "halfIsolated",
"index": 1,
},
Object {
"description": "isolated",
"index": 2,
},
Object {
"description": "loop",
"index": 3,
},
Object {
"description": "src",
"index": 5,
},
],

View File

@ -77,9 +77,11 @@ import * as NullUtil from "../util/null";
*
* ```js
* const prAddress = NodeAddress.fromParts(["pull_request", "1"]);
* const pr: Node = {address: prAddress}
* const prDescription = "My Fancy Pull Request"
* const pr: Node = {address: prAddress, description: prDescription}
* const myAddress = NodeAddress.fromParts(["user", "decentralion"]);
* const me: Node = {addess: myAddress}
* const myDescription = "@decentralion"
* const me: Node = {addess: myAddress, description: myDescription}
* const authoredAddress = EdgeAddress.fromParts(["authored", "pull_request", "1"]);
* const edge = {src: me, dst: pr, address: authoredAddress};
*
@ -121,6 +123,9 @@ export const EdgeAddress: AddressModule<EdgeAddressT> = (makeAddressModule({
*/
export type Node = {|
+address: NodeAddressT,
// Brief (ideally oneline) description for the node.
// Markdown is supported.
+description: string,
|};
/**
@ -132,7 +137,7 @@ export type Edge = {|
+dst: NodeAddressT,
|};
const COMPAT_INFO = {type: "sourcecred/graph", version: "0.5.0"};
const COMPAT_INFO = {type: "sourcecred/graph", version: "0.6.0"};
export type Neighbor = {|+node: Node, +edge: Edge|};
@ -170,6 +175,7 @@ type AddressJSON = string[]; // Result of calling {Node,Edge}Address.toParts
type Integer = number;
type IndexedNodeJSON = {|
+index: Integer,
+description: string,
|};
type IndexedEdgeJSON = {|
+address: AddressJSON,
@ -757,10 +763,12 @@ export class Graph {
}
);
const sortedNodes = sortBy(Array.from(this.nodes()), (x) => x.address);
const indexedNodes: IndexedNodeJSON[] = sortedNodes.map(({address}) => {
const index = NullUtil.get(nodeAddressToSortedIndex.get(address));
return {index};
});
const indexedNodes: IndexedNodeJSON[] = sortedNodes.map(
({address, description}) => {
const index = NullUtil.get(nodeAddressToSortedIndex.get(address));
return {index, description};
}
);
const rawJSON = {
sortedNodeAddresses: sortedNodeAddresses.map((x) =>
NodeAddress.toParts(x)
@ -787,7 +795,10 @@ export class Graph {
);
const result = new Graph();
nodesJSON.forEach((j: IndexedNodeJSON) => {
const n: Node = {address: sortedNodeAddresses[j.index]};
const n: Node = {
address: sortedNodeAddresses[j.index],
description: j.description,
};
result.addNode(n);
});
edgesJSON.forEach(({address, srcIndex, dstIndex}) => {

View File

@ -18,6 +18,7 @@ import {EdgeAddress, Graph, NodeAddress, type Node, type Edge} from "./graph";
export function partsNode(parts: string[]): Node {
return Object.freeze({
address: NodeAddress.fromParts(parts),
description: parts.toString(),
});
}

View File

@ -4,7 +4,7 @@ exports[`plugins/git/createGraph createGraph processes a simple repository 1`] =
Array [
Object {
"type": "sourcecred/graph",
"version": "0.5.0",
"version": "0.6.0",
},
Object {
"edges": Array [
@ -116,27 +116,35 @@ Array [
],
"nodes": Array [
Object {
"description": "3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
"index": 0,
},
Object {
"description": "69c5aad50eec8f2a0a07c988c3b283a6490eb45b",
"index": 1,
},
Object {
"description": "8d287c3bfbf8455ef30187bf5153ffc1b6eef268",
"index": 2,
},
Object {
"description": "c08ee3a4edea384d5291ffcbf06724a13ed72325",
"index": 3,
},
Object {
"description": "c2b51945e7457546912a8ce158ed9d294558d294",
"index": 4,
},
Object {
"description": "c90f6424017f787bbbaf22e4082a01355546f7e3",
"index": 5,
},
Object {
"description": "d160cca97611e9dfed642522ad44408d0292e8ea",
"index": 6,
},
Object {
"description": "e8b7a8f19701cd5a25e4a097d513ead60e5f8bcc",
"index": 7,
},
],

View File

@ -19,10 +19,6 @@ class GraphCreator {
this.graph = new Graph();
}
addNode(a: GN.StructuredAddress) {
this.graph.addNode({address: GN.toRaw(a)});
}
addRepository(repository: GT.Repository) {
for (const commitHash of Object.keys(repository.commits)) {
this.addCommit(repository.commits[commitHash]);
@ -30,11 +26,16 @@ class GraphCreator {
}
addCommit(commit: GT.Commit) {
const node: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: commit.hash};
this.graph.addNode({address: GN.toRaw(node)});
const structuredAddress: GN.CommitAddress = {
type: GN.COMMIT_TYPE,
hash: commit.hash,
};
const address = GN.toRaw(structuredAddress);
const description = commit.hash;
this.graph.addNode({address, description});
for (const parentHash of commit.parentHashes) {
const parent: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: parentHash};
this.graph.addEdge(GE.createEdge.hasParent(node, parent));
this.graph.addEdge(GE.createEdge.hasParent(structuredAddress, parent));
}
}
}

View File

@ -4,7 +4,7 @@ exports[`plugins/github/createGraph example graph matches snapshot 1`] = `
Array [
Object {
"type": "sourcecred/graph",
"version": "0.5.0",
"version": "0.6.0",
},
Object {
"edges": Array [
@ -2561,135 +2561,179 @@ Array [
],
"nodes": Array [
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/11#issuecomment-420811872) on [#11](https://github.com/sourcecred/example-github/issues/11): An issue with a comment from a deleted user",
"index": 6,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/11#issuecomment-420813013) on [#11](https://github.com/sourcecred/example-github/issues/11): An issue with a comment from a deleted user",
"index": 7,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/11#issuecomment-420813206) on [#11](https://github.com/sourcecred/example-github/issues/11): An issue with a comment from a deleted user",
"index": 8,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/11#issuecomment-420813621) on [#11](https://github.com/sourcecred/example-github/issues/11): An issue with a comment from a deleted user",
"index": 9,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-373768703) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 10,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-373768850) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 11,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-385576185) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 12,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-385576220) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 13,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-385576248) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 14,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-385576273) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 15,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-385576920) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 16,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/2#issuecomment-385576936) on [#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 17,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/6#issuecomment-373768442) on [#6](https://github.com/sourcecred/example-github/issues/6): An issue with comments",
"index": 18,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/6#issuecomment-373768538) on [#6](https://github.com/sourcecred/example-github/issues/6): An issue with comments",
"index": 19,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/6#issuecomment-385223316) on [#6](https://github.com/sourcecred/example-github/issues/6): An issue with comments",
"index": 20,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/issues/6#issuecomment-417104047) on [#6](https://github.com/sourcecred/example-github/issues/6): An issue with comments",
"index": 21,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/pull/3#issuecomment-369162222) on [#3](https://github.com/sourcecred/example-github/pull/3): Add README, merge via PR.",
"index": 22,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/pull/5#issuecomment-396430464) on [#5](https://github.com/sourcecred/example-github/pull/5): This pull request will be more contentious. I can feel it...",
"index": 23,
},
Object {
"description": "[comment](https://github.com/sourcecred/example-github/pull/5#discussion_r171460198) on [review](https://github.com/sourcecred/example-github/pull/5#pullrequestreview-100313899) on [#5](https://github.com/sourcecred/example-github/pull/5): This pull request will be more contentious. I can feel it...",
"index": 24,
},
Object {
"description": "[0a22334](https://github.com/sourcecred/example-github/commit/0a223346b4e6dec0127b1e6aa892c4ee0424b66a): Merge pull request #3 from sourcecred/add-readme",
"index": 25,
},
Object {
"description": "[6bd1b4c](https://github.com/sourcecred/example-github/commit/6bd1b4c0b719c22c688a74863be07a699b7b9b34): A commit from someone with no GitHub account",
"index": 26,
},
Object {
"description": "[6d5b3aa](https://github.com/sourcecred/example-github/commit/6d5b3aa31ebb68a06ceb46bbd6cf49b6ccd6f5e6): This pull request will be more contentious. I can feel it... (#5)",
"index": 27,
},
Object {
"description": "[c430bd7](https://github.com/sourcecred/example-github/commit/c430bd74455105f77215ece51945094ceeee6c86): Hello from credbot!",
"index": 28,
},
Object {
"description": "[ec91adb](https://github.com/sourcecred/example-github/commit/ec91adb718a6045b492303f00d8e8beb957dc780): Commit without pull request.",
"index": 29,
},
Object {
"description": "[ecc889d](https://github.com/sourcecred/example-github/commit/ecc889dc94cf6da17ae6eab5bb7b7155f577519d): Add README, merge via PR.",
"index": 30,
},
Object {
"description": "[#1](https://github.com/sourcecred/example-github/issues/1): An example issue.",
"index": 31,
},
Object {
"description": "[#10](https://github.com/sourcecred/example-github/issues/10): Paired with multireference",
"index": 32,
},
Object {
"description": "[#11](https://github.com/sourcecred/example-github/issues/11): An issue with a comment from a deleted user",
"index": 33,
},
Object {
"description": "[#12](https://github.com/sourcecred/example-github/issues/12): An issue with commit references",
"index": 34,
},
Object {
"description": "[#13](https://github.com/sourcecred/example-github/issues/13): An issue with reactions",
"index": 35,
},
Object {
"description": "[#2](https://github.com/sourcecred/example-github/issues/2): A referencing issue.",
"index": 36,
},
Object {
"description": "[#4](https://github.com/sourcecred/example-github/issues/4): A closed pull request",
"index": 37,
},
Object {
"description": "[#6](https://github.com/sourcecred/example-github/issues/6): An issue with comments",
"index": 38,
},
Object {
"description": "[#7](https://github.com/sourcecred/example-github/issues/7): An issue with an extremely long title, which even has a VerySuperFragicalisticialiManyCharacterUberLongTriplePlusGood word in it, and should really be truncated intelligently or something",
"index": 39,
},
Object {
"description": "[#8](https://github.com/sourcecred/example-github/issues/8): Issue with Unicode: ȴሲ𣐳楢👍 :heart: 𐤔𐤁𐤀𐤑𐤍𐤉𐤔𐤌𐤄𐤍𐤍 ❤️",
"index": 40,
},
Object {
"description": "[#3](https://github.com/sourcecred/example-github/pull/3): Add README, merge via PR.",
"index": 41,
},
Object {
"description": "[#5](https://github.com/sourcecred/example-github/pull/5): This pull request will be more contentious. I can feel it...",
"index": 42,
},
Object {
"description": "[#9](https://github.com/sourcecred/example-github/pull/9): An unmerged pull request",
"index": 43,
},
Object {
"description": "[sourcecred/example-github](https://github.com/sourcecred/example-github)",
"index": 44,
},
Object {
"description": "[review](https://github.com/sourcecred/example-github/pull/5#pullrequestreview-100313899) on [#5](https://github.com/sourcecred/example-github/pull/5): This pull request will be more contentious. I can feel it...",
"index": 45,
},
Object {
"description": "[review](https://github.com/sourcecred/example-github/pull/5#pullrequestreview-100314038) on [#5](https://github.com/sourcecred/example-github/pull/5): This pull request will be more contentious. I can feel it...",
"index": 46,
},
Object {
"description": "[@credbot](https://github.com/credbot)",
"index": 47,
},
Object {
"description": "[@decentralion](https://github.com/decentralion)",
"index": 48,
},
Object {
"description": "[@wchargin](https://github.com/wchargin)",
"index": 49,
},
],

View File

@ -22,7 +22,8 @@ class GraphCreator {
addData(view: R.RelationalView) {
for (const entity of view.entities()) {
this.addNode(entity.address());
const address = N.toRaw(entity.address());
this.graph.addNode({address, description: entity.description()});
}
for (const child of view.childEntities()) {
@ -75,10 +76,6 @@ class GraphCreator {
}
}
addNode(addr: N.StructuredAddress) {
this.graph.addNode({address: N.toRaw(addr)});
}
addAuthors(entity: R.AuthoredEntity) {
for (const author of entity.authors()) {
this.graph.addEdge(