UniRef: add GithubReferenceDetector (#1543)
As a RelationalView is not designed for multiple repositories, we should implement our own merging of mappings obtained from RelationalViews. fromRelationalViews is a factory function which does this for us. And by accepting an array of RelationalViews it's more apparent it should be used this way.
This commit is contained in:
parent
f16119af43
commit
063c08d974
|
@ -0,0 +1,37 @@
|
|||
// @flow
|
||||
|
||||
import dedent from "../../util/dedent";
|
||||
import {type NodeAddressT, NodeAddress} from "../../core/graph";
|
||||
import {MappedReferenceDetector, type URL} from "../../core/references";
|
||||
import {RelationalView} from "./relationalView";
|
||||
|
||||
/**
|
||||
* Builds a GithubReferenceDetector using multiple RelationalView.
|
||||
* As RelationalView should only be used for one repository at a time, you will
|
||||
* commonly want to compose several of them into one GithubReferenceDetector.
|
||||
*
|
||||
* Note: duplicates are normally expected. However for any URL, the corresponding
|
||||
* NodeAddressT should be the same, or we'll throw an error.
|
||||
*/
|
||||
export function fromRelationalViews(
|
||||
views: $ReadOnlyArray<RelationalView>
|
||||
): GithubReferenceDetector {
|
||||
const map: Map<URL, NodeAddressT> = new Map();
|
||||
for (const view of views) {
|
||||
for (const [url, addr] of view.urlReferenceMap().entries()) {
|
||||
const existing = map.get(url);
|
||||
if (existing && existing != addr) {
|
||||
throw new Error(dedent`\
|
||||
An entry for ${url} already existed, but with a different NodeAddressT.
|
||||
This is probably a bug with SourceCred. Please report it on GitHub.
|
||||
Old: ${NodeAddress.toString(existing)}
|
||||
New: ${NodeAddress.toString(addr)}
|
||||
`);
|
||||
}
|
||||
map.set(url, addr);
|
||||
}
|
||||
}
|
||||
return new GithubReferenceDetector(map);
|
||||
}
|
||||
|
||||
export const GithubReferenceDetector = MappedReferenceDetector;
|
|
@ -0,0 +1,75 @@
|
|||
// @flow
|
||||
|
||||
import {exampleRelationalView} from "./example/example";
|
||||
import {RelationalView} from "./relationalView";
|
||||
import {
|
||||
GithubReferenceDetector,
|
||||
fromRelationalViews,
|
||||
} from "./referenceDetector";
|
||||
import {MappedReferenceDetector} from "../../core/references";
|
||||
import {NodeAddress} from "../../core/graph";
|
||||
import dedent from "../../util/dedent";
|
||||
|
||||
describe("plugins/github/referenceDetector", () => {
|
||||
describe("GithubReferenceDetector", () => {
|
||||
it("should be a MappedReferenceDetector", () => {
|
||||
// Given
|
||||
const map = new Map();
|
||||
|
||||
// When
|
||||
const refs = new GithubReferenceDetector(map);
|
||||
|
||||
// Then
|
||||
expect(refs).toBeInstanceOf(MappedReferenceDetector);
|
||||
});
|
||||
});
|
||||
|
||||
describe("fromRelationalViews", () => {
|
||||
it("should use urlReferenceMap to create the instance", () => {
|
||||
// Given
|
||||
const rv = new RelationalView();
|
||||
const urlReferenceMap = jest.spyOn(rv, "urlReferenceMap");
|
||||
|
||||
// When
|
||||
const refs = fromRelationalViews([rv, rv]);
|
||||
|
||||
// Then
|
||||
expect(refs).toBeInstanceOf(MappedReferenceDetector);
|
||||
expect(urlReferenceMap).toBeCalledTimes(2);
|
||||
});
|
||||
|
||||
it("should deduplicate silently given the same entries", () => {
|
||||
// Given
|
||||
const rv = exampleRelationalView();
|
||||
|
||||
// When
|
||||
const refs = fromRelationalViews([rv, rv]);
|
||||
|
||||
// Then
|
||||
expect(refs.map).toEqual(rv.urlReferenceMap());
|
||||
});
|
||||
|
||||
it("should throw when encountering duplicate keys with different values", () => {
|
||||
// Given
|
||||
const url = "http://foo.bar";
|
||||
const nodeA = NodeAddress.fromParts(["test", "A"]);
|
||||
const nodeB = NodeAddress.fromParts(["test", "B"]);
|
||||
const rv1 = new RelationalView();
|
||||
const rv2 = new RelationalView();
|
||||
const rv1Spy = jest.spyOn(rv1, "urlReferenceMap");
|
||||
const rv2Spy = jest.spyOn(rv2, "urlReferenceMap");
|
||||
rv1Spy.mockReturnValue(new Map([[url, nodeA]]));
|
||||
rv2Spy.mockReturnValue(new Map([[url, nodeB]]));
|
||||
|
||||
// When
|
||||
const fn = () => fromRelationalViews([rv1, rv2]);
|
||||
|
||||
// Then
|
||||
expect(fn).toThrow(dedent`\
|
||||
An entry for http://foo.bar already existed, but with a different NodeAddressT.
|
||||
This is probably a bug with SourceCred. Please report it on GitHub.
|
||||
Old: NodeAddress["test","A"]
|
||||
New: NodeAddress["test","B"]`);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue