Redefine artifact plugin node and edge semantics (#111)

Summary:
This commit revises our implementations of node and edge types, and
specifies the semantics for artifact plugin IDs: we create IDs by
slugifying an artifact name and then resolving collisions

Test Plan:
Unit tests added. Run `yarn flow` and `yarn test`.

wchargin-branch: artifact-plugin-node-edge-semantics
This commit is contained in:
William Chargin 2018-03-26 19:17:42 -07:00 committed by GitHub
parent e57a16efbd
commit 458744e77f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 8 deletions

View File

@ -1,18 +1,45 @@
// @flow
export type ArtifactNodeID = string;
import type {Address} from "../../core/address";
import type {Graph} from "../../core/graph";
export const ARTIFACT_PLUGIN_NAME = "sourcecred/artifact-beta";
export const ARTIFACT_NODE_TYPE = "ARTIFACT";
export type ArtifactNodePayload = {|
+name: string,
+description: string,
|};
export type NodePayload = ArtifactNodePayload;
export type ArtifactEdgeID = {|
+src: string,
+dst: string,
|};
export type ArtifactEdgePayload = {|
export const INCLUDES_EDGE_TYPE = "INCLUDES";
export type IncludesEdgePayload = {|
+weight: number, // non-negative
|};
export type EdgePayload = ArtifactEdgePayload;
export type EdgePayload = IncludesEdgePayload;
const NON_SLUG_CHARACTER: RegExp = /[^a-z]/g;
export function artifactAddress(
graph: Graph<NodePayload, EdgePayload>,
repoOwner: string,
repoName: string,
artifactName: string
): Address {
const baseId = artifactName.toLowerCase().replace(NON_SLUG_CHARACTER, "-");
function address(id) {
return {
repositoryName: `${repoOwner}/${repoName}`,
pluginName: ARTIFACT_PLUGIN_NAME,
id,
type: ARTIFACT_NODE_TYPE,
};
}
let id = baseId;
for (let i = 0; graph.getNode(address(id)) != null; i++) {
id = baseId + "-" + i;
}
return address(id);
}

View File

@ -0,0 +1,51 @@
// @flow
import {Graph} from "../../core/graph";
import {artifactAddress} from "./artifactPlugin";
describe("artifactPlugin", () => {
describe("artifactAddress", () => {
it("formats the repository name", () => {
const a = artifactAddress(
new Graph(),
"not-sourcecred",
"not-artifact-plugin",
"Sample artifact!"
);
expect(a.repositoryName).toEqual("not-sourcecred/not-artifact-plugin");
});
it("slugifies the artifact name", () => {
const a = artifactAddress(
new Graph(),
"not-sourcecred",
"not-artifact-plugin",
"Sample artifact!"
);
expect(a.id).toEqual("sample-artifact-");
});
it("resolves collisions", () => {
const g = new Graph();
const ids = [];
for (let i = 0; i < 3; i++) {
const a = artifactAddress(
g,
"not-sourcecred",
"not-artifact-plugin",
"Sample artifact!"
);
ids.push(a.id);
g.addNode({
address: a,
payload: {name: "Sample artifact!", description: ""},
});
}
expect(ids).toEqual([
"sample-artifact-",
"sample-artifact--0",
"sample-artifact--1",
]);
});
});
});

View File

@ -34,7 +34,7 @@ function createSampleArtifact(name) {
id,
type: "artifact",
},
payload: {name},
payload: {name, description: ""},
};
}