use std::{collections::HashMap, os::fd::AsFd, path::Path};
use enumflags2::{BitFlags, bitflags};
use futures_util::Stream;
use serde_repr::{Deserialize_repr, Serialize_repr};
use zbus::zvariant::{Fd, Type};
use crate::{Error, FilePath, Pid, proxy::Proxy};
#[bitflags]
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Copy, Clone, Debug, Type)]
#[repr(u32)]
pub enum HostCommandFlags {
#[doc(alias = "FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV")]
ClearEnv,
#[doc(alias = "FLATPAK_HOST_COMMAND_FLAGS_WATCH_BUS")]
WatchBus,
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.Flatpak.Development")]
pub struct Development(Proxy<'static>);
impl Development {
pub async fn new() -> Result<Self, Error> {
let proxy = Proxy::new_flatpak_development("org.freedesktop.Flatpak.Development").await?;
Ok(Self(proxy))
}
pub async fn with_connection(connection: zbus::Connection) -> Result<Self, Error> {
let proxy = Proxy::new_flatpak_development_with_connection(
connection,
"org.freedesktop.Flatpak.Development",
)
.await?;
Ok(Self(proxy))
}
#[doc(alias = "HostCommandExited")]
pub async fn receive_spawn_exited(&self) -> Result<impl Stream<Item = (u32, u32)>, Error> {
self.0.signal("HostCommandExited").await
}
pub async fn host_command(
&self,
cwd_path: impl AsRef<Path>,
argv: &[impl AsRef<Path>],
fds: HashMap<u32, impl AsFd>,
envs: HashMap<&str, &str>,
flags: BitFlags<HostCommandFlags>,
) -> Result<u32, Error> {
let cwd_path = FilePath::new(cwd_path)?;
let argv = argv
.iter()
.map(FilePath::new)
.collect::<Result<Vec<FilePath>, _>>()?;
let fds: HashMap<u32, Fd> = fds.iter().map(|(k, val)| (*k, Fd::from(val))).collect();
self.0
.call("HostCommand", &(cwd_path, argv, fds, envs, flags))
.await
}
#[doc(alias = "SpawnSignal")]
#[doc(alias = "xdp_portal_spawn_signal")]
pub async fn host_command_signal(
&self,
pid: Pid,
signal: u32,
to_process_group: bool,
) -> Result<(), Error> {
self.0
.call("HostCommandSignal", &(pid, signal, to_process_group))
.await
}
}
impl std::ops::Deref for Development {
type Target = zbus::Proxy<'static>;
fn deref(&self) -> &Self::Target {
&self.0
}
}