mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-21 08:48:14 +00:00
Give GitHub plugin support for Commit addresses (#816)
The Git plugin owns Commits, but the GitHub plugin also creates commits. This commit reifies that relationship by making a Git commit address a valid GitHub structured address. This is precursor work for #815, which will require adding a commit entity to the GitHub relational view. Also, this commit surfaces and fixes a minor type bug, wherein a map from strings to referent addresses was typed to hold any structured address, rather than just referent addresses. Test plan: The unit tests confirm that serializing/deserializing a Git commit address using the GitHub plugin's methods works as intended. Also, unit tests were added that verify that (de)serializing Git addresses for non-commit objects is still an error.
This commit is contained in:
parent
7dc9449fe7
commit
3e06c054db
@ -1,5 +1,20 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`plugins/github/nodes snapshots as expected: commit 1`] = `
|
||||||
|
Object {
|
||||||
|
"address": Array [
|
||||||
|
"sourcecred",
|
||||||
|
"git",
|
||||||
|
"COMMIT",
|
||||||
|
"0000000000000000000000000000000000000000",
|
||||||
|
],
|
||||||
|
"structured": Object {
|
||||||
|
"hash": "0000000000000000000000000000000000000000",
|
||||||
|
"type": "COMMIT",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`plugins/github/nodes snapshots as expected: issue 1`] = `
|
exports[`plugins/github/nodes snapshots as expected: issue 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"address": Array [
|
"address": Array [
|
||||||
|
@ -6,7 +6,7 @@ import deepEqual from "lodash.isequal";
|
|||||||
import * as GN from "./nodes";
|
import * as GN from "./nodes";
|
||||||
import * as GE from "./edges";
|
import * as GE from "./edges";
|
||||||
|
|
||||||
import {Prefix as _GitPrefix} from "../git/nodes";
|
import * as GitNode from "../git/nodes";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Graph,
|
Graph,
|
||||||
@ -143,6 +143,7 @@ export class GraphView {
|
|||||||
[GN.COMMENT_TYPE]: (x) => x.parent,
|
[GN.COMMENT_TYPE]: (x) => x.parent,
|
||||||
[GN.REVIEW_TYPE]: (x) => x.pull,
|
[GN.REVIEW_TYPE]: (x) => x.pull,
|
||||||
[GN.USERLIKE_TYPE]: null,
|
[GN.USERLIKE_TYPE]: null,
|
||||||
|
[GitNode.COMMIT_TYPE]: null,
|
||||||
};
|
};
|
||||||
for (const node of this._graph.nodes({prefix: GN.Prefix.base})) {
|
for (const node of this._graph.nodes({prefix: GN.Prefix.base})) {
|
||||||
const structuredNode = GN.fromRaw((node: any));
|
const structuredNode = GN.fromRaw((node: any));
|
||||||
@ -195,7 +196,7 @@ export class GraphView {
|
|||||||
homs: [
|
homs: [
|
||||||
{
|
{
|
||||||
srcPrefix: GN.Prefix.pull,
|
srcPrefix: GN.Prefix.pull,
|
||||||
dstPrefix: _GitPrefix.commit,
|
dstPrefix: GitNode.Prefix.commit,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
srcAccessor: (x) => GN.toRaw((x: any).pull),
|
srcAccessor: (x) => GN.toRaw((x: any).pull),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import {NodeAddress, type NodeAddressT} from "../../core/graph";
|
import {NodeAddress, type NodeAddressT} from "../../core/graph";
|
||||||
|
import * as GitNode from "../git/nodes";
|
||||||
|
|
||||||
export opaque type RawAddress: NodeAddressT = NodeAddressT;
|
export opaque type RawAddress: NodeAddressT = NodeAddressT;
|
||||||
|
|
||||||
@ -70,7 +71,8 @@ export type StructuredAddress =
|
|||||||
| PullAddress
|
| PullAddress
|
||||||
| ReviewAddress
|
| ReviewAddress
|
||||||
| CommentAddress
|
| CommentAddress
|
||||||
| UserlikeAddress;
|
| UserlikeAddress
|
||||||
|
| GitNode.CommitAddress;
|
||||||
|
|
||||||
// Each of these types has 0 or more "AUTHORS" edges, each of which
|
// Each of these types has 0 or more "AUTHORS" edges, each of which
|
||||||
// leads to a UserlikeAddress. Note: It is not true that every
|
// leads to a UserlikeAddress. Note: It is not true that every
|
||||||
@ -125,6 +127,14 @@ export function fromRaw(x: RawAddress): StructuredAddress {
|
|||||||
function fail() {
|
function fail() {
|
||||||
return new Error(`Bad address: ${NodeAddress.toString(x)}`);
|
return new Error(`Bad address: ${NodeAddress.toString(x)}`);
|
||||||
}
|
}
|
||||||
|
if (NodeAddress.hasPrefix(x, GitNode.Prefix.base)) {
|
||||||
|
const structured: GitNode.StructuredAddress = GitNode.fromRaw((x: any));
|
||||||
|
if (structured.type === GitNode.COMMIT_TYPE) {
|
||||||
|
return (structured: GitNode.CommitAddress);
|
||||||
|
} else {
|
||||||
|
throw fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!NodeAddress.hasPrefix(x, GITHUB_PREFIX)) {
|
if (!NodeAddress.hasPrefix(x, GITHUB_PREFIX)) {
|
||||||
throw fail();
|
throw fail();
|
||||||
}
|
}
|
||||||
@ -280,6 +290,8 @@ export function toRaw(x: StructuredAddress): RawAddress {
|
|||||||
default:
|
default:
|
||||||
throw new Error((x.subtype: empty));
|
throw new Error((x.subtype: empty));
|
||||||
}
|
}
|
||||||
|
case GitNode.COMMIT_TYPE:
|
||||||
|
return GitNode.toRaw(x);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unexpected type ${(x.type: empty)}`);
|
throw new Error(`Unexpected type ${(x.type: empty)}`);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import {NodeAddress} from "../../core/graph";
|
import {NodeAddress} from "../../core/graph";
|
||||||
import * as GN from "./nodes";
|
import * as GN from "./nodes";
|
||||||
import {fromRaw, toRaw} from "./nodes";
|
import {fromRaw, toRaw} from "./nodes";
|
||||||
|
import * as GitNode from "../git/nodes";
|
||||||
|
|
||||||
describe("plugins/github/nodes", () => {
|
describe("plugins/github/nodes", () => {
|
||||||
const repo = (): GN.RepoAddress => ({
|
const repo = (): GN.RepoAddress => ({
|
||||||
@ -45,6 +46,14 @@ describe("plugins/github/nodes", () => {
|
|||||||
subtype: "USER",
|
subtype: "USER",
|
||||||
login: "decentralion",
|
login: "decentralion",
|
||||||
});
|
});
|
||||||
|
const commit = (): GitNode.CommitAddress => ({
|
||||||
|
type: GitNode.COMMIT_TYPE,
|
||||||
|
hash: "0000000000000000000000000000000000000000",
|
||||||
|
});
|
||||||
|
const tree = (): GitNode.TreeAddress => ({
|
||||||
|
type: GitNode.TREE_TYPE,
|
||||||
|
hash: "0000000000000000000000000000000000000000",
|
||||||
|
});
|
||||||
|
|
||||||
const examples = {
|
const examples = {
|
||||||
repo,
|
repo,
|
||||||
@ -55,6 +64,7 @@ describe("plugins/github/nodes", () => {
|
|||||||
pullComment,
|
pullComment,
|
||||||
reviewComment,
|
reviewComment,
|
||||||
user,
|
user,
|
||||||
|
commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Incorrect types should be caught statically, either due to being
|
// Incorrect types should be caught statically, either due to being
|
||||||
@ -140,6 +150,10 @@ describe("plugins/github/nodes", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
expectBadAddress("no kind", []);
|
expectBadAddress("no kind", []);
|
||||||
|
expectBadAddress(
|
||||||
|
"Git node that isn't a commit",
|
||||||
|
NodeAddress.toParts(GitNode.toRaw(tree()))
|
||||||
|
);
|
||||||
describe("repository with", () => {
|
describe("repository with", () => {
|
||||||
checkBadCases([
|
checkBadCases([
|
||||||
{name: "no owner", parts: [GN.REPO_TYPE]},
|
{name: "no owner", parts: [GN.REPO_TYPE]},
|
||||||
@ -236,6 +250,12 @@ describe("plugins/github/nodes", () => {
|
|||||||
toRaw({type: "COMMENT", parent: {type: "ICE_CREAM"}});
|
toRaw({type: "COMMENT", parent: {type: "ICE_CREAM"}});
|
||||||
}).toThrow("Bad comment parent type");
|
}).toThrow("Bad comment parent type");
|
||||||
});
|
});
|
||||||
|
it("a git address that isn't a commit", () => {
|
||||||
|
expect(() => {
|
||||||
|
// $ExpectFlowError
|
||||||
|
toRaw(tree());
|
||||||
|
}).toThrow("Unexpected type");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -176,6 +176,8 @@ export class RelationalView {
|
|||||||
return this.comment(address);
|
return this.comment(address);
|
||||||
case "USERLIKE":
|
case "USERLIKE":
|
||||||
return this.userlike(address);
|
return this.userlike(address);
|
||||||
|
case "COMMIT":
|
||||||
|
return null;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unexpected address type: ${(address.type: empty)}`);
|
throw new Error(`Unexpected address type: ${(address.type: empty)}`);
|
||||||
}
|
}
|
||||||
@ -393,7 +395,7 @@ export class RelationalView {
|
|||||||
// https://github.com/sourcecred/sourcecred/pull/416
|
// https://github.com/sourcecred/sourcecred/pull/416
|
||||||
// - A # followed by a number, such as #416
|
// - A # followed by a number, such as #416
|
||||||
// - An @ followed by a login name, such as @decentralion
|
// - An @ followed by a login name, such as @decentralion
|
||||||
const refToAddress: Map<string, N.StructuredAddress> = new Map();
|
const refToAddress: Map<string, N.ReferentAddress> = new Map();
|
||||||
for (const e: ReferentEntity of this.referentEntities()) {
|
for (const e: ReferentEntity of this.referentEntities()) {
|
||||||
const a = e.address();
|
const a = e.address();
|
||||||
refToAddress.set(e.url(), a);
|
refToAddress.set(e.url(), a);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user