From 0af367f7d4f94624f1c13ffc282f62b930bd5316 Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Mon, 24 Feb 2025 17:10:30 +0200 Subject: [PATCH 1/2] refactor(single-instance): improve userdata ptr handling (#2453) * fix(single-instance): fix null pointer dereference panic on Windows * fmt --- .changes/single-instance-nullpointer-deref.md | 2 +- .../examples/vanilla/src-tauri/build.rs | 2 +- .../examples/vanilla/src-tauri/rustfmt.toml | 14 --- .../examples/vanilla/src-tauri/src/main.rs | 17 ++-- .../src/platform_impl/windows.rs | 92 ++++++++++++------- 5 files changed, 68 insertions(+), 59 deletions(-) delete mode 100644 plugins/single-instance/examples/vanilla/src-tauri/rustfmt.toml diff --git a/.changes/single-instance-nullpointer-deref.md b/.changes/single-instance-nullpointer-deref.md index 7c3e7ea5..e13a9828 100644 --- a/.changes/single-instance-nullpointer-deref.md +++ b/.changes/single-instance-nullpointer-deref.md @@ -2,4 +2,4 @@ single-instance: patch --- -Fixed an issue that caused `null pointer dereference occurred` errors on rust nightly. +Fixed `null pointer dereference` panic on rust nightly on Windows. diff --git a/plugins/single-instance/examples/vanilla/src-tauri/build.rs b/plugins/single-instance/examples/vanilla/src-tauri/build.rs index b055ec37..5ebf8d2f 100644 --- a/plugins/single-instance/examples/vanilla/src-tauri/build.rs +++ b/plugins/single-instance/examples/vanilla/src-tauri/build.rs @@ -3,5 +3,5 @@ // SPDX-License-Identifier: MIT fn main() { - tauri_build::build() + tauri_build::build() } diff --git a/plugins/single-instance/examples/vanilla/src-tauri/rustfmt.toml b/plugins/single-instance/examples/vanilla/src-tauri/rustfmt.toml deleted file mode 100644 index 550a0985..00000000 --- a/plugins/single-instance/examples/vanilla/src-tauri/rustfmt.toml +++ /dev/null @@ -1,14 +0,0 @@ -max_width = 100 -hard_tabs = false -tab_spaces = 2 -newline_style = "Auto" -use_small_heuristics = "Default" -reorder_imports = true -reorder_modules = true -remove_nested_parens = true -edition = "2021" -merge_derives = true -use_try_shorthand = false -use_field_init_shorthand = false -force_explicit_abi = true -imports_granularity = "Crate" diff --git a/plugins/single-instance/examples/vanilla/src-tauri/src/main.rs b/plugins/single-instance/examples/vanilla/src-tauri/src/main.rs index 49b1a5a6..e736c4f3 100644 --- a/plugins/single-instance/examples/vanilla/src-tauri/src/main.rs +++ b/plugins/single-instance/examples/vanilla/src-tauri/src/main.rs @@ -3,16 +3,15 @@ // SPDX-License-Identifier: MIT #![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" )] fn main() { - tauri::Builder::default() - .plugin(tauri_plugin_cli::init()) - .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { - println!("{}, {argv:?}, {cwd}", app.package_info().name); - })) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); + tauri::Builder::default() + .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { + println!("{}, {argv:?}, {cwd}", app.package_info().name); + })) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); } diff --git a/plugins/single-instance/src/platform_impl/windows.rs b/plugins/single-instance/src/platform_impl/windows.rs index 2f6992ee..832d0803 100644 --- a/plugins/single-instance/src/platform_impl/windows.rs +++ b/plugins/single-instance/src/platform_impl/windows.rs @@ -20,18 +20,38 @@ use windows_sys::Win32::{ }, UI::WindowsAndMessaging::{ self as w32wm, CreateWindowExW, DefWindowProcW, DestroyWindow, FindWindowW, - RegisterClassExW, SendMessageW, GWL_STYLE, GWL_USERDATA, WINDOW_LONG_PTR_INDEX, - WM_COPYDATA, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, - WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, + RegisterClassExW, SendMessageW, CREATESTRUCTW, GWLP_USERDATA, GWL_STYLE, + WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY, WNDCLASSEXW, WS_EX_LAYERED, + WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT, WS_OVERLAPPED, WS_POPUP, WS_VISIBLE, }, }; +const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542; + struct MutexHandle(isize); + struct TargetWindowHandle(isize); -const WMCOPYDATA_SINGLE_INSTANCE_DATA: usize = 1542; +struct UserData { + app: AppHandle, + callback: Box>, +} + +impl UserData { + unsafe fn from_hwnd_raw(hwnd: HWND) -> *mut Self { + GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut Self + } -pub fn init(f: Box>) -> TauriPlugin { + unsafe fn from_hwnd<'a>(hwnd: HWND) -> &'a mut Self { + &mut *Self::from_hwnd_raw(hwnd) + } + + fn run_callback(&mut self, args: Vec, cwd: String) { + (self.callback)(&self.app, args, cwd) + } +} + +pub fn init(callback: Box>) -> TauriPlugin { plugin::Builder::new("single-instance") .setup(|app, _api| { #[allow(unused_mut)] @@ -54,21 +74,22 @@ pub fn init(f: Box>) -> TauriPlugin { let hwnd = FindWindowW(class_name.as_ptr(), window_name.as_ptr()); if !hwnd.is_null() { - let data = format!( - "{}|{}\0", - std::env::current_dir() - .unwrap_or_default() - .to_str() - .unwrap_or_default(), - std::env::args().collect::>().join("|") - ); + let cwd = std::env::current_dir().unwrap_or_default(); + let cwd = cwd.to_str().unwrap_or_default(); + + let args = std::env::args().collect::>().join("|"); + + let data = format!("{cwd}|{args}\0",); + let bytes = data.as_bytes(); let cds = COPYDATASTRUCT { dwData: WMCOPYDATA_SINGLE_INSTANCE_DATA, cbData: bytes.len() as _, lpData: bytes.as_ptr() as _, }; + SendMessageW(hwnd, WM_COPYDATA, 0, &cds as *const _ as _); + app.cleanup_before_exit(); std::process::exit(0); } @@ -76,15 +97,12 @@ pub fn init(f: Box>) -> TauriPlugin { } else { app.manage(MutexHandle(hmutex as _)); - let hwnd = create_event_target_window::(&class_name, &window_name); - unsafe { - SetWindowLongPtrW( - hwnd, - GWL_USERDATA, - Box::into_raw(Box::new((app.clone(), f))) as _, - ) + let userdata = UserData { + app: app.clone(), + callback, }; - + let userdata = Box::into_raw(Box::new(userdata)); + let hwnd = create_event_target_window::(&class_name, &window_name, userdata); app.manage(TargetWindowHandle(hwnd as _)); } @@ -116,37 +134,43 @@ unsafe extern "system" fn single_instance_window_proc( wparam: WPARAM, lparam: LPARAM, ) -> LRESULT { - let data_ptr = GetWindowLongPtrW(hwnd, GWL_USERDATA) - as *mut (AppHandle, Box>); - - if data_ptr.is_null() { - return DefWindowProcW(hwnd, msg, wparam, lparam); - } - - let (app_handle, callback) = &mut *data_ptr; - match msg { + WM_CREATE => { + let create_struct = &*(lparam as *const CREATESTRUCTW); + let userdata = create_struct.lpCreateParams as *const UserData; + SetWindowLongPtrW(hwnd, GWLP_USERDATA, userdata as _); + 0 + } + WM_COPYDATA => { let cds_ptr = lparam as *const COPYDATASTRUCT; if (*cds_ptr).dwData == WMCOPYDATA_SINGLE_INSTANCE_DATA { + let userdata = UserData::::from_hwnd(hwnd); + let data = CStr::from_ptr((*cds_ptr).lpData as _).to_string_lossy(); let mut s = data.split('|'); let cwd = s.next().unwrap(); let args = s.map(|s| s.to_string()).collect(); - callback(app_handle, args, cwd.to_string()); + + userdata.run_callback(args, cwd.to_string()); } 1 } WM_DESTROY => { - let _ = Box::from_raw(data_ptr); + let userdata = UserData::::from_hwnd_raw(hwnd); + drop(Box::from_raw(userdata)); 0 } _ => DefWindowProcW(hwnd, msg, wparam, lparam), } } -fn create_event_target_window(class_name: &[u16], window_name: &[u16]) -> HWND { +fn create_event_target_window( + class_name: &[u16], + window_name: &[u16], + userdata: *const UserData, +) -> HWND { unsafe { let class = WNDCLASSEXW { cbSize: std::mem::size_of::() as u32, @@ -187,7 +211,7 @@ fn create_event_target_window(class_name: &[u16], window_name: &[u16 std::ptr::null_mut(), std::ptr::null_mut(), GetModuleHandleW(std::ptr::null()), - std::ptr::null(), + userdata as _, ); SetWindowLongPtrW( hwnd, From fbd4d28920755818f17de659fe5701058b2960db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 16:31:28 +0100 Subject: [PATCH 2/2] publish new versions (#2404) Co-authored-by: amrbashir --- .../log-timezone_strategy-loglevel-fix.md | 6 ----- .changes/single-instance-nullpointer-deref.md | 5 ---- .changes/updater-request-error.md | 6 ----- Cargo.lock | 8 +++--- examples/api/CHANGELOG.md | 7 +++++ examples/api/package.json | 4 +-- examples/api/src-tauri/CHANGELOG.md | 7 +++++ examples/api/src-tauri/Cargo.toml | 6 ++--- plugins/log/CHANGELOG.md | 4 +++ plugins/log/Cargo.toml | 2 +- plugins/log/package.json | 2 +- plugins/single-instance/CHANGELOG.md | 4 +++ plugins/single-instance/Cargo.toml | 2 +- plugins/updater/CHANGELOG.md | 4 +++ plugins/updater/Cargo.toml | 2 +- plugins/updater/package.json | 2 +- pnpm-lock.yaml | 26 ++++++++++--------- 17 files changed, 54 insertions(+), 43 deletions(-) delete mode 100644 .changes/log-timezone_strategy-loglevel-fix.md delete mode 100644 .changes/single-instance-nullpointer-deref.md delete mode 100644 .changes/updater-request-error.md diff --git a/.changes/log-timezone_strategy-loglevel-fix.md b/.changes/log-timezone_strategy-loglevel-fix.md deleted file mode 100644 index b3787e0d..00000000 --- a/.changes/log-timezone_strategy-loglevel-fix.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"log": patch -"log-js": patch ---- - -Fix timezone_strategy overwriting previously set LogLevels. diff --git a/.changes/single-instance-nullpointer-deref.md b/.changes/single-instance-nullpointer-deref.md deleted file mode 100644 index e13a9828..00000000 --- a/.changes/single-instance-nullpointer-deref.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -single-instance: patch ---- - -Fixed `null pointer dereference` panic on rust nightly on Windows. diff --git a/.changes/updater-request-error.md b/.changes/updater-request-error.md deleted file mode 100644 index a9f579f9..00000000 --- a/.changes/updater-request-error.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -updater: patch -updater-js: patch ---- - -Fixed an issue that caused the plugin to emit a `ReleaseNotFound` error instead of a `Reqwest` error when the http request in `check()` failed. diff --git a/Cargo.lock b/Cargo.lock index e3404511..dcff853f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,7 +206,7 @@ checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "api" -version = "2.0.17" +version = "2.0.18" dependencies = [ "log", "serde", @@ -6737,7 +6737,7 @@ dependencies = [ [[package]] name = "tauri-plugin-log" -version = "2.2.1" +version = "2.2.2" dependencies = [ "android_logger", "byte-unit", @@ -6882,7 +6882,7 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" -version = "2.2.1" +version = "2.2.2" dependencies = [ "semver", "serde", @@ -6949,7 +6949,7 @@ dependencies = [ [[package]] name = "tauri-plugin-updater" -version = "2.5.0" +version = "2.5.1" dependencies = [ "base64 0.22.1", "dirs 6.0.0", diff --git a/examples/api/CHANGELOG.md b/examples/api/CHANGELOG.md index 6c65df1d..137ca0b6 100644 --- a/examples/api/CHANGELOG.md +++ b/examples/api/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## \[2.0.14] + +### Dependencies + +- Upgraded to `log-js@2.2.2` +- Upgraded to `updater-js@2.5.1` + ## \[2.0.13] ### Dependencies diff --git a/examples/api/package.json b/examples/api/package.json index d07999ba..caa92ca8 100644 --- a/examples/api/package.json +++ b/examples/api/package.json @@ -1,7 +1,7 @@ { "name": "api", "private": true, - "version": "2.0.13", + "version": "2.0.14", "type": "module", "scripts": { "dev": "vite --clearScreen false", @@ -28,7 +28,7 @@ "@tauri-apps/plugin-process": "^2.2.0", "@tauri-apps/plugin-shell": "^2.2.0", "@tauri-apps/plugin-store": "^2.2.0", - "@tauri-apps/plugin-updater": "^2.5.0", + "@tauri-apps/plugin-updater": "^2.5.1", "@zerodevx/svelte-json-view": "1.0.11" }, "devDependencies": { diff --git a/examples/api/src-tauri/CHANGELOG.md b/examples/api/src-tauri/CHANGELOG.md index dc3c417c..dd6e80af 100644 --- a/examples/api/src-tauri/CHANGELOG.md +++ b/examples/api/src-tauri/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## \[2.0.18] + +### Dependencies + +- Upgraded to `log@2.2.2` +- Upgraded to `updater@2.5.1` + ## \[2.0.17] ### Dependencies diff --git a/examples/api/src-tauri/Cargo.toml b/examples/api/src-tauri/Cargo.toml index e38c2e47..51e7f223 100644 --- a/examples/api/src-tauri/Cargo.toml +++ b/examples/api/src-tauri/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "api" publish = false -version = "2.0.17" +version = "2.0.18" description = "An example Tauri Application showcasing the api" edition = "2021" rust-version = { workspace = true } @@ -19,7 +19,7 @@ serde_json = { workspace = true } serde = { workspace = true } tiny_http = "0.12" log = { workspace = true } -tauri-plugin-log = { path = "../../../plugins/log", version = "2.2.1" } +tauri-plugin-log = { path = "../../../plugins/log", version = "2.2.2" } tauri-plugin-fs = { path = "../../../plugins/fs", version = "2.2.0", features = [ "watch", ] } @@ -53,7 +53,7 @@ features = [ [target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] tauri-plugin-cli = { path = "../../../plugins/cli", version = "2.2.0" } tauri-plugin-global-shortcut = { path = "../../../plugins/global-shortcut", version = "2.2.0" } -tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.5.0" } +tauri-plugin-updater = { path = "../../../plugins/updater", version = "2.5.1" } tauri-plugin-window-state = { path = "../../../plugins/window-state", version = "2.2.0" } [target."cfg(any(target_os = \"android\", target_os = \"ios\"))".dependencies] diff --git a/plugins/log/CHANGELOG.md b/plugins/log/CHANGELOG.md index 6c7cbdfe..54fda54d 100644 --- a/plugins/log/CHANGELOG.md +++ b/plugins/log/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## \[2.2.2] + +- [`6b4c3917`](https://github.com/tauri-apps/plugins-workspace/commit/6b4c3917389f4bc489d03b48a837557ac0584175) ([#2401](https://github.com/tauri-apps/plugins-workspace/pull/2401) by [@Seishiin](https://github.com/tauri-apps/plugins-workspace/../../Seishiin)) Fix timezone_strategy overwriting previously set LogLevels. + ## \[2.2.1] - [`784a54a3`](https://github.com/tauri-apps/plugins-workspace/commit/784a54a39094dfbaaa8dd123eb083c04dc6c3bb2) ([#2344](https://github.com/tauri-apps/plugins-workspace/pull/2344) by [@madsmtm](https://github.com/tauri-apps/plugins-workspace/../../madsmtm)) Use `objc2` instead of `objc`. diff --git a/plugins/log/Cargo.toml b/plugins/log/Cargo.toml index 22f0b4e4..e1cec499 100644 --- a/plugins/log/Cargo.toml +++ b/plugins/log/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-plugin-log" -version = "2.2.1" +version = "2.2.2" description = "Configurable logging for your Tauri app." authors = { workspace = true } license = { workspace = true } diff --git a/plugins/log/package.json b/plugins/log/package.json index bcef5bf3..a71b8ea9 100644 --- a/plugins/log/package.json +++ b/plugins/log/package.json @@ -1,6 +1,6 @@ { "name": "@tauri-apps/plugin-log", - "version": "2.2.1", + "version": "2.2.2", "description": "Configurable logging for your Tauri app.", "license": "MIT OR Apache-2.0", "authors": [ diff --git a/plugins/single-instance/CHANGELOG.md b/plugins/single-instance/CHANGELOG.md index e0802b51..77de533a 100644 --- a/plugins/single-instance/CHANGELOG.md +++ b/plugins/single-instance/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## \[2.2.2] + +- [`1ab5f157`](https://github.com/tauri-apps/plugins-workspace/commit/1ab5f1576333174095bc7dad4bef7a8576bb29ab) ([#2452](https://github.com/tauri-apps/plugins-workspace/pull/2452) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed `null pointer dereference` panic on rust nightly on Windows. + ## \[2.2.1] - [`da5c59e2`](https://github.com/tauri-apps/plugins-workspace/commit/da5c59e2fe879d177e3cfd52fcacce85440423cb) ([#2271](https://github.com/tauri-apps/plugins-workspace/pull/2271) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `zbus` dependency to version 5. No API changes. diff --git a/plugins/single-instance/Cargo.toml b/plugins/single-instance/Cargo.toml index edcbdb77..574df414 100644 --- a/plugins/single-instance/Cargo.toml +++ b/plugins/single-instance/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-plugin-single-instance" -version = "2.2.1" +version = "2.2.2" description = "Ensure a single instance of your tauri app is running." authors = { workspace = true } license = { workspace = true } diff --git a/plugins/updater/CHANGELOG.md b/plugins/updater/CHANGELOG.md index e8c2d587..21f5260a 100644 --- a/plugins/updater/CHANGELOG.md +++ b/plugins/updater/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## \[2.5.1] + +- [`6f881293`](https://github.com/tauri-apps/plugins-workspace/commit/6f881293fcd67838f6f3f8063f536292431dd1f7) ([#2439](https://github.com/tauri-apps/plugins-workspace/pull/2439) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused the plugin to emit a `ReleaseNotFound` error instead of a `Reqwest` error when the http request in `check()` failed. + ## \[2.5.0] - [`5369898d`](https://github.com/tauri-apps/plugins-workspace/commit/5369898db7a6098e3e2f43436100ea556d405628) ([#2067](https://github.com/tauri-apps/plugins-workspace/pull/2067) by [@jLynx](https://github.com/tauri-apps/plugins-workspace/../../jLynx)) Fix update installation on macOS when using an user without admin privileges. diff --git a/plugins/updater/Cargo.toml b/plugins/updater/Cargo.toml index cf9e709f..4d462f31 100644 --- a/plugins/updater/Cargo.toml +++ b/plugins/updater/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-plugin-updater" -version = "2.5.0" +version = "2.5.1" description = "In-app updates for Tauri applications." edition = { workspace = true } authors = { workspace = true } diff --git a/plugins/updater/package.json b/plugins/updater/package.json index a47faf25..12c85302 100644 --- a/plugins/updater/package.json +++ b/plugins/updater/package.json @@ -1,6 +1,6 @@ { "name": "@tauri-apps/plugin-updater", - "version": "2.5.0", + "version": "2.5.1", "license": "MIT OR Apache-2.0", "authors": [ "Tauri Programme within The Commons Conservancy" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e7540d3..a7b04740 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,7 +109,7 @@ importers: specifier: ^2.2.0 version: link:../../plugins/store '@tauri-apps/plugin-updater': - specifier: ^2.5.0 + specifier: ^2.5.1 version: link:../../plugins/updater '@zerodevx/svelte-json-view': specifier: 1.0.11 @@ -2428,9 +2428,9 @@ snapshots: - encoding - mocha - '@covector/assemble@0.12.0': + '@covector/assemble@0.12.0(mocha@10.8.2)': dependencies: - '@covector/command': 0.8.0 + '@covector/command': 0.8.0(mocha@10.8.2) '@covector/files': 0.8.0 effection: 2.0.8(mocha@10.8.2) js-yaml: 4.1.0 @@ -2441,9 +2441,10 @@ snapshots: unified: 9.2.2 transitivePeerDependencies: - encoding + - mocha - supports-color - '@covector/changelog@0.12.0': + '@covector/changelog@0.12.0(mocha@10.8.2)': dependencies: '@covector/files': 0.8.0 effection: 2.0.8(mocha@10.8.2) @@ -2453,14 +2454,16 @@ snapshots: unified: 9.2.2 transitivePeerDependencies: - encoding + - mocha - supports-color - '@covector/command@0.8.0': + '@covector/command@0.8.0(mocha@10.8.2)': dependencies: - '@effection/process': 2.1.4 + '@effection/process': 2.1.4(mocha@10.8.2) effection: 2.0.8(mocha@10.8.2) transitivePeerDependencies: - encoding + - mocha '@covector/files@0.8.0': dependencies: @@ -2507,10 +2510,8 @@ snapshots: dependencies: effection: 2.0.8(mocha@10.8.2) mocha: 10.8.2 - transitivePeerDependencies: - - encoding - '@effection/process@2.1.4': + '@effection/process@2.1.4(mocha@10.8.2)': dependencies: cross-spawn: 7.0.6 ctrlc-windows: 2.1.0 @@ -2518,6 +2519,7 @@ snapshots: shellwords: 0.1.1 transitivePeerDependencies: - encoding + - mocha '@effection/stream@2.0.6': dependencies: @@ -3377,9 +3379,9 @@ snapshots: dependencies: '@clack/prompts': 0.7.0 '@covector/apply': 0.10.0(mocha@10.8.2) - '@covector/assemble': 0.12.0 - '@covector/changelog': 0.12.0 - '@covector/command': 0.8.0 + '@covector/assemble': 0.12.0(mocha@10.8.2) + '@covector/changelog': 0.12.0(mocha@10.8.2) + '@covector/command': 0.8.0(mocha@10.8.2) '@covector/files': 0.8.0 effection: 2.0.8(mocha@10.8.2) globby: 11.1.0