diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index 78118594..36cad209 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -29,7 +29,6 @@ jobs: matrix: os: - macos-14 - - macos-12 - ubuntu-latest - windows-latest defaults: diff --git a/Cargo.lock b/Cargo.lock index b39654aa..f1107cea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,7 +149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", - "event-listener 5.2.0", + "event-listener 5.3.0", "event-listener-strategy 0.5.1", "futures-core", "pin-project-lite", @@ -710,7 +710,7 @@ dependencies = [ [[package]] name = "cargo-playdate" -version = "0.4.0-beta.1" +version = "0.4.0-beta.2" dependencies = [ "anstyle", "anyhow", @@ -1264,6 +1264,18 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "eject" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0891d287365c958cb4b5b2d6a29e34a1f5111879fa951de7ccaf55540ae88e7" +dependencies = [ + "memoffset 0.6.5", + "nix 0.25.1", + "thiserror", + "windows 0.39.0", +] + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -1378,9 +1390,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" dependencies = [ "concurrent-queue", "parking", @@ -1403,7 +1415,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" dependencies = [ - "event-listener 5.2.0", + "event-listener 5.3.0", "pin-project-lite", ] @@ -2458,9 +2470,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -3151,6 +3163,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.7.1" @@ -3252,6 +3273,20 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.6.5", + "pin-utils", +] + [[package]] name = "nix" version = "0.26.4" @@ -3261,7 +3296,7 @@ dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", - "memoffset", + "memoffset 0.7.1", "pin-utils", ] @@ -3814,11 +3849,12 @@ dependencies = [ [[package]] name = "playdate-device" -version = "0.2.1" +version = "0.2.2" dependencies = [ "async-std", "clap", "const-hex", + "eject", "futures", "futures-lite 2.3.0", "hex", @@ -3838,7 +3874,7 @@ dependencies = [ "tracing", "udev", "usb-ids", - "windows", + "windows 0.54.0", ] [[package]] @@ -3935,7 +3971,7 @@ dependencies = [ [[package]] name = "playdate-tool" -version = "0.2.3" +version = "0.3.0" dependencies = [ "clap", "console-subscriber", @@ -4094,9 +4130,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" dependencies = [ "bytes", "prost-derive", @@ -4104,12 +4140,12 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2", "quote", "syn 2.0.58", @@ -4117,9 +4153,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" dependencies = [ "prost", ] @@ -5499,6 +5535,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" +dependencies = [ + "windows_aarch64_msvc 0.39.0", + "windows_i686_gnu 0.39.0", + "windows_i686_msvc 0.39.0", + "windows_x86_64_gnu 0.39.0", + "windows_x86_64_msvc 0.39.0", +] + [[package]] name = "windows" version = "0.54.0" @@ -5598,6 +5647,12 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +[[package]] +name = "windows_aarch64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -5610,6 +5665,12 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +[[package]] +name = "windows_i686_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -5622,6 +5683,12 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +[[package]] +name = "windows_i686_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -5634,6 +5701,12 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +[[package]] +name = "windows_x86_64_gnu" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -5658,6 +5731,12 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +[[package]] +name = "windows_x86_64_msvc" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" diff --git a/cargo/Cargo.toml b/cargo/Cargo.toml index 4b1f2e98..0176f35e 100644 --- a/cargo/Cargo.toml +++ b/cargo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-playdate" -version = "0.4.0-beta.1" +version = "0.4.0-beta.2" readme = "README.md" description = "Build tool for neat yellow console." keywords = ["playdate", "build", "cargo", "plugin", "cargo-subcommand"] diff --git a/support/device/Cargo.toml b/support/device/Cargo.toml index 1c1edaad..97a48219 100644 --- a/support/device/Cargo.toml +++ b/support/device/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-device" -version = "0.2.1" +version = "0.2.2" readme = "README.md" description = "Cross-platform interface Playdate device, async & blocking." keywords = ["playdate", "usb", "serial"] @@ -73,6 +73,11 @@ const-hex = "1.11" [target.'cfg(target_os = "linux")'.dependencies] udev = "0.8" lfs-core = "0.11" +eject = "0.1" + +[target.'cfg(target_os = "windows")'.dependencies.eject] +version = "0.1" +optional = true [target.'cfg(target_os = "windows")'.dependencies.windows] version = "0.54.0" diff --git a/support/device/src/mount/linux.rs b/support/device/src/mount/linux.rs index ecd56578..334a7015 100644 --- a/support/device/src/mount/linux.rs +++ b/support/device/src/mount/linux.rs @@ -30,7 +30,7 @@ pub struct Volume { } impl Volume { - fn new(path: PathBuf, part: PathBuf, disk: PathBuf, dev_sysfs: PathBuf) -> Self { + pub fn new(path: PathBuf, part: PathBuf, disk: PathBuf, dev_sysfs: PathBuf) -> Self { Self { path, part_node: part, disk_node: disk, @@ -48,7 +48,7 @@ impl Volume { } -mod unmount { +pub mod unmount { use futures::TryFutureExt; use super::*; @@ -61,29 +61,32 @@ mod unmount { fn unmount_blocking(&self) -> Result<(), Error> { use std::process::Command; - - let res = eject(self).status() - .map_err(Error::from) - .and_then(|res| res.exit_ok().map_err(Error::from)) - .or_else(|err| -> Result<(), Error> { - unmount(self).status() - .map_err(Error::from) - .and_then(|res| res.exit_ok().map_err(Error::from)) - .map_err(|err2| Error::chain(err2, [err])) - }) - .or_else(move |err| -> Result<(), Error> { - udisksctl_unmount(self).status() - .map_err(Error::from) - .and_then(|res| res.exit_ok().map_err(Error::from)) - .map_err(|err2| Error::chain(err2, [err])) - }) - .or_else(move |err| -> Result<(), Error> { - udisks_unmount(self).status() - .map_err(Error::from) - .and_then(|res| res.exit_ok().map_err(Error::from)) - .map_err(|err2| Error::chain(err2, [err])) - }) - .inspect(|_| trace!("unmounted {self}")); + let res = + unmount_eject(&self).or_else(|err| { + eject(self).status() + .map_err(Error::from) + .and_then(|res| res.exit_ok().map_err(Error::from)) + .map_err(|err2| Error::chain(err2, [err])) + }) + .or_else(|err| -> Result<(), Error> { + unmount(self).status() + .map_err(Error::from) + .and_then(|res| res.exit_ok().map_err(Error::from)) + .map_err(|err2| Error::chain(err2, [err])) + }) + .or_else(move |err| -> Result<(), Error> { + udisksctl_unmount(self).status() + .map_err(Error::from) + .and_then(|res| res.exit_ok().map_err(Error::from)) + .map_err(|err2| Error::chain(err2, [err])) + }) + .or_else(move |err| -> Result<(), Error> { + udisks_unmount(self).status() + .map_err(Error::from) + .and_then(|res| res.exit_ok().map_err(Error::from)) + .map_err(|err2| Error::chain(err2, [err])) + }) + .inspect(|_| trace!("unmounted {self}")); // TODO: use `udisks_power_off` also as fallback for `udisksctl_power_off`: Command::from(udisksctl_power_off(self)).status() @@ -108,65 +111,80 @@ mod unmount { #[cfg(feature = "async-std")] use async_std::process::Command; - - Command::from(eject(self)).status() - .map_err(Error::from) - .and_then(|res| ready(res.exit_ok().map_err(Error::from))) - .or_else(|err| { - Command::from(unmount(self)).status() - .map_err(|err2| Error::chain(err2, [err])) - .and_then(|res| { - ready(res.exit_ok().map_err(Error::from)) - }) - }) - .or_else(|err| { - Command::from(udisksctl_unmount(self)).status() - .map_err(|err2| { - Error::chain(err2, [err]) - }) - .and_then(|res| { - ready( - res.exit_ok() - .map_err(Error::from), + async { unmount_eject(&self) }.or_else(|err| { + Command::from(eject(self)).status() + .map_err(|err2| Error::chain(err2, [err])) + .and_then(|res| { + ready(res.exit_ok().map_err(Error::from)) + }) + }) + .or_else(|err| { + Command::from(unmount(self)).status() + .map_err(|err2| Error::chain(err2, [err])) + .and_then(|res| { + ready(res.exit_ok().map_err(Error::from)) + }) + }) + .or_else(|err| { + Command::from(udisksctl_unmount(self)).status() + .map_err(|err2| { + Error::chain(err2, [err]) + }) + .and_then(|res| { + ready( + res.exit_ok() + .map_err(Error::from), ) - }) - }) - .or_else(|err| { - Command::from(udisks_unmount(self)).status() - .map_err(|err2| { - Error::chain(err2, [err]) - }) - .and_then(|res| { - ready( - res.exit_ok() - .map_err(Error::from), + }) + }) + .or_else(|err| { + Command::from(udisks_unmount(self)).status() + .map_err(|err2| { + Error::chain(err2, [err]) + }) + .and_then(|res| { + ready( + res.exit_ok() + .map_err(Error::from), ) - }) - }) - .inspect_ok(|_| trace!("unmounted {self}")) - .then(|res| { - // TODO: use `udisks_power_off` also as fallback for `udisksctl_power_off`: - Command::from(udisksctl_power_off(self)).status() - .map_err(Error::from) - .and_then(|res| { - ready( + }) + }) + .inspect_ok(|_| trace!("unmounted {self}")) + .then(|res| { + // TODO: use `udisks_power_off` also as fallback for `udisksctl_power_off`: + Command::from(udisksctl_power_off(self)).status() + .map_err(Error::from) + .and_then(|res| { + ready( res.exit_ok() .map_err(Error::from), ) - }) - .map_err(|err2| { - if let Some(err) = res.err() { - Error::chain(err2, [err]) - } else { - err2 - } - }) - }) - .await + }) + .map_err(|err2| { + if let Some(err) = res.err() + { + Error::chain(err2, [err]) + } else { + err2 + } + }) + }) + .await } } + #[cfg_attr(feature = "tracing", tracing::instrument())] + pub fn unmount_eject(vol: &Volume) -> Result<(), Error> { + use eject::device::Device; + + let drive = Device::open(&vol.disk_node).map_err(std::io::Error::from)?; + drive.eject().map_err(std::io::Error::from)?; + trace!("Ejected {}", &vol.disk_node.display()); + Ok(()) + } + + fn eject(vol: &Volume) -> std::process::Command { let mut cmd = std::process::Command::new("eject"); cmd.arg(vol.path().as_ref()); diff --git a/support/device/src/mount/mac.rs b/support/device/src/mount/mac.rs index c51d1e1a..24b9c1fa 100644 --- a/support/device/src/mount/mac.rs +++ b/support/device/src/mount/mac.rs @@ -17,6 +17,10 @@ pub struct Volume { path: PathBuf, } +impl Volume { + pub fn new(path: PathBuf) -> Self { Self { path } } +} + impl From for Volume { fn from(path: PathBuf) -> Self { Self { path } } } @@ -31,7 +35,7 @@ impl Volume { } -mod unmount { +pub mod unmount { use super::*; use crate::mount::Unmount; use crate::mount::UnmountAsync; diff --git a/support/device/src/mount/win.rs b/support/device/src/mount/win.rs index 83dc6b50..9ebb17d9 100644 --- a/support/device/src/mount/win.rs +++ b/support/device/src/mount/win.rs @@ -25,6 +25,14 @@ pub struct Volume { serial_number: Option, } +impl Volume { + pub fn new(letter: char) -> Self { + Self { letter, + disk_number: None, + serial_number: None } + } +} + impl std::fmt::Display for Volume { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.letter.fmt(f) } } @@ -34,7 +42,7 @@ impl Volume { pub fn path(&self) -> Cow<'_, Path> { PathBuf::from(format!("{}:", self.letter)).into() } } -mod unmount { +pub mod unmount { use futures::FutureExt; use futures::TryFutureExt; @@ -46,24 +54,29 @@ mod unmount { impl Unmount for Volume { #[cfg_attr(feature = "tracing", tracing::instrument())] fn unmount_blocking(&self) -> Result<(), Error> { - winapi::unmount(self.letter).or_else(|err| { - if std::env::var_os("SHELL").is_some() { - eject_sh(self.letter).status() - .map_err(Error::from) - .and_then(|res| { - res.exit_ok().map_err(Error::from) - }) - .map_err(|err2| Error::chain(err2, [err])) - } else { - Err(err) - } - }) - .or_else(|err| { - eject_pw(self.letter).status() - .map_err(Error::from) - .and_then(|res| res.exit_ok().map_err(Error::from)) - .map_err(|err2| Error::chain(err2, [err])) - }) + #[cfg(feature = "eject")] + let res = unmount_eject(&self).or_else(|err| { + winapi::unmount(self.letter).map_err(|err2| Error::chain(err2, [err])) + }); + #[cfg(not(feature = "eject"))] + let res = winapi::unmount(self.letter); + + res.or_else(|err| { + if std::env::var_os("SHELL").is_some() { + eject_sh(self.letter).status() + .map_err(Error::from) + .and_then(|res| res.exit_ok().map_err(Error::from)) + .map_err(|err2| Error::chain(err2, [err])) + } else { + Err(err) + } + }) + .or_else(|err| { + eject_pw(self.letter).status() + .map_err(Error::from) + .and_then(|res| res.exit_ok().map_err(Error::from)) + .map_err(|err2| Error::chain(err2, [err])) + }) } } @@ -71,31 +84,56 @@ mod unmount { #[cfg_attr(feature = "tracing", tracing::instrument())] async fn unmount(&self) -> Result<(), Error> { use futures_lite::future::ready; + use futures::future::lazy; #[cfg(all(feature = "tokio", not(feature = "async-std")))] use tokio::process::Command; #[cfg(feature = "async-std")] use async_std::process::Command; - futures::future::lazy(|_| winapi::unmount(self.letter)).or_else(|err| { - if std::env::var_os("SHELL").is_some() { - Command::from(eject_sh(self.letter)).status() - .map_err(|err2| Error::chain(err2, [err])) - .and_then(|res| ready(res.exit_ok().map_err(Error::from))) - .left_future() - } else { - ready(Err(err)).right_future() - } - }) - .or_else(|err| { - Command::from(eject_pw(self.letter)).status() - .map_err(|err2| Error::chain(err2, [err])) - .and_then(|res| ready(res.exit_ok().map_err(Error::from))) - }) - .await + #[cfg(feature = "eject")] + let fut = lazy(|_| unmount_eject(&self)).or_else(|err| { + lazy(|_| { + winapi::unmount(self.letter).map_err(|err2| { + Error::chain(err2, [err]) + }) + }) + }); + #[cfg(not(feature = "eject"))] + let fut = lazy(|_| winapi::unmount(self.letter)); + + fut.or_else(|err| { + if std::env::var_os("SHELL").is_some() { + Command::from(eject_sh(self.letter)).status() + .map_err(|err2| Error::chain(err2, [err])) + .and_then(|res| ready(res.exit_ok().map_err(Error::from))) + .left_future() + } else { + ready(Err(err)).right_future() + } + }) + .or_else(|err| { + Command::from(eject_pw(self.letter)).status() + .map_err(|err2| Error::chain(err2, [err])) + .and_then(|res| ready(res.exit_ok().map_err(Error::from))) + }) + .await } } + #[cfg(feature = "eject")] + #[cfg_attr(feature = "tracing", tracing::instrument())] + pub fn unmount_eject(vol: &Volume) -> Result<(), Error> { + use eject::device::Device; + + let path = to_vol_path_short(vol.letter); + let drive = Device::open(&path).map_err(std::io::Error::from)?; + drive.eject().map_err(std::io::Error::from)?; + trace!("Ejected {}", vol.letter); + Ok(()) + } + + fn eject_sh(letter: char) -> std::process::Command { let string = to_vol_path_short(letter); let mut cmd = std::process::Command::new("eject"); diff --git a/support/tool/Cargo.toml b/support/tool/Cargo.toml index fcf5d71b..ac95cbd8 100644 --- a/support/tool/Cargo.toml +++ b/support/tool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "playdate-tool" -version = "0.2.3" +version = "0.3.0" readme = "README.md" description = "Tool for interaction with Playdate device and sim." keywords = ["playdate", "usb", "utility"] @@ -55,6 +55,8 @@ workspace = true [features] +eject = ["device/eject"] # windows only, enable one more unmount method + tracing = [ "dep:tracing", "tracing-subscriber", diff --git a/support/tool/README.md b/support/tool/README.md index 8b5172c9..1c58b9e5 100644 --- a/support/tool/README.md +++ b/support/tool/README.md @@ -46,6 +46,11 @@ To build playdate-tool you're need: cargo install playdate-tool ``` +Also with optional feature `eject`, windows only: +```bash +cargo install playdate-tool --feature=eject +``` + ## Usage diff --git a/support/tool/src/cli.rs b/support/tool/src/cli.rs index a11437ec..d6a193ce 100644 --- a/support/tool/src/cli.rs +++ b/support/tool/src/cli.rs @@ -100,6 +100,18 @@ pub struct Dbg { pub enum DbgCmd { /// Inspect device(s) state. Inspect, + + /// New way to eject. + /// + /// Argument `query` - The path of the device. + /// + /// On **Linux** this is the path of the device's file, which almost always + /// will be inside `/dev`. For example: `/dev/cdrom`. Do not use paths to a drive's mount point. + /// + /// On **Windows** this is the path you would use with `CreateFile` but + /// without the `\\?\` or `\\.\` prefix. Examples of correct paths + /// include `D:` (but not `D:\`), `CdRom0` and `Volume{26a21bda-a627-11d7-9931-806e6f6e6963}`. + Eject { path: PathBuf }, } diff --git a/support/tool/src/main.rs b/support/tool/src/main.rs index 69055ccb..19bb7cd2 100644 --- a/support/tool/src/main.rs +++ b/support/tool/src/main.rs @@ -78,7 +78,7 @@ async fn main() -> miette::Result<()> { #[cfg(not(feature = "tracing"))] { #[cfg(debug_assertions)] - std::env::set_var("RUST_LOG", "trace"); + std::env::set_var("RUST_LOG", "trace,nusb=info"); env_logger::Builder::from_env(env_logger::Env::default()).format_indent(Some(3)) .format_module_path(false) .format_target(true) @@ -120,6 +120,7 @@ async fn main() -> miette::Result<()> { } +#[cfg(debug_assertions)] mod debug { use super::*; @@ -128,6 +129,7 @@ mod debug { use cli::DbgCmd as Cmd; match cmd { Cmd::Inspect => inspect().await?, + Cmd::Eject { path } => eject(path).await?, } Ok(()) } @@ -145,6 +147,31 @@ mod debug { Ok(()) } + + pub async fn eject(path: PathBuf) -> Result<(), Error> { + println!("Ejecting {path:?}"); + + #[cfg(target_os = "linux")] + { + let vol = pddev::mount::volume::Volume::new(PathBuf::new(), PathBuf::new(), path, PathBuf::new()); + pddev::mount::volume::unmount::unmount_eject(&vol)?; + } + + #[cfg(all(target_os = "windows", feature = "device/eject"))] + { + let vol = pddev::mount::volume::Volume::new( + path.file_name() + .expect("drive name expected") + .to_string_lossy() + .chars() + .next() + .expect("volume name letter"), + ); + pddev::mount::volume::unmount::unmount_eject(&vol)?; + } + + Ok(()) + } } @@ -369,6 +396,10 @@ async fn list(format: cli::Format, kind: cli::DeviceKind) -> Result<(), error::E cli::DeviceKind::Storage => volumes_for_map(usb::discover::devices_storage()?).await?, cli::DeviceKind::Data => usb::discover::devices_data()?.map(|dev| (dev, None)).collect(), }.into_iter() + .inspect(|(dev, vol)| { + debug!("dev: {dev:?}"); + debug!("vol: {vol:?}"); + }) .map(|(dev, vol)| (dev, vol.map(|v| v.path().to_path_buf()))); match format {