blob: 47da54abbd51b9b8a878e002a0cdd00cf4723413 [file] [log] [blame]
/**
* @module module/blamelist-panel-sk
* @description <h2><code>blamelist-panel-sk</code></h2>
*
* A list of commits and authors. If the list is too long, the first several will be shown.
* The last commit in the list will not be shown, as it is interpreted to be "the last good commit",
* or the last commit for which Gold had data before the first commit in the list.
*
* This should typically go into some sort of dialog to show the user.
*/
import { define } from 'elements-sk/define';
import { html, TemplateResult } from 'lit-html';
import { diffDate } from 'common-sk/modules/human';
import { ElementSk } from '../../../infra-sk/modules/ElementSk';
import { truncate } from '../../../infra-sk/modules/string';
import { baseRepoURL } from '../settings';
import { Commit } from '../rpc_types';
const maxCommitsToDisplay = 15;
const commitRow = (c: Commit): TemplateResult => {
if (c.hash) {
// Assume this is a standard git commit
return html`
<tr>
<td title=${c.author}>${truncate(c.author, 20)}</td>
<td title=${new Date(c.commit_time * 1000)}>
${diffDate(c.commit_time * 1000)}
</td>
<td>
<a href=${commitHref(c)} target=_blank rel=noopener>
${c.hash?.substring(0, 8)}
</a>
</td>
<td title=${c.message}>${truncate(c.message || '', 80)}</td>
</tr>
`;
}
// This is an instance using non-standard ids
// TODO(kjlubick) make this link to something useful
return html`
<tr>
<td>${c.id}</td>
</tr>
`;
};
// lastGoodCommit is the last commit that Gold had data before newest commit. When we create the
// range below, the next commit in the repo's history after the oldest commit will be the first to
// show up. We need to do this because Gold removes commits that have no data (to make the data
// "dense") and we don't want to construct a blamelist that is missing commits.
const commitRange = (commits: Commit[], lastGoodCommit: Commit): string => {
if (!commits.length) {
return '';
}
// If we have CL "commit", it is not in the repo we are going to link to (at least not reachable
// by CL id). Therefore, we skip a CL "commit" when constructing the blamelist. "commit" here is
// in quotes because we re-use the Commit structure to pass in information about a CL for the
// purpose of drawing a trace.
let newestCommit = commits[0];
if (newestCommit.cl_url) {
newestCommit = commits[1];
}
// If we have exactly one commit or one commit and one CL "commit", we can't show a range.
if (!newestCommit || lastGoodCommit.hash === newestCommit.hash) {
return '';
}
const repo = baseRepoURL();
if (!repo) {
throw new DOMException('repo not set in settings');
}
if (repo.indexOf('github.com') !== -1) {
return `${repo}/compare/${lastGoodCommit.hash}...${newestCommit.hash}`;
}
return `${repo}/+log/${lastGoodCommit.hash}..${newestCommit.hash}`;
};
const commitHref = (commit: Commit) => {
if (commit.cl_url) {
return commit.cl_url;
}
// TODO(kjlubick): Deduplicate with by-blame-sk.
const repo = baseRepoURL();
if (!repo) {
throw new DOMException('repo not set in settings');
}
if (repo.indexOf('github.com') !== -1) {
return `${repo}/commit/${commit.hash}`;
}
return `${repo}/+show/${commit.hash}`;
};
export class BlamelistPanelSk extends ElementSk {
static template = (ele: BlamelistPanelSk): TemplateResult => {
const commitRangeHref = commitRange(ele.commits, ele.lastGoodCommit);
return html`
<h2 ?hidden=${!commitRangeHref} class=full_range>
<a href=${commitRangeHref} target=_blank rel=noopener>View Full Range</a>
</h2>
<h2>Commits for which Gold saw data:</h2>
<table>
${ele.commits.slice(0, maxCommitsToDisplay).map(commitRow)}
</table>
<div>
${ele.commits.length > maxCommitsToDisplay ? '...and other commits.' : ''}
</div>`;
};
private _commits: Commit[] = [];
private lastGoodCommit: Commit = {
hash: '', author: '', message: '', commit_time: 0, cl_url: '', id: '',
};
constructor() {
super(BlamelistPanelSk.template);
}
connectedCallback(): void {
super.connectedCallback();
this._render();
}
get commits(): Commit[] { return this._commits; }
set commits(commits: Commit[]) {
// This can happen if clicking on the oldest commit.
if (commits.length === 1) {
this._commits = commits;
this.lastGoodCommit = commits[0];
} else {
// Slice off the last good commit.
this.lastGoodCommit = commits.pop() || this.lastGoodCommit;
this._commits = commits;
}
this._render();
}
}
define('blamelist-panel-sk', BlamelistPanelSk);