Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate fslist1 channel #21055

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion HACKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ The Python bridge can be used interactively on a local machine:
To make it easy to test out channels without having to write out messages
manually, `cockpit.misc.print` can be used:

PYTHONPATH=src python3 -m cockpit.misc.print open fslist1 path=/etc watch=False | PYTHONPATH=src python3 -m cockpit.bridge
PYTHONPATH=src python3 -m cockpit.misc.print open fsinfo path=/etc 'attrs=["type", "entries"]' | PYTHONPATH=src python3 -m cockpit.bridge

These shell aliases might be useful when experimenting with the protocol:

Expand Down
30 changes: 0 additions & 30 deletions doc/protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -1038,36 +1038,6 @@ fields:
* "type": If the event was created this contains the type of the new file.
Will be one of: file, directory, link, special or unknown.

In case of an error, the channel will be closed. In addition to the
usual "problem" field, the "close" control message sent by the server
might have the following additional fields:

* "message": A string in the current locale describing the error.

Payload: fslist1
---------------

A channel of this type lists the files in a directory and will watch
for further changes.

The following options can be specified in the "open" control message:

* "path": The path name of the directory to watch. This should be an
absolute path.
* "watch": Boolean, when true the directory will be watched and signal
on changes. Defaults to "true"

The channel will send a number of JSON messages that list the current
content of the directory. These messages have a "event" field with
value "present", a "path" field that holds the (relative) name of
the file, "owner", "group", "size" and "modified" (timestamp) fields with
some basic file information, and a "type" field. Type will be one of:
file, directory, link, special or unknown. After all files have been listed the
"ready" control message will be sent.

Other messages on the stream signal changes to the directory, in the
same format as used by the "fswatch1" payload type.

In case of an error, the channel will be closed. In addition to the
usual "problem" field, the "close" control message sent by the server
might have the following additional fields:
Expand Down
45 changes: 17 additions & 28 deletions pkg/lib/cockpit-components-file-autocomplete.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { Select, SelectOption } from "@patternfly/react-core/dist/esm/deprecated
import PropTypes from "prop-types";
import { debounce } from 'throttle-debounce';

import { fsinfo } from "cockpit/fsinfo";

const _ = cockpit.gettext;

export class FileAutoComplete extends React.Component {
Expand Down Expand Up @@ -58,7 +60,7 @@ export class FileAutoComplete extends React.Component {
path = value.slice(0, value.length - 1);

const match = this.state.displayFiles
.find(entry => (entry.type == 'directory' && entry.path == path + '/') || (entry.type == 'file' && entry.path == path));
.find(entry => (entry.type == 'dir' && entry.path == path + '/') || (entry.type == 'reg' && entry.path == path));

if (match) {
// If match file path is a prefix of another file, do not update current directory,
Expand All @@ -67,7 +69,7 @@ export class FileAutoComplete extends React.Component {
const isPrefix = this.state.displayFiles.filter(entry => entry.path.startsWith(value)).length > 1;
// If the inserted string corresponds to a directory listed in the results
// update the current directory and refetch results
if (match.type == 'directory' && !isPrefix)
if (match.type == 'dir' && !isPrefix)
cb(match.path);
else
this.setState({ value: match.path });
Expand All @@ -91,38 +93,25 @@ export class FileAutoComplete extends React.Component {

onCreateOption(newValue) {
this.setState(prevState => ({
displayFiles: [...prevState.displayFiles, { type: "file", path: newValue }]
displayFiles: [...prevState.displayFiles, { type: "reg", path: newValue }]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

}));
}

updateFiles(path) {
if (this.state.directory == path)
return;

const channel = cockpit.channel({
payload: "fslist1",
path,
superuser: this.props.superuser,
watch: false,
});
const results = [];

channel.addEventListener("ready", () => {
this.finishUpdate(results, null, path);
});

channel.addEventListener("close", (ev, data) => {
this.finishUpdate(results, data.message, path);
});

channel.addEventListener("message", (ev, data) => {
const item = JSON.parse(data);
if (item && item.path && item.event == 'present' &&
(!this.props.onlyDirectories || item.type == 'directory')) {
item.path = item.path + (item.type == 'directory' ? '/' : '');
results.push(item);
}
});
fsinfo(path, ['type', 'entries'], { superuser: this.props.superuser })
.then(info => {
const results = [];
for (const name in info.entries ?? {}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

const type = info.entries[name].type;
if (!this.props.onlyDirectories || type == 'dir')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This added line is not executed by any test.

results.push({ type, path: name + (type == 'dir' ? '/' : '') });
}
this.finishUpdate(results, null, path);
})
.catch(error => this.finishUpdate([], error.message, path));
}

finishUpdate(results, error, directory) {
Expand All @@ -137,7 +126,7 @@ export class FileAutoComplete extends React.Component {

if (directory) {
listItems.unshift({
type: "directory",
type: "dir",
path: directory
});
}
Expand Down
2 changes: 2 additions & 0 deletions src/cockpit/channels/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def tag_from_fd(fd):
return None


# DEPRECATED: https://github.com/cockpit-project/cockpit/pull/21055
# as of 2024-09-30 there are no more users of this in any known project
class FsListChannel(Channel):
payload = 'fslist1'

Expand Down
2 changes: 1 addition & 1 deletion test/verify/check-shell-keys
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ session optional pam_ssh_add.so
b.wait_in_text("#credentials-modal .pf-v5-c-select__menu-item.pf-m-disabled", "No such file or directory")
b.focus("#credentials-modal .pf-v5-c-select__toggle-typeahead input")
b.key("Backspace", 5)
b.wait_visible("#credentials-modal .pf-v5-c-select__menu-item.directory:contains('/var/lib/')")
b.wait_visible("#credentials-modal .pf-v5-c-select__menu-item.dir:contains('/var/lib/')")
b.click("#credentials-modal .pf-v5-c-select__toggle-clear")
b.wait_val("#credentials-modal .pf-v5-c-select__toggle-typeahead input", "")

Expand Down