Skip to content

Commit f462dc0

Browse files
committed
Path::read()
1 parent 1d7b132 commit f462dc0

2 files changed

Lines changed: 77 additions & 3 deletions

File tree

src/dialogs/editor.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import { basename } from "cockpit-path";
3333
import type { Dialogs, DialogResult } from 'dialogs';
3434
import { fmt_to_fragments } from 'utils';
3535

36+
import { Path } from '../path.ts';
37+
3638
import "./editor.css";
3739

3840
const _ = cockpit.gettext;
@@ -76,9 +78,10 @@ class Editor extends EventEmitter<{ updated(state: EditorState): void }> {
7678
}
7779

7880
load_file() {
79-
// Can't do this async because we can't get the tag via await
80-
this.file.read()
81-
.then(((content: string, tag: string) => {
81+
const path = new Path(this.file.path);
82+
path.read({})
83+
.then(((data: {content: string, tag: string }) => {
84+
const { content, tag } = data;
8285
this.update({ content, tag_now: tag, tag_at_load: tag, error: null });
8386
}) as any /* eslint-disable-line @typescript-eslint/no-explicit-any */)
8487
.catch(error => this.update({ error }));

src/path.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* This file is part of Cockpit.
3+
*
4+
* Copyright (C) 2025 Red Hat, Inc.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
'use strict';
21+
22+
import { join_data } from 'cockpit/_internal/common.ts';
23+
import { Channel, ChannelPayload, ChannelOptions, BaseChannelOptions } from 'cockpit/channel.ts';
24+
25+
interface PathOptions extends BaseChannelOptions {
26+
payload?: never;
27+
}
28+
29+
interface ReadOptions {
30+
payload?: never;
31+
max_read_size?: number;
32+
path?: string,
33+
}
34+
35+
export class Path {
36+
filename: string;
37+
#options: PathOptions;
38+
39+
constructor(filename: string, options?: PathOptions) {
40+
this.filename = filename;
41+
this.#options = options || {};
42+
}
43+
44+
// eslint-disable-next-line max-len
45+
async read<P extends ChannelPayload = string>(options: ChannelOptions<P> & ReadOptions): Promise<{ tag: string, content: P }> {
46+
const data: P[] = [];
47+
// HACK: jelle is misunderstanding TypeScript here, obviously I can't
48+
// pass `path: this.filename` to `new Channel` as it is not a valid
49+
// option, but why does this hack work?
50+
const global_options = { ...this.#options, path: this.filename };
51+
const channel = new Channel<P>({ ...global_options, ...options, payload: 'fsread1' });
52+
53+
channel.on('data', chunk => {
54+
data.push(chunk);
55+
});
56+
57+
await channel.wait();
58+
59+
return new Promise((resolve, reject) => {
60+
channel.on('close', message => {
61+
if (message.problem) {
62+
// TODO: BasicError
63+
reject(message.problem);
64+
} else {
65+
// StrOrBytes it not assignable to P
66+
resolve({ tag: message.tag as string, content: join_data(data, channel.binary) as P });
67+
}
68+
});
69+
});
70+
}
71+
}

0 commit comments

Comments
 (0)