Fixed system shortcuts for appimage version
This commit is contained in:
parent
658e32159a
commit
eb1500324f
4 changed files with 67 additions and 7 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -3108,7 +3108,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quicksearch-core"
|
||||
version = "1.1.7"
|
||||
version = "1.1.8"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"cfb",
|
||||
|
|
@ -3150,7 +3150,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quicksearch-gui"
|
||||
version = "1.1.7"
|
||||
version = "1.1.8"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"eframe",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pdf-extract = { path = "vendor/pdf-extract" } # Patched unbounded reads which co
|
|||
rtf-parser = { path = "vendor/rtf-parser" } # Patched a parsing error which occurs on UTF-16 characters
|
||||
|
||||
[workspace.package]
|
||||
version = "1.1.7"
|
||||
version = "1.1.8"
|
||||
edition = "2021"
|
||||
license = "GPL-3.0-or-later"
|
||||
authors = ["Jeremy <jeremy@karsttech.com>"]
|
||||
|
|
|
|||
|
|
@ -107,14 +107,28 @@ pub fn take_token() -> Option<String> {
|
|||
TOKEN.lock().unwrap_or_else(std::sync::PoisonError::into_inner).take()
|
||||
}
|
||||
|
||||
/// What to tell the user to bind, as they would type it. The installed name
|
||||
/// What to tell the user (or a desktop binding) to run. The installed name
|
||||
/// when we are on the path under it, and the full path otherwise — a build
|
||||
/// run out of `target/` is the common case, and "quicksearch" would be wrong
|
||||
/// advice there.
|
||||
///
|
||||
/// An AppImage needs its own rule: `current_exe` there points into the
|
||||
/// runtime's FUSE mount (`/tmp/.mount_…`), which vanishes with the process,
|
||||
/// so a binding made from it dies the moment QuickSearch closes. The
|
||||
/// runtime exports the durable path of the `.AppImage` file itself as
|
||||
/// `$APPIMAGE`; that is the thing to run.
|
||||
pub fn command_name() -> String {
|
||||
let Ok(exe) = std::env::current_exe() else {
|
||||
return "quicksearch".to_string();
|
||||
};
|
||||
durable_command(std::env::var_os("APPIMAGE").map(std::path::PathBuf::from), exe)
|
||||
}
|
||||
|
||||
/// The rule itself, split from the environment for the tests.
|
||||
fn durable_command(appimage: Option<PathBuf>, exe: PathBuf) -> String {
|
||||
if let Some(appimage) = appimage.filter(|p| p.is_absolute()) {
|
||||
return appimage.display().to_string();
|
||||
}
|
||||
let installed = exe
|
||||
.parent()
|
||||
.is_some_and(|dir| matches!(dir.to_str(), Some("/usr/bin") | Some("/usr/local/bin")));
|
||||
|
|
@ -584,6 +598,30 @@ mod tests {
|
|||
assert_ne!(a, b);
|
||||
}
|
||||
|
||||
/// An AppImage's mount path dies with the process; a binding must run
|
||||
/// the image file itself. Everything else keeps the old rule.
|
||||
#[test]
|
||||
fn the_bound_command_survives_the_appimage_exiting() {
|
||||
let mount = PathBuf::from("/tmp/.mount_quicksjBMkDo/usr/bin/quicksearch");
|
||||
assert_eq!(
|
||||
durable_command(Some(PathBuf::from("/home/u/Apps/QuickSearch.AppImage")), mount.clone()),
|
||||
"/home/u/Apps/QuickSearch.AppImage"
|
||||
);
|
||||
// A relative or empty APPIMAGE is somebody playing games; ignored.
|
||||
assert_eq!(
|
||||
durable_command(Some(PathBuf::from("games")), mount.clone()),
|
||||
mount.display().to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
durable_command(None, PathBuf::from("/usr/bin/quicksearch")),
|
||||
"quicksearch"
|
||||
);
|
||||
assert_eq!(
|
||||
durable_command(None, PathBuf::from("/opt/qs/quicksearch")),
|
||||
"/opt/qs/quicksearch"
|
||||
);
|
||||
}
|
||||
|
||||
/// The Windows reply parser, which faces whatever a squatting process
|
||||
/// cares to write into the well-known pipe name.
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -399,9 +399,31 @@ mod kde {
|
|||
binding, holder.action_friendly, holder.component_friendly,
|
||||
));
|
||||
}
|
||||
// An earlier build's file in the old location would leave a second
|
||||
// component claiming a key; gone before the new one appears.
|
||||
// A re-install must start from nothing. The daemon's service refresh
|
||||
// only *drops* components whose file vanished — it never re-reads a
|
||||
// changed one, and a component surviving `unregister` empty blocks
|
||||
// re-detection by name — so an install over an existing binding
|
||||
// would keep serving the old Exec line (fatal for an AppImage,
|
||||
// whose old mount path died with the last run). Tear down like
|
||||
// `remove` does and let the daemon notice before rebuilding.
|
||||
if desktop_file().is_file() || legacy_desktop_file().is_file() {
|
||||
let _ = call("unregister", &[COMPONENT, ACTION]);
|
||||
let _ = std::fs::remove_file(desktop_file());
|
||||
let _ = std::fs::remove_file(legacy_desktop_file());
|
||||
if run("kbuildsycoca6", &[]).or_else(|_| run("kbuildsycoca5", &[])).is_ok() {
|
||||
// Gone when getComponent stops answering; bounded, and a
|
||||
// timeout just falls through to the rebuild below.
|
||||
for _ in 0..10 {
|
||||
if call("getComponent", &[COMPONENT]).is_err() {
|
||||
break;
|
||||
}
|
||||
std::thread::sleep(std::time::Duration::from_millis(200));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No marker file, but an earlier claim may still be registered.
|
||||
let _ = call("unregister", &[COMPONENT, ACTION]);
|
||||
}
|
||||
|
||||
// The file is the whole registration — key included — and the
|
||||
// installed marker, so a failure below deletes it again.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue