Cred explorer: display commit short hash + summary (#879)
This modifies how commits are displayed in the cred explorer. Rather than printing the full hash, we now print a short hash followed by the summary. Test plan: Snapshot is updated, also I tested it by running SourceCred on a real repository.
This commit is contained in:
parent
09ed51ed6e
commit
1e5f728e29
|
@ -1,6 +1,7 @@
|
|||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
- Display short hash + summary for commits (#879)
|
||||
- Hyperlink to GitHub entities (#860)
|
||||
- Add GitHub reactions to the graph (#846)
|
||||
- Detect references to commits (#833)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`plugins/git/render commit snapshots as expected 1`] = `"commit 3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f"`;
|
||||
exports[`plugins/git/render commit snapshots as expected 1`] = `"3715ddf: This is an example commit"`;
|
||||
|
|
|
@ -9,6 +9,7 @@ import * as E from "./edges";
|
|||
import {description} from "./render";
|
||||
import type {Assets} from "../../app/assets";
|
||||
import type {Repo} from "../../core/repo";
|
||||
import type {Repository} from "./types";
|
||||
|
||||
export class StaticPluginAdapter implements IStaticPluginAdapter {
|
||||
name() {
|
||||
|
@ -42,23 +43,38 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
|
|||
];
|
||||
}
|
||||
async load(assets: Assets, repo: Repo): Promise<IDynamicPluginAdapter> {
|
||||
const url = assets.resolve(
|
||||
`/api/v1/data/data/${repo.owner}/${repo.name}/git/graph.json`
|
||||
);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
return Promise.reject(response);
|
||||
const baseUrl = `/api/v1/data/data/${repo.owner}/${repo.name}/git/`;
|
||||
async function loadGraph() {
|
||||
const url = assets.resolve(baseUrl + "graph.json");
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
return Promise.reject(response);
|
||||
}
|
||||
const json = await response.json();
|
||||
return Graph.fromJSON(json);
|
||||
}
|
||||
const json = await response.json();
|
||||
const graph = Graph.fromJSON(json);
|
||||
return new DynamicPluginAdapter(graph);
|
||||
async function loadRepository(): Promise<Repository> {
|
||||
const url = assets.resolve(baseUrl + "repository.json");
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
return Promise.reject(response);
|
||||
}
|
||||
return await response.json();
|
||||
}
|
||||
const [graph, repository] = await Promise.all([
|
||||
loadGraph(),
|
||||
loadRepository(),
|
||||
]);
|
||||
return new DynamicPluginAdapter(graph, repository);
|
||||
}
|
||||
}
|
||||
|
||||
class DynamicPluginAdapter implements IDynamicPluginAdapter {
|
||||
+_graph: Graph;
|
||||
constructor(graph: Graph) {
|
||||
+_repository: Repository;
|
||||
constructor(graph: Graph, repository: Repository) {
|
||||
this._graph = graph;
|
||||
this._repository = repository;
|
||||
}
|
||||
graph() {
|
||||
return this._graph;
|
||||
|
@ -67,7 +83,7 @@ class DynamicPluginAdapter implements IDynamicPluginAdapter {
|
|||
// This cast is unsound, and might throw at runtime, but won't have
|
||||
// silent failures or cause problems down the road.
|
||||
const address = N.fromRaw((node: any));
|
||||
return description(address);
|
||||
return description(address, this._repository);
|
||||
}
|
||||
static() {
|
||||
return new StaticPluginAdapter();
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
// @flow
|
||||
|
||||
import * as N from "./nodes";
|
||||
import type {Repository} from "./types";
|
||||
|
||||
export function description(address: N.StructuredAddress) {
|
||||
export function description(
|
||||
address: N.StructuredAddress,
|
||||
repository: Repository
|
||||
) {
|
||||
switch (address.type) {
|
||||
case "COMMIT":
|
||||
return `commit ${address.hash}`;
|
||||
case "TREE":
|
||||
return `tree ${address.hash}`;
|
||||
case "BLOB":
|
||||
return `blob ${address.hash}`;
|
||||
case "TREE_ENTRY":
|
||||
return `entry ${JSON.stringify(address.name)} in tree ${
|
||||
address.treeHash
|
||||
}`;
|
||||
case "COMMIT": {
|
||||
const hash = address.hash;
|
||||
const commit = repository.commits[hash];
|
||||
if (commit == null) {
|
||||
console.error(`Unable to find data for commit ${hash}`);
|
||||
return hash;
|
||||
}
|
||||
const {shortHash, summary} = commit;
|
||||
return `${shortHash}: ${summary}`;
|
||||
}
|
||||
default:
|
||||
throw new Error(`unknown type: ${(address.type: empty)}`);
|
||||
}
|
||||
|
|
|
@ -2,15 +2,35 @@
|
|||
|
||||
import * as GN from "./nodes";
|
||||
import {description} from "./render";
|
||||
import type {Repository} from "./types";
|
||||
|
||||
describe("plugins/git/render", () => {
|
||||
const examples = {
|
||||
commit: (): GN.CommitAddress => ({
|
||||
type: GN.COMMIT_TYPE,
|
||||
hash: "3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f",
|
||||
}),
|
||||
};
|
||||
const exampleHash = "3715ddfb8d4c4fd2a6f6af75488c82f84c92ec2f";
|
||||
const exampleCommit: GN.CommitAddress = Object.freeze({
|
||||
type: GN.COMMIT_TYPE,
|
||||
hash: exampleHash,
|
||||
});
|
||||
const exampleRepository: Repository = Object.freeze({
|
||||
commits: {
|
||||
[exampleHash]: {
|
||||
hash: exampleHash,
|
||||
shortHash: exampleHash.slice(0, 7),
|
||||
summary: "This is an example commit",
|
||||
parentHashes: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
it("commit snapshots as expected", () => {
|
||||
expect(description(examples.commit())).toMatchSnapshot();
|
||||
expect(description(exampleCommit, exampleRepository)).toMatchSnapshot();
|
||||
});
|
||||
it("logs an error for a commit not in the repository", () => {
|
||||
const badCommit = {type: GN.COMMIT_TYPE, hash: "1234"};
|
||||
// $ExpectFlowError
|
||||
console.error = jest.fn();
|
||||
expect(description(badCommit, exampleRepository)).toBe("1234");
|
||||
expect(console.error).toHaveBeenCalledWith(
|
||||
"Unable to find data for commit 1234"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue