mod cli; pub use cli::{ Action, Cli, docker_credential_helper, exec, get, GlobalArgs, RunArgs, invoke_shortcut, }; pub use platform::{connect, server_addr}; pub mod proto; pub fn show_window(global_args: GlobalArgs) -> anyhow::Result<()> { let invoke = cli::InvokeArgs { shortcut_action: proto::ShortcutAction::ShowWindow }; cli::invoke_shortcut(invoke, global_args) } #[cfg(unix)] mod platform { use std::path::PathBuf; use tokio::net::UnixStream; pub async fn connect(addr: Option) -> Result { let path = addr.unwrap_or_else(|| server_addr("creddy-server")); UnixStream::connect(&path).await } pub fn server_addr(sock_name: &str) -> PathBuf { let mut path = dirs::runtime_dir() .unwrap_or_else(|| PathBuf::from("/tmp")); if cfg!(debug_assertions) { path.push(format!("{sock_name}.dev.sock")) } else { path.push(format!("{sock_name}.sock")); } path } } #[cfg(windows)] mod platform { use std::path::PathBuf; use std::time::Duration; use tokio::net::windows::named_pipe::{NamedPipeClient, ClientOptions}; use windows::Win32::Foundation::ERROR_PIPE_BUSY; pub async fn connect(addr: Option) -> std::io::Result { let opts = ClientOptions::new(); let pipe_name = addr.unwrap_or_else(|| server_addr("creddy-server")); loop { match opts.open(&pipe_name) { Ok(client) => return Ok(client), Err(e) if e.raw_os_error() == Some(ERROR_PIPE_BUSY.0 as i32) => { tokio::time::sleep(Duration::from_millis(50)).await; }, Err(e) => return Err(e), } } } pub fn server_addr(sock_name: &str) -> PathBuf { if cfg!(debug_assertions) { format!(r"\\.\pipe\{sock_name}.dev").into() } else { format!(r"\\.\pipe\{sock_name}").into() } } }