Skip to content

Commit 74c6a86

Browse files
committed
timetravel with git: something works now
1 parent 2087d99 commit 74c6a86

File tree

4 files changed

+117
-103
lines changed

4 files changed

+117
-103
lines changed

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

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
import { SyncDoc } from "@cocalc/sync/editor/generic/sync-doc";
2929
import { webapp_client } from "../../webapp-client";
3030
import { exec } from "@cocalc/frontend/frame-editors/generic/client";
31-
31+
import { ViewDocument } from "./view-document";
3232
import {
3333
Actions as CodeEditorActions,
3434
CodeEditorState,
@@ -163,10 +163,6 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
163163
// syncdoc_changed -- can get called at any time, so have to be extra careful
164164
versions = List<Date>(this.syncdoc.all_versions());
165165
} catch (err) {
166-
console.warn(
167-
"ignoring issue with time travel due to syncdoc not being ready",
168-
err,
169-
);
170166
this.setState({ versions: List([]) });
171167
return;
172168
}
@@ -296,25 +292,19 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
296292
}
297293

298294
public setTextMode(id: string, text_mode: boolean): void {
299-
for (const actions of [this, this.ambient_actions]) {
300-
if (actions == null) continue;
301-
const node = actions._get_frame_node(id);
302-
if (node == null) continue;
303-
text_mode = !!text_mode;
304-
actions.set_frame_tree({ id, text_mode });
305-
break;
295+
const node = this._get_frame_node(id);
296+
if (node == null) {
297+
return;
306298
}
299+
this.set_frame_tree({ id, text_mode: !!text_mode });
307300
}
308301

309302
public setGitMode(id: string, git_mode: boolean): void {
310-
for (const actions of [this, this.ambient_actions]) {
311-
if (actions == null) continue;
312-
const node = actions._get_frame_node(id);
313-
if (node == null) continue;
314-
git_mode = !!git_mode;
315-
actions.set_frame_tree({ id, git_mode });
316-
break;
303+
const node = this._get_frame_node(id);
304+
if (node == null) {
305+
return;
317306
}
307+
this.set_frame_tree({ id, git_mode: !!git_mode });
318308
this.updateGitVersions();
319309
}
320310

@@ -371,9 +361,16 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
371361

372362
private gitCommand = async (args: string[], commit?: string) => {
373363
const { head, tail } = path_split(this.docpath);
364+
console.log({
365+
command: "git",
366+
args: args.concat([`${commit ? commit + ":./" : ""}${tail}`]),
367+
path: head,
368+
project_id: this.project_id,
369+
err_on_exit: true,
370+
});
374371
return await exec({
375372
command: "git",
376-
args: args.concat([`${commit ? commit + ":" : ""}${tail}`]),
373+
args: args.concat([`${commit ? commit + ":./" : ""}${tail}`]),
377374
path: head,
378375
project_id: this.project_id,
379376
err_on_exit: true,
@@ -411,18 +408,26 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
411408
}
412409
};
413410

414-
gitShow = async (version: Date): Promise<string> => {
411+
private gitShow = async (version: Date): Promise<string | undefined> => {
415412
const h = this.gitTimestampToHash[version.valueOf()];
416413
if (h == null) {
417-
return "";
414+
return;
418415
}
419416
try {
420417
const { stdout } = await this.gitCommand(["show"], h);
421418
return stdout;
422419
} catch (err) {
423420
this.set_error(`${err}`);
424-
return "";
421+
return;
422+
}
423+
};
424+
425+
gitDoc = async (version: Date): Promise<ViewDocument | undefined> => {
426+
const str = await this.gitShow(version);
427+
if (str == null) {
428+
return undefined;
425429
}
430+
return new ViewDocument(this.docpath, str);
426431
};
427432
}
428433

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

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
// Time travel editor react component.
77

8+
import { useEffect, useState } from "react";
89
import { Checkbox, Tooltip } from "antd";
910
import { Map } from "immutable";
1011
import { redux } from "../../app-framework";
@@ -27,6 +28,7 @@ import { to_ipynb } from "../../jupyter/history-viewer";
2728
import { SagewsDiff } from "./sagews-diff";
2829
import { useEditorRedux } from "@cocalc/frontend/app-framework";
2930
import { Viewer } from "./viewer";
31+
import type { Document } from "@cocalc/sync/editor/generic/types";
3032

3133
const HAS_SPECIAL_VIEWER = new Set([
3234
"tasks",
@@ -60,6 +62,8 @@ export function TimeTravel(props: Props) {
6062
const docext = useEditor("docext");
6163
const git = useEditor("git");
6264

65+
const [doc, setDoc] = useState<Document | undefined>(undefined);
66+
6367
const getVersion = (): Date | undefined => {
6468
if (props.desc == null || versions == null) return;
6569
const version = props.desc.get("version");
@@ -68,6 +72,31 @@ export function TimeTravel(props: Props) {
6872
return versions.get(-1);
6973
};
7074

75+
const getDoc = (version?: number | Date | undefined) => {
76+
if (version == null) {
77+
version = getVersion();
78+
} else if (typeof version == "number") {
79+
if (versions == null) return;
80+
version = versions.get(version);
81+
}
82+
if (version == null) return;
83+
return props.actions.get_doc(version);
84+
};
85+
86+
useEffect(() => {
87+
const version = getVersion();
88+
if (version != null) {
89+
if (props.desc?.get("git_mode")) {
90+
(async () => {
91+
const doc = await props.actions.gitDoc(version);
92+
setDoc(doc ?? undefined);
93+
})();
94+
} else {
95+
setDoc(getDoc(version));
96+
}
97+
}
98+
}, [props.desc?.get("version"), versions]);
99+
71100
const renderVersion = () => {
72101
if (props.desc == null || versions == null) return;
73102
if (props.desc.get("changes_mode")) {
@@ -88,51 +117,6 @@ export function TimeTravel(props: Props) {
88117
}
89118
};
90119

91-
const getDoc = (version?: number | Date | undefined) => {
92-
if (version == null) {
93-
version = getVersion();
94-
} else if (typeof version == "number") {
95-
if (versions == null) return;
96-
version = versions.get(version);
97-
}
98-
if (version == null) return;
99-
return props.actions.get_doc(version);
100-
};
101-
102-
const renderDocument = () => {
103-
if (
104-
docpath == null ||
105-
docext == null ||
106-
props.desc == null ||
107-
props.desc.get("changes_mode")
108-
) {
109-
return;
110-
}
111-
112-
const version = getVersion();
113-
if (version == null) {
114-
// no versions yet, so nothing to render
115-
return;
116-
}
117-
const doc = getDoc(version);
118-
if (doc == null) {
119-
return;
120-
}
121-
return (
122-
<Viewer
123-
ext={docext}
124-
doc={doc}
125-
textMode={props.desc.get("text_mode")}
126-
actions={props.actions}
127-
id={props.id}
128-
path={docpath ? docpath : "a.js"}
129-
project_id={props.project_id}
130-
font_size={props.font_size}
131-
editor_settings={props.editor_settings}
132-
/>
133-
);
134-
};
135-
136120
const getDiffValues = ():
137121
| { v0: string; v1: string; use_json: boolean }
138122
| undefined => {
@@ -392,23 +376,32 @@ export function TimeTravel(props: Props) {
392376
return <Loading theme={"medium"} />;
393377
};
394378

395-
const renderView = () => {
396-
return (
397-
<>
398-
{renderDocument()}
399-
{renderDiff()}
400-
</>
401-
);
402-
};
403-
404379
if (loading) {
405380
return renderLoading();
406381
}
407382
return (
408383
<div className="smc-vfill">
409384
{renderControls()}
410385
{renderTimeSelect()}
411-
{renderView()}
386+
<>
387+
{doc != null &&
388+
docpath != null &&
389+
docext != null &&
390+
!props.desc?.get("changes_mode") && (
391+
<Viewer
392+
ext={docext}
393+
doc={doc}
394+
textMode={props.desc.get("text_mode")}
395+
actions={props.actions}
396+
id={props.id}
397+
path={docpath ? docpath : "a.js"}
398+
project_id={props.project_id}
399+
font_size={props.font_size}
400+
editor_settings={props.editor_settings}
401+
/>
402+
)}
403+
{renderDiff()}
404+
</>
412405
</div>
413406
);
414407
}
Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,61 @@
11
import { fromJS } from "immutable";
22
import type { Document } from "@cocalc/sync/editor/generic/types";
3+
import { filenameMode } from "@cocalc/frontend/file-associations";
4+
5+
export function isObjectDoc(path) {
6+
/* not a great way to tell if json lines or text? */
7+
const obj = "__cocalc__object_doc__";
8+
return filenameMode(path, obj) == obj;
9+
}
310

411
export class ViewDocument implements Document {
5-
private v: any[] = [];
12+
private v: any[] | null;
613
private str: string;
714

8-
constructor(str: string) {
15+
constructor(path: string, str: string) {
916
this.str = str;
10-
const v: any[] = [];
11-
for (const x of str.split("\n")) {
12-
v.push(JSON.parse(x));
17+
if (isObjectDoc(path)) {
18+
const v: any[] = [];
19+
for (const x of str.split("\n")) {
20+
v.push(JSON.parse(x));
21+
}
22+
this.v = v;
23+
} else {
24+
this.v = null;
1325
}
14-
this.v = v;
1526
}
1627

17-
// @ts-ignore
18-
apply_patch(_patch) {
28+
apply_patch(_patch): any {
1929
throw Error("not implemented");
2030
}
2131

22-
// @ts-ignore
23-
make_patch(_doc) {
32+
make_patch(_doc): any {
2433
throw Error("not implemented");
2534
}
2635

27-
// @ts-ignore
28-
is_equal(_doc) {
36+
is_equal(_doc): boolean {
2937
throw Error("not implemented");
3038
}
3139

32-
to_str() {
40+
to_str(): string {
3341
return this.str;
3442
}
3543

3644
// @ts-ignore
37-
set(_x) {
45+
set(_x: any): any {
3846
throw Error("not implemented");
3947
}
4048

41-
get(query) {
49+
get(query?) {
50+
const v = this.v;
51+
if (v == null) {
52+
return [];
53+
}
54+
if (query == null) {
55+
return fromJS(v);
56+
}
4257
const matches: any[] = [];
43-
for (const x of this.v) {
58+
for (const x of v) {
4459
for (const key in query) {
4560
if (x[key] != query[key]) {
4661
continue;
@@ -53,7 +68,11 @@ export class ViewDocument implements Document {
5368
}
5469

5570
get_one(query) {
56-
for (const x of this.v) {
71+
const v = this.v;
72+
if (v == null) {
73+
return;
74+
}
75+
for (const x of v) {
5776
for (const key in query) {
5877
if (x[key] != query[key]) {
5978
continue;
@@ -65,16 +84,16 @@ export class ViewDocument implements Document {
6584
}
6685

6786
// @ts-ignore
68-
delete(_query) {
87+
delete(_query): any {
6988
throw Error("not implemented");
7089
}
7190

7291
// optional info about what changed going from prev to this.
73-
changes(_prev) {
92+
changes(_prev): any {
7493
throw Error("not implemented");
7594
}
7695
// how many in this document (length of string number of records in db-doc, etc.)
7796
count() {
78-
return this.v.length;
97+
return this.v?.length ?? this.str.length;
7998
}
8099
}

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import type { Document } from "@cocalc/sync/editor/generic/types";
66
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
77
import { TextDocument } from "./document";
88
import { TasksHistoryViewer } from "../../editors/task-editor/history-viewer";
9-
import { filenameMode } from "@cocalc/frontend/file-associations";
109
import { HistoryViewer as JupyterHistoryViewer } from "../../jupyter/history-viewer";
1110
import { SagewsCodemirror } from "./sagews-codemirror";
1211
import Whiteboard from "@cocalc/frontend/frame-editors/whiteboard-editor/time-travel";
12+
import { isObjectDoc } from "./view-document";
1313

1414
export function Viewer({
1515
ext,
@@ -37,10 +37,7 @@ export function Viewer({
3737
<TextDocument
3838
value={doc.to_str()}
3939
id={id}
40-
path={
41-
/* TODO: this is to tell if json lines or text */
42-
filenameMode(path, "") == "" ? "a.js" : path
43-
}
40+
path={isObjectDoc(path) ? "a.js" : path}
4441
project_id={project_id}
4542
font_size={font_size}
4643
editor_settings={editor_settings}

0 commit comments

Comments
 (0)