feat(plugins): allow changing the plugin's /host folder (under a new permission) (#3827)
* working without notifying plugins * permissions and events * cleanups and formatting * style(fmt): rustfmt
This commit is contained in:
parent
90ecd8fb4b
commit
0c21eae664
16 changed files with 301 additions and 37 deletions
|
|
@ -158,6 +158,7 @@ pub enum PluginInstruction {
|
|||
},
|
||||
WatchFilesystem,
|
||||
ListClientsToPlugin(SessionLayoutMetadata, PluginId, ClientId),
|
||||
ChangePluginHostDir(PathBuf, PluginId, ClientId),
|
||||
Exit,
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +205,7 @@ impl From<&PluginInstruction> for PluginContext {
|
|||
PluginContext::FailedToWriteConfigToDisk
|
||||
},
|
||||
PluginInstruction::ListClientsToPlugin(..) => PluginContext::ListClientsToPlugin,
|
||||
PluginInstruction::ChangePluginHostDir(..) => PluginContext::ChangePluginHostDir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -886,6 +888,11 @@ pub(crate) fn plugin_thread_main(
|
|||
PluginInstruction::WatchFilesystem => {
|
||||
wasm_bridge.start_fs_watcher_if_not_started();
|
||||
},
|
||||
PluginInstruction::ChangePluginHostDir(new_host_folder, plugin_id, client_id) => {
|
||||
wasm_bridge
|
||||
.change_plugin_host_dir(new_host_folder, plugin_id, client_id)
|
||||
.non_fatal();
|
||||
},
|
||||
PluginInstruction::Exit => {
|
||||
break;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use std::{
|
|||
};
|
||||
use url::Url;
|
||||
use wasmtime::{Engine, Instance, Linker, Module, Store};
|
||||
use wasmtime_wasi::{DirPerms, FilePerms, WasiCtxBuilder};
|
||||
use wasmtime_wasi::{preview1::WasiP1Ctx, DirPerms, FilePerms, WasiCtxBuilder};
|
||||
use zellij_utils::consts::ZELLIJ_PLUGIN_ARTIFACT_DIR;
|
||||
use zellij_utils::prost::Message;
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ pub struct PluginLoader<'a> {
|
|||
size: Size,
|
||||
wasm_blob_on_hd: Option<(Vec<u8>, PathBuf)>,
|
||||
path_to_default_shell: PathBuf,
|
||||
zellij_cwd: PathBuf,
|
||||
plugin_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
default_shell: Option<TerminalAction>,
|
||||
|
|
@ -85,7 +85,7 @@ impl<'a> PluginLoader<'a> {
|
|||
connected_clients: Arc<Mutex<Vec<ClientId>>>,
|
||||
loading_indication: &mut LoadingIndication,
|
||||
path_to_default_shell: PathBuf,
|
||||
zellij_cwd: PathBuf,
|
||||
plugin_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
default_shell: Option<TerminalAction>,
|
||||
|
|
@ -110,7 +110,7 @@ impl<'a> PluginLoader<'a> {
|
|||
engine,
|
||||
&plugin_dir,
|
||||
path_to_default_shell,
|
||||
Some(zellij_cwd),
|
||||
Some(plugin_cwd),
|
||||
capabilities,
|
||||
client_attributes,
|
||||
default_shell,
|
||||
|
|
@ -145,7 +145,7 @@ impl<'a> PluginLoader<'a> {
|
|||
connected_clients: Arc<Mutex<Vec<ClientId>>>,
|
||||
loading_indication: &mut LoadingIndication,
|
||||
path_to_default_shell: PathBuf,
|
||||
zellij_cwd: PathBuf,
|
||||
plugin_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
default_shell: Option<TerminalAction>,
|
||||
|
|
@ -168,7 +168,7 @@ impl<'a> PluginLoader<'a> {
|
|||
tab_index,
|
||||
size,
|
||||
path_to_default_shell,
|
||||
zellij_cwd,
|
||||
plugin_cwd,
|
||||
capabilities,
|
||||
client_attributes,
|
||||
default_shell,
|
||||
|
|
@ -222,7 +222,7 @@ impl<'a> PluginLoader<'a> {
|
|||
connected_clients: Arc<Mutex<Vec<ClientId>>>,
|
||||
loading_indication: &mut LoadingIndication,
|
||||
path_to_default_shell: PathBuf,
|
||||
zellij_cwd: PathBuf,
|
||||
plugin_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
default_shell: Option<TerminalAction>,
|
||||
|
|
@ -246,7 +246,7 @@ impl<'a> PluginLoader<'a> {
|
|||
engine.clone(),
|
||||
&plugin_dir,
|
||||
path_to_default_shell.clone(),
|
||||
zellij_cwd.clone(),
|
||||
plugin_cwd.clone(),
|
||||
capabilities.clone(),
|
||||
client_attributes.clone(),
|
||||
default_shell.clone(),
|
||||
|
|
@ -333,7 +333,7 @@ impl<'a> PluginLoader<'a> {
|
|||
tab_index: Option<usize>,
|
||||
size: Size,
|
||||
path_to_default_shell: PathBuf,
|
||||
zellij_cwd: PathBuf,
|
||||
plugin_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
default_shell: Option<TerminalAction>,
|
||||
|
|
@ -366,7 +366,7 @@ impl<'a> PluginLoader<'a> {
|
|||
size,
|
||||
wasm_blob_on_hd: None,
|
||||
path_to_default_shell,
|
||||
zellij_cwd,
|
||||
plugin_cwd,
|
||||
capabilities,
|
||||
client_attributes,
|
||||
default_shell,
|
||||
|
|
@ -412,7 +412,7 @@ impl<'a> PluginLoader<'a> {
|
|||
// prefer the explicitly given cwd, otherwise copy it from the running plugin
|
||||
// (when reloading a plugin, we want to copy it, when starting a new plugin instance from
|
||||
// meomory, we want to reset it)
|
||||
let zellij_cwd = cwd.unwrap_or_else(|| running_plugin.store.data().plugin_cwd.clone());
|
||||
let plugin_cwd = cwd.unwrap_or_else(|| running_plugin.store.data().plugin_cwd.clone());
|
||||
loading_indication.set_name(running_plugin.store.data().name());
|
||||
PluginLoader::new(
|
||||
plugin_cache,
|
||||
|
|
@ -426,7 +426,7 @@ impl<'a> PluginLoader<'a> {
|
|||
tab_index,
|
||||
size,
|
||||
path_to_default_shell,
|
||||
zellij_cwd,
|
||||
plugin_cwd,
|
||||
capabilities,
|
||||
client_attributes,
|
||||
default_shell,
|
||||
|
|
@ -446,7 +446,7 @@ impl<'a> PluginLoader<'a> {
|
|||
engine: Engine,
|
||||
plugin_dir: &'a PathBuf,
|
||||
path_to_default_shell: PathBuf,
|
||||
zellij_cwd: PathBuf,
|
||||
plugin_cwd: PathBuf,
|
||||
capabilities: PluginCapabilities,
|
||||
client_attributes: ClientAttributes,
|
||||
default_shell: Option<TerminalAction>,
|
||||
|
|
@ -483,7 +483,7 @@ impl<'a> PluginLoader<'a> {
|
|||
tab_index,
|
||||
size,
|
||||
path_to_default_shell,
|
||||
zellij_cwd,
|
||||
plugin_cwd,
|
||||
capabilities,
|
||||
client_attributes,
|
||||
default_shell,
|
||||
|
|
@ -736,7 +736,7 @@ impl<'a> PluginLoader<'a> {
|
|||
self.engine.clone(),
|
||||
&self.plugin_dir,
|
||||
self.path_to_default_shell.clone(),
|
||||
self.zellij_cwd.clone(),
|
||||
self.plugin_cwd.clone(),
|
||||
self.capabilities.clone(),
|
||||
self.client_attributes.clone(),
|
||||
self.default_shell.clone(),
|
||||
|
|
@ -784,18 +784,22 @@ impl<'a> PluginLoader<'a> {
|
|||
},
|
||||
}
|
||||
}
|
||||
fn create_plugin_instance_env(&self, module: &Module) -> Result<(Store<PluginEnv>, Instance)> {
|
||||
let err_context = || {
|
||||
format!(
|
||||
"Failed to create instance, plugin env and subscriptions for plugin {}",
|
||||
self.plugin_id
|
||||
)
|
||||
};
|
||||
pub fn create_wasi_ctx(
|
||||
host_dir: &PathBuf,
|
||||
data_dir: &PathBuf,
|
||||
cache_dir: &PathBuf,
|
||||
tmp_dir: &PathBuf,
|
||||
plugin_url: &String,
|
||||
plugin_id: PluginId,
|
||||
stdin_pipe: Arc<Mutex<VecDeque<u8>>>,
|
||||
stdout_pipe: Arc<Mutex<VecDeque<u8>>>,
|
||||
) -> Result<WasiP1Ctx> {
|
||||
let err_context = || format!("Failed to create wasi_ctx");
|
||||
let dirs = vec![
|
||||
("/host".to_owned(), self.zellij_cwd.clone()),
|
||||
("/data".to_owned(), self.plugin_own_data_dir.clone()),
|
||||
("/cache".to_owned(), self.plugin_own_cache_dir.clone()),
|
||||
("/tmp".to_owned(), ZELLIJ_TMP_DIR.clone()),
|
||||
("/host".to_owned(), host_dir.clone()),
|
||||
("/data".to_owned(), data_dir.clone()),
|
||||
("/cache".to_owned(), cache_dir.clone()),
|
||||
("/tmp".to_owned(), tmp_dir.clone()),
|
||||
];
|
||||
let dirs = dirs.into_iter().filter(|(_dir_name, dir)| {
|
||||
// note that this does not protect against TOCTOU errors
|
||||
|
|
@ -812,16 +816,35 @@ impl<'a> PluginLoader<'a> {
|
|||
.preopened_dir(host_path, guest_path, DirPerms::all(), FilePerms::all())
|
||||
.with_context(err_context)?;
|
||||
}
|
||||
let stdin_pipe = Arc::new(Mutex::new(VecDeque::new()));
|
||||
let stdout_pipe = Arc::new(Mutex::new(VecDeque::new()));
|
||||
wasi_ctx_builder
|
||||
.stdin(VecDequeInputStream(stdin_pipe.clone()))
|
||||
.stdout(WriteOutputStream(stdout_pipe.clone()))
|
||||
.stderr(WriteOutputStream(Arc::new(Mutex::new(LoggingPipe::new(
|
||||
&self.plugin.location.to_string(),
|
||||
self.plugin_id,
|
||||
plugin_url, plugin_id,
|
||||
)))));
|
||||
let wasi_ctx = wasi_ctx_builder.build_p1();
|
||||
Ok(wasi_ctx)
|
||||
}
|
||||
fn create_plugin_instance_env(&self, module: &Module) -> Result<(Store<PluginEnv>, Instance)> {
|
||||
let err_context = || {
|
||||
format!(
|
||||
"Failed to create instance, plugin env and subscriptions for plugin {}",
|
||||
self.plugin_id
|
||||
)
|
||||
};
|
||||
let stdin_pipe = Arc::new(Mutex::new(VecDeque::new()));
|
||||
let stdout_pipe = Arc::new(Mutex::new(VecDeque::new()));
|
||||
|
||||
let wasi_ctx = PluginLoader::create_wasi_ctx(
|
||||
&self.plugin_cwd,
|
||||
&self.plugin_own_data_dir,
|
||||
&self.plugin_own_cache_dir,
|
||||
&ZELLIJ_TMP_DIR,
|
||||
&self.plugin.location.to_string(),
|
||||
self.plugin_id,
|
||||
stdin_pipe.clone(),
|
||||
stdout_pipe.clone(),
|
||||
)?;
|
||||
let plugin = self.plugin.clone();
|
||||
let plugin_env = PluginEnv {
|
||||
plugin_id: self.plugin_id,
|
||||
|
|
@ -838,7 +861,7 @@ impl<'a> PluginLoader<'a> {
|
|||
client_attributes: self.client_attributes.clone(),
|
||||
default_shell: self.default_shell.clone(),
|
||||
default_layout: self.default_layout.clone(),
|
||||
plugin_cwd: self.zellij_cwd.clone(),
|
||||
plugin_cwd: self.plugin_cwd.clone(),
|
||||
input_pipes_to_unblock: Arc::new(Mutex::new(HashSet::new())),
|
||||
input_pipes_to_block: Arc::new(Mutex::new(HashSet::new())),
|
||||
layout_dir: self.layout_dir.clone(),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use crate::plugins::pipes::{
|
|||
};
|
||||
use crate::plugins::plugin_loader::PluginLoader;
|
||||
use crate::plugins::plugin_map::{AtomicEvent, PluginEnv, PluginMap, RunningPlugin, Subscriptions};
|
||||
|
||||
use crate::plugins::plugin_worker::MessageToWorker;
|
||||
use crate::plugins::watch_filesystem::watch_filesystem;
|
||||
use crate::plugins::zellij_exports::{wasi_read_string, wasi_write_object};
|
||||
|
|
@ -18,7 +19,7 @@ use std::{
|
|||
use wasmtime::{Engine, Module};
|
||||
use zellij_utils::async_channel::Sender;
|
||||
use zellij_utils::async_std::task::{self, JoinHandle};
|
||||
use zellij_utils::consts::ZELLIJ_CACHE_DIR;
|
||||
use zellij_utils::consts::{ZELLIJ_CACHE_DIR, ZELLIJ_TMP_DIR};
|
||||
use zellij_utils::data::{InputMode, PermissionStatus, PermissionType, PipeMessage, PipeSource};
|
||||
use zellij_utils::downloader::Downloader;
|
||||
use zellij_utils::input::keybinds::Keybinds;
|
||||
|
|
@ -736,6 +737,107 @@ impl WasmBridge {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn change_plugin_host_dir(
|
||||
&mut self,
|
||||
new_host_dir: PathBuf,
|
||||
plugin_id_to_update: PluginId,
|
||||
client_id_to_update: ClientId,
|
||||
) -> Result<()> {
|
||||
let plugins_to_change: Vec<(
|
||||
PluginId,
|
||||
ClientId,
|
||||
Arc<Mutex<RunningPlugin>>,
|
||||
Arc<Mutex<Subscriptions>>,
|
||||
)> = self
|
||||
.plugin_map
|
||||
.lock()
|
||||
.unwrap()
|
||||
.running_plugins_and_subscriptions()
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|(plugin_id, _client_id, _running_plugin, _subscriptions)| {
|
||||
// TODO: cache this somehow in this case...
|
||||
!&self
|
||||
.cached_events_for_pending_plugins
|
||||
.contains_key(&plugin_id)
|
||||
})
|
||||
.collect();
|
||||
task::spawn({
|
||||
let senders = self.senders.clone();
|
||||
async move {
|
||||
match new_host_dir.try_exists() {
|
||||
Ok(false) => {
|
||||
log::error!(
|
||||
"Failed to change folder to {},: folder does not exist",
|
||||
new_host_dir.display()
|
||||
);
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
Some(plugin_id_to_update),
|
||||
Some(client_id_to_update),
|
||||
Event::FailedToChangeHostFolder(Some(format!(
|
||||
"Folder {} does not exist",
|
||||
new_host_dir.display()
|
||||
))),
|
||||
)]));
|
||||
return;
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"Failed to change folder to {},: {}",
|
||||
new_host_dir.display(),
|
||||
e
|
||||
);
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
Some(plugin_id_to_update),
|
||||
Some(client_id_to_update),
|
||||
Event::FailedToChangeHostFolder(Some(e.to_string())),
|
||||
)]));
|
||||
return;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
for (plugin_id, client_id, running_plugin, _subscriptions) in &plugins_to_change {
|
||||
if plugin_id == &plugin_id_to_update && client_id == &client_id_to_update {
|
||||
let mut running_plugin = running_plugin.lock().unwrap();
|
||||
let plugin_env = running_plugin.store.data_mut();
|
||||
let stdin_pipe = plugin_env.stdin_pipe.clone();
|
||||
let stdout_pipe = plugin_env.stdout_pipe.clone();
|
||||
let wasi_ctx = PluginLoader::create_wasi_ctx(
|
||||
&new_host_dir,
|
||||
&plugin_env.plugin_own_data_dir,
|
||||
&plugin_env.plugin_own_cache_dir,
|
||||
&ZELLIJ_TMP_DIR,
|
||||
&plugin_env.plugin.location.to_string(),
|
||||
plugin_env.plugin_id,
|
||||
stdin_pipe.clone(),
|
||||
stdout_pipe.clone(),
|
||||
);
|
||||
match wasi_ctx {
|
||||
Ok(wasi_ctx) => {
|
||||
drop(std::mem::replace(&mut plugin_env.wasi_ctx, wasi_ctx));
|
||||
plugin_env.plugin_cwd = new_host_dir.clone();
|
||||
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
Some(*plugin_id),
|
||||
Some(*client_id),
|
||||
Event::HostFolderChanged(new_host_dir.clone()),
|
||||
)]));
|
||||
},
|
||||
Err(e) => {
|
||||
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![(
|
||||
Some(*plugin_id),
|
||||
Some(*client_id),
|
||||
Event::FailedToChangeHostFolder(Some(e.to_string())),
|
||||
)]));
|
||||
log::error!("Failed to create wasi ctx: {}", e);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
pub fn pipe_messages(
|
||||
&mut self,
|
||||
mut messages: Vec<(Option<PluginId>, Option<ClientId>, PipeMessage)>,
|
||||
|
|
|
|||
|
|
@ -352,6 +352,9 @@ fn host_run_plugin_command(caller: Caller<'_, PluginEnv>) {
|
|||
write_config_to_disk,
|
||||
} => rebind_keys(env, keys_to_rebind, keys_to_unbind, write_config_to_disk)?,
|
||||
PluginCommand::ListClients => list_clients(env),
|
||||
PluginCommand::ChangeHostFolder(new_host_folder) => {
|
||||
change_host_folder(env, new_host_folder)
|
||||
},
|
||||
},
|
||||
(PermissionStatus::Denied, permission) => {
|
||||
log::error!(
|
||||
|
|
@ -1484,6 +1487,16 @@ fn list_clients(env: &PluginEnv) {
|
|||
});
|
||||
}
|
||||
|
||||
fn change_host_folder(env: &PluginEnv, new_host_folder: PathBuf) {
|
||||
let _ = env.senders.to_plugin.as_ref().map(|sender| {
|
||||
sender.send(PluginInstruction::ChangePluginHostDir(
|
||||
new_host_folder,
|
||||
env.plugin_id,
|
||||
env.client_id,
|
||||
))
|
||||
});
|
||||
}
|
||||
|
||||
fn scan_host_folder(env: &PluginEnv, folder_to_scan: PathBuf) {
|
||||
if !folder_to_scan.starts_with("/host") {
|
||||
log::error!(
|
||||
|
|
@ -1913,6 +1926,7 @@ fn check_command_permission(
|
|||
PluginCommand::RebindKeys { .. } | PluginCommand::Reconfigure(..) => {
|
||||
PermissionType::Reconfigure
|
||||
},
|
||||
PluginCommand::ChangeHostFolder(..) => PermissionType::FullHdAccess,
|
||||
_ => return (PermissionStatus::Granted, None),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1128,6 +1128,13 @@ pub fn rebind_keys(
|
|||
unsafe { host_run_plugin_command() };
|
||||
}
|
||||
|
||||
pub fn change_host_folder(new_host_folder: PathBuf) {
|
||||
let plugin_command = PluginCommand::ChangeHostFolder(new_host_folder);
|
||||
let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap();
|
||||
object_to_stdout(&protobuf_plugin_command.encode_to_vec());
|
||||
unsafe { host_run_plugin_command() };
|
||||
}
|
||||
|
||||
// Utility Functions
|
||||
|
||||
#[allow(unused)]
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub struct Event {
|
|||
pub name: i32,
|
||||
#[prost(
|
||||
oneof = "event::Payload",
|
||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23"
|
||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25"
|
||||
)]
|
||||
pub payload: ::core::option::Option<event::Payload>,
|
||||
}
|
||||
|
|
@ -64,10 +64,26 @@ pub mod event {
|
|||
FailedToWriteConfigToDiskPayload(super::FailedToWriteConfigToDiskPayload),
|
||||
#[prost(message, tag = "23")]
|
||||
ListClientsPayload(super::ListClientsPayload),
|
||||
#[prost(message, tag = "24")]
|
||||
HostFolderChangedPayload(super::HostFolderChangedPayload),
|
||||
#[prost(message, tag = "25")]
|
||||
FailedToChangeHostFolderPayload(super::FailedToChangeHostFolderPayload),
|
||||
}
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct FailedToChangeHostFolderPayload {
|
||||
#[prost(string, optional, tag = "1")]
|
||||
pub error_message: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct HostFolderChangedPayload {
|
||||
#[prost(string, tag = "1")]
|
||||
pub new_host_folder_path: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ListClientsPayload {
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub client_info: ::prost::alloc::vec::Vec<ClientInfo>,
|
||||
|
|
@ -468,6 +484,8 @@ pub enum EventType {
|
|||
CommandPaneReRun = 24,
|
||||
FailedToWriteConfigToDisk = 25,
|
||||
ListClients = 26,
|
||||
HostFolderChanged = 27,
|
||||
FailedToChangeHostFolder = 28,
|
||||
}
|
||||
impl EventType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
|
|
@ -503,6 +521,8 @@ impl EventType {
|
|||
EventType::CommandPaneReRun => "CommandPaneReRun",
|
||||
EventType::FailedToWriteConfigToDisk => "FailedToWriteConfigToDisk",
|
||||
EventType::ListClients => "ListClients",
|
||||
EventType::HostFolderChanged => "HostFolderChanged",
|
||||
EventType::FailedToChangeHostFolder => "FailedToChangeHostFolder",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
|
|
@ -535,6 +555,8 @@ impl EventType {
|
|||
"CommandPaneReRun" => Some(Self::CommandPaneReRun),
|
||||
"FailedToWriteConfigToDisk" => Some(Self::FailedToWriteConfigToDisk),
|
||||
"ListClients" => Some(Self::ListClients),
|
||||
"HostFolderChanged" => Some(Self::HostFolderChanged),
|
||||
"FailedToChangeHostFolder" => Some(Self::FailedToChangeHostFolder),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub struct PluginCommand {
|
|||
pub name: i32,
|
||||
#[prost(
|
||||
oneof = "plugin_command::Payload",
|
||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88"
|
||||
tags = "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89"
|
||||
)]
|
||||
pub payload: ::core::option::Option<plugin_command::Payload>,
|
||||
}
|
||||
|
|
@ -174,10 +174,18 @@ pub mod plugin_command {
|
|||
LoadNewPluginPayload(super::LoadNewPluginPayload),
|
||||
#[prost(message, tag = "88")]
|
||||
RebindKeysPayload(super::RebindKeysPayload),
|
||||
#[prost(message, tag = "89")]
|
||||
ChangeHostFolderPayload(super::ChangeHostFolderPayload),
|
||||
}
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ChangeHostFolderPayload {
|
||||
#[prost(string, tag = "1")]
|
||||
pub new_host_folder: ::prost::alloc::string::String,
|
||||
}
|
||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RebindKeysPayload {
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub keys_to_rebind: ::prost::alloc::vec::Vec<KeyToRebind>,
|
||||
|
|
@ -716,6 +724,7 @@ pub enum CommandName {
|
|||
LoadNewPlugin = 111,
|
||||
RebindKeys = 112,
|
||||
ListClients = 113,
|
||||
ChangeHostFolder = 114,
|
||||
}
|
||||
impl CommandName {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
|
|
@ -840,6 +849,7 @@ impl CommandName {
|
|||
CommandName::LoadNewPlugin => "LoadNewPlugin",
|
||||
CommandName::RebindKeys => "RebindKeys",
|
||||
CommandName::ListClients => "ListClients",
|
||||
CommandName::ChangeHostFolder => "ChangeHostFolder",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
|
|
@ -961,6 +971,7 @@ impl CommandName {
|
|||
"LoadNewPlugin" => Some(Self::LoadNewPlugin),
|
||||
"RebindKeys" => Some(Self::RebindKeys),
|
||||
"ListClients" => Some(Self::ListClients),
|
||||
"ChangeHostFolder" => Some(Self::ChangeHostFolder),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ pub enum PermissionType {
|
|||
ReadCliPipes = 7,
|
||||
MessageAndLaunchOtherPlugins = 8,
|
||||
Reconfigure = 9,
|
||||
FullHdAccess = 10,
|
||||
}
|
||||
impl PermissionType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
|
|
@ -31,6 +32,7 @@ impl PermissionType {
|
|||
"MessageAndLaunchOtherPlugins"
|
||||
}
|
||||
PermissionType::Reconfigure => "Reconfigure",
|
||||
PermissionType::FullHdAccess => "FullHdAccess",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
|
|
@ -46,6 +48,7 @@ impl PermissionType {
|
|||
"ReadCliPipes" => Some(Self::ReadCliPipes),
|
||||
"MessageAndLaunchOtherPlugins" => Some(Self::MessageAndLaunchOtherPlugins),
|
||||
"Reconfigure" => Some(Self::Reconfigure),
|
||||
"FullHdAccess" => Some(Self::FullHdAccess),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -912,6 +912,8 @@ pub enum Event {
|
|||
CommandPaneReRun(u32, Context), // u32 - terminal_pane_id, Option<i32> -
|
||||
FailedToWriteConfigToDisk(Option<String>), // String -> the file path we failed to write
|
||||
ListClients(Vec<ClientInfo>),
|
||||
HostFolderChanged(PathBuf), // PathBuf -> new host folder
|
||||
FailedToChangeHostFolder(Option<String>), // String -> the error we got when changing
|
||||
}
|
||||
|
||||
#[derive(
|
||||
|
|
@ -942,6 +944,7 @@ pub enum Permission {
|
|||
ReadCliPipes,
|
||||
MessageAndLaunchOtherPlugins,
|
||||
Reconfigure,
|
||||
FullHdAccess,
|
||||
}
|
||||
|
||||
impl PermissionType {
|
||||
|
|
@ -963,6 +966,7 @@ impl PermissionType {
|
|||
"Send messages to and launch other plugins".to_owned()
|
||||
},
|
||||
PermissionType::Reconfigure => "Change Zellij runtime configuration".to_owned(),
|
||||
PermissionType::FullHdAccess => "Full access to the hard-drive".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1893,4 +1897,5 @@ pub enum PluginCommand {
|
|||
write_config_to_disk: bool,
|
||||
},
|
||||
ListClients,
|
||||
ChangeHostFolder(PathBuf),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -435,6 +435,7 @@ pub enum PluginContext {
|
|||
Reconfigure,
|
||||
FailedToWriteConfigToDisk,
|
||||
ListClientsToPlugin,
|
||||
ChangePluginHostDir,
|
||||
}
|
||||
|
||||
/// Stack call representations corresponding to the different types of [`ClientInstruction`]s.
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ enum EventType {
|
|||
CommandPaneReRun = 24;
|
||||
FailedToWriteConfigToDisk = 25;
|
||||
ListClients = 26;
|
||||
HostFolderChanged = 27;
|
||||
FailedToChangeHostFolder = 28;
|
||||
}
|
||||
|
||||
message EventNameList {
|
||||
|
|
@ -81,9 +83,19 @@ message Event {
|
|||
CommandPaneReRunPayload command_pane_rerun_payload = 21;
|
||||
FailedToWriteConfigToDiskPayload failed_to_write_config_to_disk_payload = 22;
|
||||
ListClientsPayload list_clients_payload = 23;
|
||||
HostFolderChangedPayload host_folder_changed_payload = 24;
|
||||
FailedToChangeHostFolderPayload failed_to_change_host_folder_payload = 25;
|
||||
}
|
||||
}
|
||||
|
||||
message FailedToChangeHostFolderPayload {
|
||||
optional string error_message = 1;
|
||||
}
|
||||
|
||||
message HostFolderChangedPayload {
|
||||
string new_host_folder_path = 1;
|
||||
}
|
||||
|
||||
message ListClientsPayload {
|
||||
repeated ClientInfo client_info = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,6 +333,22 @@ impl TryFrom<ProtobufEvent> for Event {
|
|||
},
|
||||
_ => Err("Malformed payload for the FailedToWriteConfigToDisk Event"),
|
||||
},
|
||||
Some(ProtobufEventType::HostFolderChanged) => match protobuf_event.payload {
|
||||
Some(ProtobufEventPayload::HostFolderChangedPayload(
|
||||
host_folder_changed_payload,
|
||||
)) => Ok(Event::HostFolderChanged(PathBuf::from(
|
||||
host_folder_changed_payload.new_host_folder_path,
|
||||
))),
|
||||
_ => Err("Malformed payload for the HostFolderChanged Event"),
|
||||
},
|
||||
Some(ProtobufEventType::FailedToChangeHostFolder) => match protobuf_event.payload {
|
||||
Some(ProtobufEventPayload::FailedToChangeHostFolderPayload(
|
||||
failed_to_change_host_folder_payload,
|
||||
)) => Ok(Event::FailedToChangeHostFolder(
|
||||
failed_to_change_host_folder_payload.error_message,
|
||||
)),
|
||||
_ => Err("Malformed payload for the FailedToChangeHostFolder Event"),
|
||||
},
|
||||
None => Err("Unknown Protobuf Event"),
|
||||
}
|
||||
}
|
||||
|
|
@ -683,6 +699,20 @@ impl TryFrom<Event> for ProtobufEvent {
|
|||
.collect(),
|
||||
})),
|
||||
}),
|
||||
Event::HostFolderChanged(new_host_folder_path) => Ok(ProtobufEvent {
|
||||
name: ProtobufEventType::HostFolderChanged as i32,
|
||||
payload: Some(event::Payload::HostFolderChangedPayload(
|
||||
HostFolderChangedPayload {
|
||||
new_host_folder_path: new_host_folder_path.display().to_string(),
|
||||
},
|
||||
)),
|
||||
}),
|
||||
Event::FailedToChangeHostFolder(error_message) => Ok(ProtobufEvent {
|
||||
name: ProtobufEventType::FailedToChangeHostFolder as i32,
|
||||
payload: Some(event::Payload::FailedToChangeHostFolderPayload(
|
||||
FailedToChangeHostFolderPayload { error_message },
|
||||
)),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1228,6 +1258,8 @@ impl TryFrom<ProtobufEventType> for EventType {
|
|||
ProtobufEventType::CommandPaneReRun => EventType::CommandPaneReRun,
|
||||
ProtobufEventType::FailedToWriteConfigToDisk => EventType::FailedToWriteConfigToDisk,
|
||||
ProtobufEventType::ListClients => EventType::ListClients,
|
||||
ProtobufEventType::HostFolderChanged => EventType::HostFolderChanged,
|
||||
ProtobufEventType::FailedToChangeHostFolder => EventType::FailedToChangeHostFolder,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1263,6 +1295,8 @@ impl TryFrom<EventType> for ProtobufEventType {
|
|||
EventType::CommandPaneReRun => ProtobufEventType::CommandPaneReRun,
|
||||
EventType::FailedToWriteConfigToDisk => ProtobufEventType::FailedToWriteConfigToDisk,
|
||||
EventType::ListClients => ProtobufEventType::ListClients,
|
||||
EventType::HostFolderChanged => ProtobufEventType::HostFolderChanged,
|
||||
EventType::FailedToChangeHostFolder => ProtobufEventType::FailedToChangeHostFolder,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ enum CommandName {
|
|||
LoadNewPlugin = 111;
|
||||
RebindKeys = 112;
|
||||
ListClients = 113;
|
||||
ChangeHostFolder = 114;
|
||||
}
|
||||
|
||||
message PluginCommand {
|
||||
|
|
@ -210,9 +211,14 @@ message PluginCommand {
|
|||
ReloadPluginPayload reload_plugin_payload = 86;
|
||||
LoadNewPluginPayload load_new_plugin_payload = 87;
|
||||
RebindKeysPayload rebind_keys_payload = 88;
|
||||
ChangeHostFolderPayload change_host_folder_payload = 89;
|
||||
}
|
||||
}
|
||||
|
||||
message ChangeHostFolderPayload {
|
||||
string new_host_folder = 1;
|
||||
}
|
||||
|
||||
message RebindKeysPayload {
|
||||
repeated KeyToRebind keys_to_rebind = 1;
|
||||
repeated KeyToUnbind keys_to_unbind = 2;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ pub use super::generated_api::api::{
|
|||
input_mode::InputMode as ProtobufInputMode,
|
||||
plugin_command::{
|
||||
plugin_command::Payload, BreakPanesToNewTabPayload, BreakPanesToTabWithIndexPayload,
|
||||
ClearScreenForPaneIdPayload, CliPipeOutputPayload, CloseTabWithIndexPayload, CommandName,
|
||||
ContextItem, EditScrollbackForPaneWithIdPayload, EnvVariable, ExecCmdPayload,
|
||||
FixedOrPercent as ProtobufFixedOrPercent,
|
||||
ChangeHostFolderPayload, ClearScreenForPaneIdPayload, CliPipeOutputPayload,
|
||||
CloseTabWithIndexPayload, CommandName, ContextItem, EditScrollbackForPaneWithIdPayload,
|
||||
EnvVariable, ExecCmdPayload, FixedOrPercent as ProtobufFixedOrPercent,
|
||||
FixedOrPercentValue as ProtobufFixedOrPercentValue,
|
||||
FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, HidePaneWithIdPayload,
|
||||
HttpVerb as ProtobufHttpVerb, IdAndNewName, KeyToRebind, KeyToUnbind, KillSessionsPayload,
|
||||
|
|
@ -1303,6 +1303,14 @@ impl TryFrom<ProtobufPluginCommand> for PluginCommand {
|
|||
Some(_) => Err("ListClients should have no payload, found a payload"),
|
||||
None => Ok(PluginCommand::ListClients),
|
||||
},
|
||||
Some(CommandName::ChangeHostFolder) => match protobuf_plugin_command.payload {
|
||||
Some(Payload::ChangeHostFolderPayload(change_host_folder_payload)) => {
|
||||
Ok(PluginCommand::ChangeHostFolder(PathBuf::from(
|
||||
change_host_folder_payload.new_host_folder,
|
||||
)))
|
||||
},
|
||||
_ => Err("Mismatched payload for ChangeHostFolder"),
|
||||
},
|
||||
None => Err("Unrecognized plugin command"),
|
||||
}
|
||||
}
|
||||
|
|
@ -2130,6 +2138,12 @@ impl TryFrom<PluginCommand> for ProtobufPluginCommand {
|
|||
name: CommandName::ListClients as i32,
|
||||
payload: None,
|
||||
}),
|
||||
PluginCommand::ChangeHostFolder(new_host_folder) => Ok(ProtobufPluginCommand {
|
||||
name: CommandName::ChangeHostFolder as i32,
|
||||
payload: Some(Payload::ChangeHostFolderPayload(ChangeHostFolderPayload {
|
||||
new_host_folder: new_host_folder.display().to_string(), // TODO: not accurate?
|
||||
})),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,4 +13,5 @@ enum PermissionType {
|
|||
ReadCliPipes = 7;
|
||||
MessageAndLaunchOtherPlugins = 8;
|
||||
Reconfigure = 9;
|
||||
FullHdAccess = 10;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ impl TryFrom<ProtobufPermissionType> for PermissionType {
|
|||
Ok(PermissionType::MessageAndLaunchOtherPlugins)
|
||||
},
|
||||
ProtobufPermissionType::Reconfigure => Ok(PermissionType::Reconfigure),
|
||||
ProtobufPermissionType::FullHdAccess => Ok(PermissionType::FullHdAccess),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,6 +52,7 @@ impl TryFrom<PermissionType> for ProtobufPermissionType {
|
|||
Ok(ProtobufPermissionType::MessageAndLaunchOtherPlugins)
|
||||
},
|
||||
PermissionType::Reconfigure => Ok(ProtobufPermissionType::Reconfigure),
|
||||
PermissionType::FullHdAccess => Ok(ProtobufPermissionType::FullHdAccess),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue