So I am working with https://github.com/espanso/espanso 2.1.8
It has a workspace in the root directory:
[workspace] members = [ "espanso", "espanso-detect", "espanso-ui", "espanso-inject", "espanso-ipc", "espanso-config", "espanso-match", "espanso-clipboard", "espanso-render", "espanso-info", "espanso-path", "espanso-modulo", "espanso-migrate", "espanso-mac-utils", "espanso-kvs", "espanso-engine", "espanso-package", ]
In the espanso directory I have customized the Cargo.toml to add two [[bin]] section:
Cargo.toml
[[bin]]
[package] name = "espanso" version = "2.1.8" authors = ["Federico Terzi <federicoterzi96@gmail.com>"] license = "GPL-3.0" description = "Cross-platform Text Expander written in Rust" readme = "README.md" homepage = "https://github.com/federico-terzi/espanso" edition = "2018" [features] default = ["modulo", "native-tls"] # These features control whether Espanso will use the native TLS functionality # or not. On some platforms (currently Linux) we prefer vendoring the SSL # logic used by the packages to avoid dependency issues. # https://github.com/espanso/espanso/issues/1056 native-tls = ["espanso-package/default-tls"] vendored-tls = ["espanso-package/rustls-tls"] # If the wayland feature is enabled, all X11 dependencies will be dropped # and only methods suitable for Wayland will be used wayland = ["espanso-detect/wayland", "espanso-inject/wayland", "espanso-clipboard/wayland", "espanso-info/wayland"] # Compile modulo and all its dependencies (including wxWidgets). If you don't # enable it, features like Forms and Search might not be available. modulo = ["espanso-modulo", "espanso-clipboard/avoid-gdi", "espanso-ui/avoid-gdi"] [[bin]] name = "espanso" path = "src/main.rs" required-features = ["default"] [[bin]] name = "espanso-wayland" path = "src/main.rs" required-features = ["wayland"] [dependencies] espanso-detect = { path = "../espanso-detect" } espanso-ui = { path = "../espanso-ui" } espanso-inject = { path = "../espanso-inject" } espanso-config = { path = "../espanso-config" } espanso-match = { path = "../espanso-match" } espanso-clipboard = { path = "../espanso-clipboard" } espanso-info = { path = "../espanso-info" } espanso-render = { path = "../espanso-render" } espanso-path = { path = "../espanso-path" } espanso-ipc = { path = "../espanso-ipc" } espanso-modulo = { path = "../espanso-modulo", optional = true } espanso-migrate = { path = "../espanso-migrate" } espanso-kvs = { path = "../espanso-kvs" } espanso-engine = { path = "../espanso-engine" } espanso-package = { path = "../espanso-package"} maplit = "1.0.2" simplelog = "0.12.0" log = "0.4.14" anyhow = "1.0.38" thiserror = "1.0.23" clap = "2.33.3" lazy_static = "1.4.0" crossbeam = "0.8.0" enum-as-inner = "0.5.0" dirs = "3.0.1" serde = { version = "1.0.123", features = ["derive"] } serde_json = "1.0.62" log-panics = "2.0.0" fs2 = "0.4.3" serde_yaml = "0.8.17" fs_extra = "1.2.0" dialoguer = "0.10.0" colored = "2.0.0" tempdir = "0.3.7" notify-debouncer-mini = "0.2.0" opener = "0.5.0" sysinfo = "0.28.0" time = "0.3.0" [target.'cfg(unix)'.dependencies] libc = "0.2.98" [target.'cfg(target_os="linux")'.dependencies] caps = "0.5.2" const_format = "0.2.14" regex = "1.5.5" [package.metadata.deb] maintainer = "Federico Terzi <federicoterzi96@gmail.com>" depends = "$auto, systemd, libxtst6, xclip, libnotify-bin, libxkbcommon0, libwxgtk3.0-gtk3-0v5" section = "utility" license-file = ["../LICENSE", "1"] [package.metadata.deb.variants.wayland] depends = "$auto, systemd, libnotify-bin, libxkbcommon0, libwxgtk3.0-gtk3-0v5, wl-clipboard" # TODO: once this issue [1] is fixed, we should create a variant for # wayland to automatically run the setcap script. # [1]: https://github.com/mmstick/cargo-deb/issues/151
When I run cargo2rpm in the workspace I have the following error:
cargo2rpm --path ./Cargo.toml buildrequires (base) 0s fish Traceback (most recent call last): File "/usr/bin/cargo2rpm", line 8, in <module> sys.exit(main()) ^^^^^^ File "/usr/lib/python3.12/site-packages/cargo2rpm/__main__.py", line 111, in main action_buildrequires(args) File "/usr/lib/python3.12/site-packages/cargo2rpm/__main__.py", line 50, in action_buildrequires brs = workspace_buildrequires(metadata, flags, args.with_check) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/site-packages/cargo2rpm/rpm.py", line 234, in workspace_buildrequires member_flags = metadata.get_feature_flags_for_workspace_members(flags) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/site-packages/cargo2rpm/metadata.py", line 617, in get_feature_flags_for_workspace_members required_features[package.name].update(reqs) ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^ KeyError: 'espanso'
If I remove required-features = ["default"] and required-features = ["wayland"] from the [[bin]] section it works, but I need them.
required-features = ["default"]
required-features = ["wayland"]
Thanks for reporting this, I'll investigate (and add the metadata for espanso as a test case to prevent future regressions).
Note that required-features = ["default"] should be a noop, unless you build with -n / --no-default-features.
-n
--no-default-features
I found the issue, it was a logic bug in the resolver for enabled features across workspace members. It was easy to fix: https://pagure.io/fedora-rust/cargo2rpm/c/8f9ad961cfec09f504748e1c7aa086d7be62b781?branch=main
I'll tag a new version of cargo2rpm and push it to Fedora shortly.
Note that I would still handle this differently myself, but at least it should now also not crash the way you're doing it :)
Metadata Update from @decathorpe: - Issue status updated to: Closed (was: Open)
Thank you!
How would you do it?
I would probably try something like this:
%build %cargo_build mv target/release/espanso ./espanso %cargo_build -f wayland mv target/release/espanso ./espanso-wayland
and then not use %cargo_install but install these files manually.
%cargo_install
That wouldn't require patching in custom binary targets (not sure if it's worth it, since you need to patch out windows and Mac dependencies anyway)
OK thanks.
I have to patch the source a lot anyway:
diff -up espanso-2.1.8/espanso/src/cli/daemon/watcher.rs.orig espanso-2.1.8/espanso/src/cli/daemon/watcher.rs --- espanso-2.1.8/espanso/src/cli/daemon/watcher.rs.orig 2022-11-01 11:23:19.000000000 +0100 +++ espanso-2.1.8/espanso/src/cli/daemon/watcher.rs 2023-09-21 20:03:25.199873322 +0200 @@ -19,7 +19,11 @@ use std::{path::Path, time::Duration}; -use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; +use notify_debouncer_mini::{ + new_debouncer_opt, + notify::{Config, RecommendedWatcher, RecursiveMode}, + Debouncer, +}; use anyhow::Result; use crossbeam::{channel::Sender, select}; @@ -51,11 +55,16 @@ pub fn initialize_and_spawn(config_dir: fn watcher_main(config_dir: &Path, debounce_tx: crossbeam::channel::Sender<()>) { let (tx, rx) = std::sync::mpsc::channel(); - let mut watcher: RecommendedWatcher = - Watcher::new(tx, Duration::from_millis(WATCHER_NOTIFY_DELAY_MS)) - .expect("unable to create file watcher"); + let mut watcher: Debouncer<RecommendedWatcher> = new_debouncer_opt( + Duration::from_millis(WATCHER_DEBOUNCE_DURATION_MS), + None, + tx, + Config::default().with_poll_interval(Duration::from_millis(WATCHER_NOTIFY_DELAY_MS)), + ) + .expect("unable to create file watcher"); watcher + .watcher() .watch(&config_dir, RecursiveMode::Recursive) .expect("unable to start file watcher"); @@ -63,32 +72,19 @@ fn watcher_main(config_dir: &Path, debou loop { let should_reload = match rx.recv() { - Ok(event) => { - let path = match event { - DebouncedEvent::Create(path) => Some(path), - DebouncedEvent::Write(path) => Some(path), - DebouncedEvent::Remove(path) => Some(path), - DebouncedEvent::Rename(_, path) => Some(path), - _ => None, - }; - - if let Some(path) = path { - let extension = path - .extension() - .unwrap_or_default() - .to_string_lossy() - .to_ascii_lowercase(); - - if ["yml", "yaml"].iter().any(|ext| ext == &extension) { - // Only load non-hidden yml files - !is_file_hidden(&path) - } else { - // If there is no extension, it's probably a folder - extension.is_empty() - } - } else { - false - } + Ok(Ok(events)) => events.iter().any(|one_event| { + let path = &one_event.path; // Changed this line + let extension = path + .extension() + .unwrap_or_default() + .to_string_lossy() + .to_ascii_lowercase(); + + ["yml", "yaml"].iter().any(|ext| ext == &extension) && !is_file_hidden(path) + }), + Ok(Err(e)) => { + warn!("error while watching files: {:?}", e); + false } Err(e) => { warn!("error while watching files: {:?}", e); diff -up espanso-2.1.8/espanso/src/cli/service/linux.rs.orig espanso-2.1.8/espanso/src/cli/service/linux.rs --- espanso-2.1.8/espanso/src/cli/service/linux.rs.orig 2022-11-01 11:23:19.000000000 +0100 +++ espanso-2.1.8/espanso/src/cli/service/linux.rs 2023-09-21 20:03:25.199873322 +0200 @@ -27,7 +27,12 @@ use thiserror::Error; use crate::{error_eprintln, info_println, warn_eprintln}; +#[cfg(feature = "wayland")] +const LINUX_SERVICE_NAME: &str = "espanso-wayland"; + +#[cfg(not(feature = "wayland"))] const LINUX_SERVICE_NAME: &str = "espanso"; + const LINUX_SERVICE_CONTENT: &str = include_str!("../../res/linux/systemd.service"); #[allow(clippy::transmute_bytes_to_str)] const LINUX_SERVICE_FILENAME: &str = formatcp!("{}.service", LINUX_SERVICE_NAME); diff -up espanso-2.1.8/espanso/src/main.rs.orig espanso-2.1.8/espanso/src/main.rs --- espanso-2.1.8/espanso/src/main.rs.orig 2022-11-01 11:23:19.000000000 +0100 +++ espanso-2.1.8/espanso/src/main.rs 2023-09-21 20:03:25.200873315 +0200 @@ -30,8 +30,11 @@ use cli::{CliAlias, CliModule, CliModule use log::{error, info, warn}; use logging::FileProxy; use simplelog::{ - CombinedLogger, ConfigBuilder, LevelFilter, SharedLogger, TermLogger, TerminalMode, WriteLogger, + ColorChoice, CombinedLogger, ConfigBuilder, LevelFilter, SharedLogger, TermLogger, TerminalMode, + WriteLogger, }; +use std::convert::identity; +use time::macros::format_description; use crate::{ cli::{LogMode, PathsOverrides}, @@ -524,12 +527,9 @@ For example, specifying 'email' is equiv let log_proxy = FileProxy::new(); if handler.enable_logs { let config = ConfigBuilder::new() - .set_time_to_local(true) - .set_time_format(format!( - "%H:%M:%S [{}({})]", - handler.subcommand, - std::process::id() - )) + .set_time_offset_to_local() + .unwrap_or_else(identity) + .set_time_format_custom(format_description!("[hour]:[minute]:[second]]")) .set_location_level(LevelFilter::Off) .add_filter_ignore_str("html5ever") .build(); @@ -541,7 +541,10 @@ For example, specifying 'email' is equiv )]; if !handler.disable_logs_terminal_output { - outputs.insert(0, TermLogger::new(log_level, config, TerminalMode::Mixed)); + outputs.insert( + 0, + TermLogger::new(log_level, config, TerminalMode::Mixed, ColorChoice::Auto), + ); } CombinedLogger::init(outputs).expect("unable to initialize logs");
Yeah, I thought patches will already be the case so ... it doesn't save you much.
Log in to comment on this ticket.