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]]
|
[[package]]
|
||||||
name = "quicksearch-core"
|
name = "quicksearch-core"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"cfb",
|
"cfb",
|
||||||
|
|
@ -3150,7 +3150,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quicksearch-gui"
|
name = "quicksearch-gui"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"eframe",
|
"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
|
rtf-parser = { path = "vendor/rtf-parser" } # Patched a parsing error which occurs on UTF-16 characters
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
authors = ["Jeremy <jeremy@karsttech.com>"]
|
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()
|
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
|
/// 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
|
/// run out of `target/` is the common case, and "quicksearch" would be wrong
|
||||||
/// advice there.
|
/// 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 {
|
pub fn command_name() -> String {
|
||||||
let Ok(exe) = std::env::current_exe() else {
|
let Ok(exe) = std::env::current_exe() else {
|
||||||
return "quicksearch".to_string();
|
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
|
let installed = exe
|
||||||
.parent()
|
.parent()
|
||||||
.is_some_and(|dir| matches!(dir.to_str(), Some("/usr/bin") | Some("/usr/local/bin")));
|
.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);
|
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
|
/// The Windows reply parser, which faces whatever a squatting process
|
||||||
/// cares to write into the well-known pipe name.
|
/// cares to write into the well-known pipe name.
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -399,9 +399,31 @@ mod kde {
|
||||||
binding, holder.action_friendly, holder.component_friendly,
|
binding, holder.action_friendly, holder.component_friendly,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// An earlier build's file in the old location would leave a second
|
// A re-install must start from nothing. The daemon's service refresh
|
||||||
// component claiming a key; gone before the new one appears.
|
// 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());
|
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
|
// The file is the whole registration — key included — and the
|
||||||
// installed marker, so a failure below deletes it again.
|
// installed marker, so a failure below deletes it again.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue