make windows work again

This commit is contained in:
Joseph Montanaro 2025-01-02 13:15:49 -05:00
parent cd4c613758
commit bf62054c2b
13 changed files with 2493 additions and 88 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "creddy", "name": "creddy",
"version": "0.4.9", "version": "0.6.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "creddy", "name": "creddy",
"version": "0.4.9", "version": "0.6.3",
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.0.0-beta.13", "@tauri-apps/api": "^2.0.0-beta.13",
"@tauri-apps/plugin-dialog": "^2.0.0-beta.5", "@tauri-apps/plugin-dialog": "^2.0.0-beta.5",

View File

@ -1,6 +1,6 @@
{ {
"name": "creddy", "name": "creddy",
"version": "0.6.3", "version": "0.6.4",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",

67
src-tauri/Cargo.lock generated
View File

@ -1086,7 +1086,7 @@ dependencies = [
"cocoa-foundation", "cocoa-foundation",
"core-foundation", "core-foundation",
"core-graphics", "core-graphics",
"foreign-types 0.5.0", "foreign-types",
"libc", "libc",
"objc", "objc",
] ]
@ -1167,7 +1167,7 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"core-foundation", "core-foundation",
"core-graphics-types", "core-graphics-types",
"foreign-types 0.5.0", "foreign-types",
"libc", "libc",
] ]
@ -1217,7 +1217,7 @@ dependencies = [
[[package]] [[package]]
name = "creddy" name = "creddy"
version = "0.6.3" version = "0.6.4"
dependencies = [ dependencies = [
"argon2", "argon2",
"auto-launch", "auto-launch",
@ -1231,7 +1231,6 @@ dependencies = [
"futures", "futures",
"is-terminal", "is-terminal",
"once_cell", "once_cell",
"openssl",
"rfd 0.13.0", "rfd 0.13.0",
"rsa", "rsa",
"serde", "serde",
@ -1262,7 +1261,7 @@ dependencies = [
[[package]] [[package]]
name = "creddy_cli" name = "creddy_cli"
version = "0.6.0" version = "0.6.4"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@ -1270,6 +1269,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
"windows 0.51.1",
] ]
[[package]] [[package]]
@ -1876,15 +1876,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared 0.1.1",
]
[[package]] [[package]]
name = "foreign-types" name = "foreign-types"
version = "0.5.0" version = "0.5.0"
@ -1892,7 +1883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [ dependencies = [
"foreign-types-macros", "foreign-types-macros",
"foreign-types-shared 0.3.1", "foreign-types-shared",
] ]
[[package]] [[package]]
@ -1906,12 +1897,6 @@ dependencies = [
"syn 2.0.68", "syn 2.0.68",
] ]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]] [[package]]
name = "foreign-types-shared" name = "foreign-types-shared"
version = "0.3.1" version = "0.3.1"
@ -3473,50 +3458,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl"
version = "0.10.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
dependencies = [
"bitflags 2.6.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.68",
]
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
version = "0.1.5" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]] [[package]]
name = "option-ext" name = "option-ext"
version = "0.2.0" version = "0.2.0"
@ -4867,7 +4814,7 @@ dependencies = [
"bytemuck", "bytemuck",
"cfg_aliases", "cfg_aliases",
"core-graphics", "core-graphics",
"foreign-types 0.5.0", "foreign-types",
"js-sys", "js-sys",
"log", "log",
"objc2", "objc2",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "creddy" name = "creddy"
version = "0.6.3" version = "0.6.4"
description = "A friendly AWS credentials manager" description = "A friendly AWS credentials manager"
authors = ["Joseph Montanaro"] authors = ["Joseph Montanaro"]
license = "" license = ""
@ -22,6 +22,7 @@ dirs = "5.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
tokio = { version = ">=1.19", features = ["full"] } tokio = { version = ">=1.19", features = ["full"] }
windows = { version = "0.51.1", features = ["Win32_Foundation", "Win32_System_Pipes"] }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -47,7 +48,6 @@ is-terminal = "0.4.7"
argon2 = { version = "0.5.0", features = ["std"] } argon2 = { version = "0.5.0", features = ["std"] }
chacha20poly1305 = { version = "0.10.1", features = ["std"] } chacha20poly1305 = { version = "0.10.1", features = ["std"] }
which = "4.4.0" which = "4.4.0"
windows = { version = "0.51.1", features = ["Win32_Foundation", "Win32_System_Pipes"] }
time = "0.3.31" time = "0.3.31"
tauri-plugin-global-shortcut = "2.0.0-beta.6" tauri-plugin-global-shortcut = "2.0.0-beta.6"
tauri-plugin-os = "2.0.0-beta.6" tauri-plugin-os = "2.0.0-beta.6"
@ -63,11 +63,14 @@ sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio", "uuid"] }
tokio = { workspace = true } tokio = { workspace = true }
tokio-util = { version = "0.7.11", features = ["codec"] } tokio-util = { version = "0.7.11", features = ["codec"] }
futures = "0.3.30" futures = "0.3.30"
openssl = "0.10.64" # openssl = { version = "0.10.64", features = ["vendored"] }
rsa = "0.9.6" rsa = "0.9.6"
sha2 = "0.10.8" sha2 = "0.10.8"
ssh-encoding = "0.2.0" ssh-encoding = "0.2.0"
[target.'cfg(windows)'.dependencies]
windows = { workspace = true }
[features] [features]
# by default Tauri runs in production mode # by default Tauri runs in production mode
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL

View File

@ -1,6 +1,6 @@
[package] [package]
name = "creddy_cli" name = "creddy_cli"
version = "0.6.0" version = "0.6.4"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
@ -10,3 +10,6 @@ dirs = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
[target.'cfg(windows)'.dependencies]
windows = { workspace = true }

View File

@ -2,8 +2,6 @@ use std::path::PathBuf;
use std::process::Command as ChildCommand; use std::process::Command as ChildCommand;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::process::CommandExt; use std::os::unix::process::CommandExt;
#[cfg(windows)]
use std::time::Duration;
use anyhow::{bail, Context}; use anyhow::{bail, Context};
use clap::{ use clap::{
@ -184,17 +182,10 @@ pub fn exec(args: ExecArgs, global: GlobalArgs) -> anyhow::Result<()> {
#[cfg(windows)] #[cfg(windows)]
{ {
let mut child = match cmd.spawn() { let mut child = cmd.spawn()
Ok(c) => c, .with_context(|| format!("Failed to execute command: {}", args.command.join(" ")))?;
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
let name: OsString = cmd_name.into();
return Err(ExecError::NotFound(name).into());
}
Err(e) => return Err(ExecError::ExecutionFailed(e).into()),
};
let status = child.wait() let status = child.wait()
.map_err(|e| ExecError::ExecutionFailed(e))?; .with_context(|| format!("Failed to execute command: {}", args.command.join(" ")))?;
std::process::exit(status.code().unwrap_or(1)); std::process::exit(status.code().unwrap_or(1));
}; };
} }

View File

@ -47,12 +47,31 @@ mod platform {
#[cfg(windows)] #[cfg(windows)]
mod platform { mod platform {
pub fn server_addr(sock_name: &str) -> String { 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<PathBuf>) -> std::io::Result<NamedPipeClient> {
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) { if cfg!(debug_assertions) {
format!(r"\\.\pipe\{sock_name}.dev") format!(r"\\.\pipe\{sock_name}.dev").into()
} }
else { else {
format!(r"\\.\pipe\{sock_name}") format!(r"\\.\pipe\{sock_name}").into()
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -201,6 +201,10 @@ pub enum HandlerError {
Signature(#[from] signature::Error), Signature(#[from] signature::Error),
#[error(transparent)] #[error(transparent)]
Encoding(#[from] ssh_encoding::Error), Encoding(#[from] ssh_encoding::Error),
#[cfg(windows)]
#[error(transparent)]
Windows(#[from] windows::core::Error),
} }

View File

@ -188,6 +188,7 @@ mod platform {
#[cfg(windows)] #[cfg(windows)]
mod platform { mod platform {
use std::os::windows::io::AsRawHandle; use std::os::windows::io::AsRawHandle;
use std::path::PathBuf;
use tokio::net::windows::named_pipe::{ use tokio::net::windows::named_pipe::{
NamedPipeServer, NamedPipeServer,
ServerOptions, ServerOptions,
@ -201,7 +202,7 @@ mod platform {
pub type Stream = NamedPipeServer; pub type Stream = NamedPipeServer;
pub fn bind(sock_name: &str) -> std::io::Result<(String, NamedPipeServer)> { pub fn bind(sock_name: &str) -> std::io::Result<(NamedPipeServer, PathBuf)> {
let addr = creddy_cli::server_addr(sock_name); let addr = creddy_cli::server_addr(sock_name);
let listener = ServerOptions::new() let listener = ServerOptions::new()
.first_pipe_instance(true) .first_pipe_instance(true)
@ -209,7 +210,7 @@ mod platform {
Ok((listener, addr)) Ok((listener, addr))
} }
pub async fn accept(listener: &mut NamedPipeServer, addr: &String) -> Result<(NamedPipeServer, u32), HandlerError> { pub async fn accept(listener: &mut NamedPipeServer, addr: &PathBuf) -> Result<(NamedPipeServer, u32), HandlerError> {
// connect() just waits for a client to connect, it doesn't return anything // connect() just waits for a client to connect, it doesn't return anything
listener.connect().await?; listener.connect().await?;

View File

@ -50,7 +50,7 @@
} }
}, },
"productName": "creddy", "productName": "creddy",
"version": "0.6.3", "version": "0.6.4",
"identifier": "creddy", "identifier": "creddy",
"plugins": {}, "plugins": {},
"app": { "app": {

View File

@ -91,7 +91,7 @@
{#if launchTerminalError} {#if launchTerminalError}
<div class="toast"> <div class="toast">
<div class="alert alert-error shadow-lg"> <div class="alert alert-error text-wrap shadow-lg">
<span>{launchTerminalError.msg || launchTerminalError}</span> <span>{launchTerminalError.msg || launchTerminalError}</span>
<div> <div>
<button class="btn btn-alert-error" on:click={() => launchTerminalError = null}> <button class="btn btn-alert-error" on:click={() => launchTerminalError = null}>

View File

@ -115,7 +115,7 @@
{#if error} {#if error}
<div transition:fly={{y: 100, easing: backInOut, duration: 400}} class="toast"> <div transition:fly={{y: 100, easing: backInOut, duration: 400}} class="toast">
<div class="alert alert-error no-animation"> <div class="alert alert-error no-animation text-wrap">
<div> <div>
<span>{error}</span> <span>{error}</span>
</div> </div>
@ -127,7 +127,7 @@
</div> </div>
{:else if configModified} {:else if configModified}
<div transition:fly={{y: 100, easing: backInOut, duration: 400}} class="toast"> <div transition:fly={{y: 100, easing: backInOut, duration: 400}} class="toast">
<div class="alert shadow-lg no-animation"> <div class="alert shadow-lg no-animation text-wrap">
<span>You have unsaved changes.</span> <span>You have unsaved changes.</span>
<div> <div>