Skip to content

Commit b3ff38d

Browse files
committed
git timetravel -- show author names
1 parent b01db7d commit b3ff38d

File tree

3 files changed

+77
-22
lines changed

3 files changed

+77
-22
lines changed

src/packages/frontend/frame-editors/time-travel-editor/actions.ts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
7777
syncdoc?: SyncDoc;
7878
private first_load: boolean = true;
7979
ambient_actions?: CodeEditorActions;
80-
private gitTimestampToHash: { [t: number]: string } = {};
80+
private gitLog: { [t: number]: { hash: string; name: string } } = {};
8181

8282
_init2(): void {
8383
const { head, tail } = path_split(this.path);
@@ -450,18 +450,25 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
450450
try {
451451
const { stdout } = await this.gitCommand([
452452
"log",
453-
`--format="%at %H"`,
453+
`--format="%at %H %an <%ae>"`,
454454
"--",
455455
]);
456-
this.gitTimestampToHash = {};
456+
this.gitLog = {};
457457
const versions: Date[] = [];
458458
for (const x of stdout.split("\n")) {
459-
const [t0, h] = x.slice(1, -1).split(" ");
460-
if (!x || !t0 || !h) {
459+
const y = x.slice(1, -1);
460+
const i = y.indexOf(" ");
461+
if (i == -1) continue;
462+
const t0 = y.slice(0, i);
463+
const j = y.indexOf(" ", i + 1);
464+
if (j == -1) continue;
465+
const hash = y.slice(i + 1, j).trim();
466+
const name = y.slice(j + 1).trim();
467+
if (!x || !t0 || !hash) {
461468
continue;
462469
}
463470
const t = parseInt(t0) * 1000;
464-
this.gitTimestampToHash[t] = h.trim();
471+
this.gitLog[t] = { hash, name };
465472
versions.push(new Date(t));
466473
}
467474
versions.reverse();
@@ -479,7 +486,7 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
479486
};
480487

481488
private gitShow = async (version: Date): Promise<string | undefined> => {
482-
const h = this.gitTimestampToHash[version.valueOf()];
489+
const h = this.gitLog[version.valueOf()]?.hash;
483490
if (h == null) {
484491
return;
485492
}
@@ -497,6 +504,26 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
497504
}
498505
};
499506

507+
gitNames = (version0: number, version1: number): string[] => {
508+
const versions = this.store.get("git_versions");
509+
if (versions == null) {
510+
return [];
511+
}
512+
const v0 = versions.get(version0)?.valueOf();
513+
const v1 = versions.get(version1)?.valueOf();
514+
if (v0 == null || v1 == null) {
515+
return [];
516+
}
517+
const names: string[] = [];
518+
for (const t in this.gitLog) {
519+
const t0 = parseInt(t);
520+
if (t0 >= v0 && t0 <= v1) {
521+
names.push(this.gitLog[t].name);
522+
}
523+
}
524+
return names;
525+
};
526+
500527
gitDoc = async (version: Date): Promise<ViewDocument | undefined> => {
501528
const str = await this.gitShow(version);
502529
if (str == null) {

src/packages/frontend/frame-editors/time-travel-editor/authors.tsx

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* License: MS-RSL – see LICENSE.md for details
44
*/
55

6-
import { Tooltip } from "antd";
6+
import { Popover, Tooltip } from "antd";
77
const { User } = require("../../users");
88
import { Loading, r_join } from "../../components";
99
import { TimeTravelActions } from "./actions";
@@ -20,7 +20,39 @@ interface Props {
2020
version1: number;
2121
}
2222

23-
export function Authors(props: Props) {
23+
export function GitAuthors({ actions, version0, version1 }: Props) {
24+
const names = actions.gitNames(version0, version1);
25+
const data: { [person: string]: { emails: Set<string>; count: number } } = {};
26+
const people: string[] = [];
27+
for (const name of names) {
28+
const i = name.lastIndexOf("<");
29+
const email = name.slice(i + 1, -1).trim();
30+
const person = name.slice(0, i).trim();
31+
people.push(person);
32+
if (data[person] == null) {
33+
data[person] = { emails: new Set([email]), count: 1 };
34+
} else {
35+
data[person].emails.add(email);
36+
data[person].count += 1;
37+
}
38+
}
39+
const w = Array.from(new Set(people));
40+
w.sort();
41+
const v: JSX.Element[] = [];
42+
for (const person of w) {
43+
v.push(
44+
<Popover
45+
title={<>{data[person].count} Commits</>}
46+
content={Array.from(data[person].emails).join(", ")}
47+
>
48+
{person} ({data[person].count})
49+
</Popover>,
50+
);
51+
}
52+
return <span>{r_join(v)}</span>;
53+
}
54+
55+
export function TimeTravelAuthors({ actions, version0, version1 }: Props) {
2456
const userMap = useTypedRedux("users", "user_map");
2557

2658
const renderUser = (account_id: string) => {
@@ -69,7 +101,7 @@ export function Authors(props: Props) {
69101
const renderAuthor = (account_id: string) => {
70102
if (userMap != null && userMap.has(account_id)) {
71103
return renderUser(account_id);
72-
} else if (account_id == props.actions.project_id) {
104+
} else if (account_id == actions.project_id) {
73105
return renderProject();
74106
} else if (isEncodedNumUUID(account_id)) {
75107
return renderComputeServer(decodeUUIDtoNum(account_id));
@@ -83,10 +115,7 @@ export function Authors(props: Props) {
83115
return <Loading />;
84116
}
85117
const v: JSX.Element[] = [];
86-
for (const account_id of props.actions.get_account_ids(
87-
props.version0,
88-
props.version1,
89-
)) {
118+
for (const account_id of actions.get_account_ids(version0, version1)) {
90119
v.push(renderAuthor(account_id));
91120
}
92121
if (v.length == 0) return renderUnknown();

src/packages/frontend/frame-editors/time-travel-editor/time-travel.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { NavigationButtons } from "./navigation-buttons";
1616
import { NavigationSlider } from "./navigation-slider";
1717
import { RangeSlider } from "./range-slider";
1818
import { Version, VersionRange } from "./version";
19-
import { Authors } from "./authors";
19+
import { GitAuthors, TimeTravelAuthors } from "./authors";
2020
import { LoadFullHistory } from "./load-full-history";
2121
import { OpenFile } from "./open-file";
2222
import { RevertFile } from "./revert-file";
@@ -247,13 +247,12 @@ export function TimeTravel(props: Props) {
247247
if (version0 == null || version1 == null) {
248248
return;
249249
}
250-
return (
251-
<Authors
252-
actions={props.actions}
253-
version0={version0}
254-
version1={version1}
255-
/>
256-
);
250+
const opts = { actions: props.actions, version0, version1 };
251+
if (gitMode) {
252+
return <GitAuthors {...opts} />;
253+
} else {
254+
return <TimeTravelAuthors {...opts} />;
255+
}
257256
};
258257

259258
const renderLoadFullHistory = () => {

0 commit comments

Comments
 (0)