Remove git adresses for trees, blobs, and entries (#877)

In #873 I removed the data types for trees, blobs, and entries, but
neglected to remove the address related code. This commit corrects that
mistake. Some test cases in other modules have been removed because the
failure is now structurally impossible, e.g. it is not possible that we
would provide a non-commit address to the GitHub plugin, because
non-commit addresses do not exist.

Test plan: `yarn test --full` passes.
This commit is contained in:
Dandelion Mané 2018-09-20 15:18:01 -07:00 committed by GitHub
parent 1dd8b7bcb7
commit 5348fe68bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 5 additions and 626 deletions

View File

@ -1,64 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`plugins/git/edges createEdge works for "becomes" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"git",
"BECOMES",
"3",
"TREE_ENTRY",
"de07d6d2b2977734cf39d2b9aff4135eefce3eb7",
"old_science.txt",
"3",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
"dstParts": Array [
"sourcecred",
"git",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
"srcParts": Array [
"sourcecred",
"git",
"TREE_ENTRY",
"de07d6d2b2977734cf39d2b9aff4135eefce3eb7",
"old_science.txt",
],
}
`;
exports[`plugins/git/edges createEdge works for "hasContents" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"git",
"HAS_CONTENTS",
"3",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
"dstParts": Array [
"sourcecred",
"git",
"BLOB",
"f1f2514ca6d7a6a1a0511957021b1995bf9ace1c",
],
"srcParts": Array [
"sourcecred",
"git",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
}
`;
exports[`plugins/git/edges createEdge works for "hasParent" 1`] = `
Object {
"addressParts": Array [
@ -86,55 +27,3 @@ Object {
],
}
`;
exports[`plugins/git/edges createEdge works for "hasTree" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"git",
"HAS_TREE",
"2",
"COMMIT",
"3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
],
"dstParts": Array [
"sourcecred",
"git",
"TREE",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
],
"srcParts": Array [
"sourcecred",
"git",
"COMMIT",
"3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
],
}
`;
exports[`plugins/git/edges createEdge works for "includes" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"git",
"INCLUDES",
"3",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
"dstParts": Array [
"sourcecred",
"git",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
"srcParts": Array [
"sourcecred",
"git",
"TREE",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
],
}
`;

View File

@ -1,20 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`plugins/git/nodes snapshots as expected: blob 1`] = `
Object {
"address": Array [
"sourcecred",
"git",
"BLOB",
"f1f2514ca6d7a6a1a0511957021b1995bf9ace1c",
],
"structured": Object {
"hash": "f1f2514ca6d7a6a1a0511957021b1995bf9ace1c",
"type": "BLOB",
},
}
`;
exports[`plugins/git/nodes snapshots as expected: commit 1`] = `
Object {
"address": Array [
@ -29,35 +14,3 @@ Object {
},
}
`;
exports[`plugins/git/nodes snapshots as expected: tree 1`] = `
Object {
"address": Array [
"sourcecred",
"git",
"TREE",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
],
"structured": Object {
"hash": "7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"type": "TREE",
},
}
`;
exports[`plugins/git/nodes snapshots as expected: treeEntry 1`] = `
Object {
"address": Array [
"sourcecred",
"git",
"TREE_ENTRY",
"7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"science.txt",
],
"structured": Object {
"name": "science.txt",
"treeHash": "7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
"type": "TREE_ENTRY",
},
}
`;

View File

@ -1,9 +1,3 @@
// 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"`;

View File

@ -23,52 +23,18 @@ function gitEdgeAddress(...parts: string[]): RawAddress {
export const Prefix = Object.freeze({
base: GIT_PREFIX,
hasTree: gitEdgeAddress(HAS_TREE_TYPE),
hasParent: gitEdgeAddress(HAS_PARENT_TYPE),
includes: gitEdgeAddress(INCLUDES_TYPE),
becomes: gitEdgeAddress(BECOMES_TYPE),
hasContents: gitEdgeAddress(HAS_CONTENTS_TYPE),
});
export type HasTreeAddress = {|
type: typeof HAS_TREE_TYPE,
commit: GitNode.CommitAddress,
|};
export type HasParentAddress = {|
type: typeof HAS_PARENT_TYPE,
child: GitNode.CommitAddress,
parent: GitNode.CommitAddress,
|};
export type IncludesAddress = {|
type: typeof INCLUDES_TYPE,
treeEntry: GitNode.TreeEntryAddress,
|};
export type BecomesAddress = {|
type: typeof BECOMES_TYPE,
was: GitNode.TreeEntryAddress,
becomes: GitNode.TreeEntryAddress,
|};
export type HasContentsAddress = {|
type: typeof HAS_CONTENTS_TYPE,
treeEntry: GitNode.TreeEntryAddress,
|};
export type StructuredAddress =
| HasTreeAddress
| HasParentAddress
| IncludesAddress
| BecomesAddress
| HasContentsAddress;
export type StructuredAddress = HasParentAddress;
export const createEdge = Object.freeze({
hasTree: (
commit: GitNode.CommitAddress,
tree: GitNode.TreeAddress
): Edge => ({
address: toRaw({type: HAS_TREE_TYPE, commit}),
src: GitNode.toRaw(commit),
dst: GitNode.toRaw(tree),
}),
hasParent: (
child: GitNode.CommitAddress,
parent: GitNode.CommitAddress
@ -77,30 +43,6 @@ export const createEdge = Object.freeze({
src: GitNode.toRaw(child),
dst: GitNode.toRaw(parent),
}),
includes: (
tree: GitNode.TreeAddress,
treeEntry: GitNode.TreeEntryAddress
): Edge => ({
address: toRaw({type: INCLUDES_TYPE, treeEntry}),
src: GitNode.toRaw(tree),
dst: GitNode.toRaw(treeEntry),
}),
becomes: (
was: GitNode.TreeEntryAddress,
becomes: GitNode.TreeEntryAddress
): Edge => ({
address: toRaw({type: BECOMES_TYPE, was, becomes}),
src: GitNode.toRaw(was),
dst: GitNode.toRaw(becomes),
}),
hasContents: (
treeEntry: GitNode.TreeEntryAddress,
contents: GitNode.TreeEntryContentsAddress
): Edge => ({
address: toRaw({type: HAS_CONTENTS_TYPE, treeEntry}),
src: GitNode.toRaw(treeEntry),
dst: GitNode.toRaw(contents),
}),
});
const NODE_PREFIX_LENGTH = NodeAddress.toParts(GitNode._gitAddress()).length;
@ -149,15 +91,6 @@ export function fromRaw(x: RawAddress): StructuredAddress {
const [_unused_sc, _unused_git, _type, ...rest] = EdgeAddress.toParts(x);
const type: $ElementType<StructuredAddress, "type"> = (_type: any);
switch (type) {
case "HAS_TREE": {
const parts = multiLengthDecode(rest, fail);
if (parts.length !== 1) throw fail();
const [commitParts] = parts;
const commit: GitNode.CommitAddress = (GitNode.fromRaw(
GitNode._gitAddress(...commitParts)
): any);
return {type: HAS_TREE_TYPE, commit};
}
case "HAS_PARENT": {
const parts = multiLengthDecode(rest, fail);
if (parts.length !== 2) throw fail();
@ -170,36 +103,6 @@ export function fromRaw(x: RawAddress): StructuredAddress {
): any);
return {type: HAS_PARENT_TYPE, child, parent};
}
case "INCLUDES": {
const parts = multiLengthDecode(rest, fail);
if (parts.length !== 1) throw fail();
const [treeEntryParts] = parts;
const treeEntry: GitNode.TreeEntryAddress = (GitNode.fromRaw(
GitNode._gitAddress(...treeEntryParts)
): any);
return {type: INCLUDES_TYPE, treeEntry};
}
case "BECOMES": {
const parts = multiLengthDecode(rest, fail);
if (parts.length !== 2) throw fail();
const [wasParts, becomesParts] = parts;
const was: GitNode.TreeEntryAddress = (GitNode.fromRaw(
GitNode._gitAddress(...wasParts)
): any);
const becomes: GitNode.TreeEntryAddress = (GitNode.fromRaw(
GitNode._gitAddress(...becomesParts)
): any);
return {type: BECOMES_TYPE, was, becomes};
}
case "HAS_CONTENTS": {
const parts = multiLengthDecode(rest, fail);
if (parts.length !== 1) throw fail();
const [treeEntryParts] = parts;
const treeEntry: GitNode.TreeEntryAddress = (GitNode.fromRaw(
GitNode._gitAddress(...treeEntryParts)
): any);
return {type: HAS_CONTENTS_TYPE, treeEntry};
}
default:
// eslint-disable-next-line no-unused-expressions
(type: empty);
@ -209,33 +112,12 @@ export function fromRaw(x: RawAddress): StructuredAddress {
export function toRaw(x: StructuredAddress): RawAddress {
switch (x.type) {
case HAS_TREE_TYPE:
return EdgeAddress.append(
Prefix.hasTree,
...lengthEncode(GitNode.toRaw(x.commit))
);
case HAS_PARENT_TYPE:
return EdgeAddress.append(
Prefix.hasParent,
...lengthEncode(GitNode.toRaw(x.child)),
...lengthEncode(GitNode.toRaw(x.parent))
);
case INCLUDES_TYPE:
return EdgeAddress.append(
Prefix.includes,
...lengthEncode(GitNode.toRaw(x.treeEntry))
);
case BECOMES_TYPE:
return EdgeAddress.append(
Prefix.becomes,
...lengthEncode(GitNode.toRaw(x.was)),
...lengthEncode(GitNode.toRaw(x.becomes))
);
case HAS_CONTENTS_TYPE:
return EdgeAddress.append(
Prefix.hasContents,
...lengthEncode(GitNode.toRaw(x.treeEntry))
);
default:
throw new Error((x.type: empty));
}

View File

@ -7,10 +7,6 @@ import * as GN from "./nodes";
describe("plugins/git/edges", () => {
const nodeExamples = {
blob: (): GN.BlobAddress => ({
type: GN.BLOB_TYPE,
hash: "f1f2514ca6d7a6a1a0511957021b1995bf9ace1c",
}),
commit: (): GN.CommitAddress => ({
type: GN.COMMIT_TYPE,
hash: "3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
@ -19,33 +15,11 @@ describe("plugins/git/edges", () => {
type: GN.COMMIT_TYPE,
hash: "69c5aad50eec8f2a0a07c988c3b283a6490eb45b",
}),
tree: (): GN.TreeAddress => ({
type: GN.TREE_TYPE,
hash: "7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
}),
treeEntry: (): GN.TreeEntryAddress => ({
type: GN.TREE_ENTRY_TYPE,
treeHash: "7be3ecfee5314ffa9b2d93fc4377792b2d6d70ed",
name: "science.txt",
}),
oldTreeEntry: (): GN.TreeEntryAddress => ({
type: GN.TREE_ENTRY_TYPE,
treeHash: "de07d6d2b2977734cf39d2b9aff4135eefce3eb7",
name: "old_science.txt",
}),
};
const edgeExamples = {
hasTree: () =>
createEdge.hasTree(nodeExamples.commit(), nodeExamples.tree()),
hasParent: () =>
createEdge.hasParent(nodeExamples.commit(), nodeExamples.parentCommit()),
includes: () =>
createEdge.includes(nodeExamples.tree(), nodeExamples.treeEntry()),
becomes: () =>
createEdge.becomes(nodeExamples.oldTreeEntry(), nodeExamples.treeEntry()),
hasContents: () =>
createEdge.hasContents(nodeExamples.treeEntry(), nodeExamples.blob()),
};
describe("createEdge", () => {

View File

@ -60,18 +60,6 @@ export class GraphView {
this._maybeCheckInvariants();
}
tree(commit: GN.CommitAddress): GN.TreeAddress {
const result: GN.TreeAddress = Array.from(
this._neighbors(commit, {
direction: Direction.OUT,
nodePrefix: GN.Prefix.tree,
edgePrefix: GE.Prefix.hasTree,
})
)[0];
this._maybeCheckInvariants();
return result;
}
parents(commit: GN.CommitAddress): Iterator<GN.CommitAddress> {
const result: Iterator<GN.CommitAddress> = this._neighbors(commit, {
direction: Direction.OUT,
@ -82,49 +70,6 @@ export class GraphView {
return result;
}
entries(tree: GN.TreeAddress): Iterator<GN.TreeEntryAddress> {
const result: Iterator<GN.TreeEntryAddress> = this._neighbors(tree, {
direction: Direction.OUT,
nodePrefix: GN.Prefix.treeEntry,
edgePrefix: GE.Prefix.includes,
});
this._maybeCheckInvariants();
return result;
}
contents(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryContentsAddress> {
const result: Iterator<GN.TreeEntryContentsAddress> = this._neighbors(
entry,
{
direction: Direction.OUT,
nodePrefix: GN.Prefix.base, // multiple kinds
edgePrefix: GE.Prefix.hasContents,
}
);
this._maybeCheckInvariants();
return result;
}
evolvesTo(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryAddress> {
const result: Iterator<GN.TreeEntryAddress> = this._neighbors(entry, {
direction: Direction.OUT,
nodePrefix: GN.Prefix.treeEntry,
edgePrefix: GE.Prefix.becomes,
});
this._maybeCheckInvariants();
return result;
}
evolvesFrom(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryAddress> {
const result: Iterator<GN.TreeEntryAddress> = this._neighbors(entry, {
direction: Direction.IN,
nodePrefix: GN.Prefix.treeEntry,
edgePrefix: GE.Prefix.becomes,
});
this._maybeCheckInvariants();
return result;
}
_maybeCheckInvariants() {
if (process.env.NODE_ENV === "test") {
// TODO(perf): If this method becomes really slow, we can disable
@ -149,32 +94,10 @@ export class GraphView {
|}>,
|};
const edgeInvariants = {
[GE.HAS_TREE_TYPE]: {
prefix: GE.Prefix.hasTree,
homs: [{srcPrefix: GN.Prefix.commit, dstPrefix: GN.Prefix.tree}],
},
[GE.HAS_PARENT_TYPE]: {
prefix: GE.Prefix.hasParent,
homs: [{srcPrefix: GN.Prefix.commit, dstPrefix: GN.Prefix.commit}],
},
[GE.INCLUDES_TYPE]: {
prefix: GE.Prefix.includes,
homs: [{srcPrefix: GN.Prefix.tree, dstPrefix: GN.Prefix.treeEntry}],
},
[GE.BECOMES_TYPE]: {
prefix: GE.Prefix.becomes,
homs: [
{srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.treeEntry},
],
},
[GE.HAS_CONTENTS_TYPE]: {
prefix: GE.Prefix.hasContents,
homs: [
{srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.blob},
{srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.tree},
{srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.commit},
],
},
};
for (const edge of this._graph.edges({
@ -202,30 +125,6 @@ export class GraphView {
}
}
// Any HAS_TREE edge to a commit must be properly named. This
// implies that a commit has at most one such edge. (Normal commits
// should have trees, but submodule commits might not.)
for (const rawNode of this._graph.nodes({prefix: GN.Prefix.commit})) {
for (const neighbor of this._graph.neighbors(rawNode, {
direction: Direction.OUT,
nodePrefix: NodeAddress.empty,
edgePrefix: GE.Prefix.hasTree,
})) {
const rawEdge = neighbor.edge;
const edge: GE.HasTreeAddress = (GE.fromRaw(
(((rawEdge.address: EdgeAddressT): any): GE.RawAddress)
): any);
const node: GN.CommitAddress = ((GN.fromRaw(
(((rawNode: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
if (node.hash !== edge.commit.hash) {
throw new Error(
`invariant violation: bad HAS_TREE edge: ${edgeToString(rawEdge)}`
);
}
}
}
// All HAS_PARENT edges must map between between the correct commits.
for (const edge of this._graph.edges({
addressPrefix: GE.Prefix.hasParent,
@ -245,75 +144,5 @@ export class GraphView {
);
}
}
// Each tree entry must have a unique and properly named INCLUDES edge.
for (const rawNode of this._graph.nodes({prefix: GN.Prefix.treeEntry})) {
const treeNeighbors = Array.from(
this._graph.neighbors(rawNode, {
direction: Direction.IN,
nodePrefix: NodeAddress.empty,
edgePrefix: GE.Prefix.includes,
})
);
if (treeNeighbors.length !== 1) {
throw new Error(
"invariant violation: tree entry should have 1 inclusion, " +
`but has ${treeNeighbors.length}: ${NodeAddress.toString(rawNode)}`
);
}
const edge = treeNeighbors[0].edge;
const tree: GN.TreeAddress = ((GN.fromRaw(
(((edge.src: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
const treeEntry: GN.TreeEntryAddress = ((GN.fromRaw(
(((edge.dst: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
const expectedEdge = GE.createEdge.includes(tree, treeEntry);
if (edge.address !== expectedEdge.address) {
throw new Error(
`invariant violation: bad INCLUDES edge: ${edgeToString(edge)}`
);
}
}
// All BECOMES edges must map between between the correct tree entries.
for (const edge of this._graph.edges({
addressPrefix: GE.Prefix.becomes,
srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty,
})) {
const src: GN.TreeEntryAddress = ((GN.fromRaw(
(((edge.src: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
const dst: GN.TreeEntryAddress = ((GN.fromRaw(
(((edge.dst: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
const expectedEdge = GE.createEdge.becomes(src, dst);
if (edge.address !== expectedEdge.address) {
throw new Error(
`invariant violation: bad BECOMES edge: ${edgeToString(edge)}`
);
}
}
// All HAS_CONTENTS edges must be properly named.
for (const edge of this._graph.edges({
addressPrefix: GE.Prefix.hasContents,
srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty,
})) {
const src: GN.TreeEntryAddress = ((GN.fromRaw(
(((edge.src: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
const dst: GN.TreeEntryContentsAddress = ((GN.fromRaw(
(((edge.dst: NodeAddressT): any): GN.RawAddress)
): GN.StructuredAddress): any);
const expectedEdge = GE.createEdge.hasContents(src, dst);
if (edge.address !== expectedEdge.address) {
throw new Error(
`invariant violation: bad HAS_CONTENTS edge: ${edgeToString(edge)}`
);
}
}
}
}

View File

@ -78,18 +78,13 @@ describe("plugins/git/graphView", () => {
const c3: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: "c3"};
const e2 = GE.createEdge.hasParent(c1, c2);
const e3 = GE.createEdge.hasParent(c1, c3);
const tree: GN.TreeAddress = {type: GN.TREE_TYPE, hash: "t1"};
const foreignNode = NodeAddress.fromParts(["who", "are", "you"]);
const baseGraph = () =>
new Graph()
.addNode(foreignNode)
.addNode(GN.toRaw(c1))
.addNode(GN.toRaw(c2))
.addNode(GN.toRaw(c3))
.addNode(GN.toRaw(tree))
.addEdge(GE.createEdge.hasTree(c1, tree))
.addEdge(GE.createEdge.hasTree(c2, tree))
.addEdge(GE.createEdge.hasTree(c3, tree));
.addNode(GN.toRaw(c3));
it("for proper src", () => {
const badEdge = {...e2, src: foreignNode};
const g = baseGraph().addEdge(badEdge);

View File

@ -10,49 +10,19 @@ export function _gitAddress(...parts: string[]): RawAddress {
return NodeAddress.append(GIT_PREFIX, ...parts);
}
export const BLOB_TYPE: "BLOB" = "BLOB";
export const COMMIT_TYPE: "COMMIT" = "COMMIT";
export const TREE_TYPE: "TREE" = "TREE";
export const TREE_ENTRY_TYPE: "TREE_ENTRY" = "TREE_ENTRY";
export const Prefix = Object.freeze({
base: GIT_PREFIX,
blob: _gitAddress(BLOB_TYPE),
commit: _gitAddress(COMMIT_TYPE),
tree: _gitAddress(TREE_TYPE),
treeEntry: _gitAddress(TREE_ENTRY_TYPE),
});
export type BlobAddress = {|
+type: typeof BLOB_TYPE,
+hash: Hash,
|};
export type CommitAddress = {|
+type: typeof COMMIT_TYPE,
+hash: Hash,
|};
export type TreeAddress = {|
+type: typeof TREE_TYPE,
+hash: Hash,
|};
export type TreeEntryAddress = {|
+type: typeof TREE_ENTRY_TYPE,
+treeHash: Hash,
+name: string,
|};
// A tree entry has contents with one of the following types of
// addresses.
export type TreeEntryContentsAddress =
| BlobAddress
| CommitAddress
| TreeAddress;
export type StructuredAddress =
| BlobAddress
| CommitAddress
| TreeAddress
| TreeEntryAddress;
export type StructuredAddress = CommitAddress;
export function fromRaw(x: RawAddress): StructuredAddress {
function fail() {
@ -64,26 +34,11 @@ export function fromRaw(x: RawAddress): StructuredAddress {
const [_unused_sc, _unused_git, _type, ...rest] = NodeAddress.toParts(x);
const type: $ElementType<StructuredAddress, "type"> = (_type: any);
switch (type) {
case "BLOB": {
if (rest.length !== 1) throw fail();
const [hash] = rest;
return {type: BLOB_TYPE, hash};
}
case "COMMIT": {
if (rest.length !== 1) throw fail();
const [hash] = rest;
return {type: COMMIT_TYPE, hash};
}
case "TREE": {
if (rest.length !== 1) throw fail();
const [hash] = rest;
return {type: TREE_TYPE, hash};
}
case "TREE_ENTRY": {
if (rest.length !== 2) throw fail();
const [treeHash, name] = rest;
return {type: TREE_ENTRY_TYPE, treeHash, name};
}
default:
// eslint-disable-next-line no-unused-expressions
(type: empty);
@ -93,14 +48,8 @@ export function fromRaw(x: RawAddress): StructuredAddress {
export function toRaw(x: StructuredAddress): RawAddress {
switch (x.type) {
case BLOB_TYPE:
return NodeAddress.append(Prefix.blob, x.hash);
case COMMIT_TYPE:
return NodeAddress.append(Prefix.commit, x.hash);
case TREE_TYPE:
return NodeAddress.append(Prefix.tree, x.hash);
case TREE_ENTRY_TYPE:
return NodeAddress.append(Prefix.treeEntry, x.treeHash, x.name);
default:
throw new Error(`Unexpected type ${(x.type: empty)}`);
}

View File

@ -6,36 +6,18 @@ import {fromRaw, toRaw} from "./nodes";
describe("plugins/git/nodes", () => {
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",
}),
};
// Incorrect types should be caught statically, either due to being
// totally invalid...
// Incorrect types should be caught statically
// $ExpectFlowError
const _unused_badTree: GN.RepoAddress = {
type: "TREEEEE",
hash: "browns",
};
// ...or due to being annotated with the type of a distinct structured
// address:
// $ExpectFlowError
const _unused_badCommit: GN.CommitAddress = {...examples.tree()};
describe("`fromRaw` after `toRaw` is identity", () => {
Object.keys(examples).forEach((example) => {
@ -92,38 +74,12 @@ describe("plugins/git/nodes", () => {
expectBadAddress("no type", []);
expectBadAddress("bad type", ["wat"]);
expectBadAddress("blob with no hash", [GN.BLOB_TYPE]);
expectBadAddress("blob with extra field", [
GN.BLOB_TYPE,
examples.blob().hash,
examples.blob().hash,
]);
expectBadAddress("commit with no hash", [GN.COMMIT_TYPE]);
expectBadAddress("commit with extra field", [
GN.COMMIT_TYPE,
examples.commit().hash,
examples.commit().hash,
]);
expectBadAddress("tree with no hash", [GN.TREE_TYPE]);
expectBadAddress("tree with extra field", [
GN.TREE_TYPE,
examples.tree().hash,
examples.tree().hash,
]);
expectBadAddress("tree entry with no fields", [GN.TREE_ENTRY_TYPE]);
expectBadAddress("tree entry with only tree hash", [
GN.TREE_ENTRY_TYPE,
examples.treeEntry().treeHash,
]);
expectBadAddress("tree entry with extra field", [
GN.TREE_ENTRY_TYPE,
examples.treeEntry().treeHash,
examples.treeEntry().name,
"wat",
]);
});
describe("toRaw(...) with", () => {

View File

@ -5,34 +5,12 @@ 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();
});
});

View File

@ -4,7 +4,7 @@ import {Graph, type Edge, EdgeAddress} from "../../core/graph";
import {GraphView} from "./graphView";
import * as GE from "./edges";
import * as GN from "./nodes";
import {COMMIT_TYPE, toRaw as gitToRaw, TREE_TYPE} from "../git/nodes";
import {COMMIT_TYPE, toRaw as gitToRaw} from "../git/nodes";
import {exampleGraph} from "./example/example";
function exampleView() {
@ -265,12 +265,6 @@ describe("plugins/github/graphView", () => {
const badEdge = GE.createEdge.mergedAs(issue, commit);
failsForEdge(badEdge);
});
it("dst must be commit address", () => {
const tree = {type: TREE_TYPE, hash: "hash"};
// $ExpectFlowError
const badEdge = GE.createEdge.mergedAs(pull, tree);
failsForEdge(badEdge);
});
it("src must be pull in edge address", () => {
const otherPull = {type: "PULL", repo, number: "143"};
const mergedAs = GE.createEdge.mergedAs(otherPull, commit);

View File

@ -50,10 +50,6 @@ describe("plugins/github/nodes", () => {
type: GitNode.COMMIT_TYPE,
hash: "0000000000000000000000000000000000000000",
});
const tree = (): GitNode.TreeAddress => ({
type: GitNode.TREE_TYPE,
hash: "0000000000000000000000000000000000000000",
});
const examples = {
repo,
@ -150,10 +146,6 @@ describe("plugins/github/nodes", () => {
);
});
expectBadAddress("no kind", []);
expectBadAddress(
"Git node that isn't a commit",
NodeAddress.toParts(GitNode.toRaw(tree()))
);
describe("repository with", () => {
checkBadCases([
{name: "no owner", parts: [GN.REPO_TYPE]},
@ -250,12 +242,6 @@ describe("plugins/github/nodes", () => {
toRaw({type: "COMMENT", parent: {type: "ICE_CREAM"}});
}).toThrow("Bad comment parent type");
});
it("a git address that isn't a commit", () => {
expect(() => {
// $ExpectFlowError
toRaw(tree());
}).toThrow("Unexpected type");
});
});
});
});