mirror of
https://github.com/storytold/craft-launcher.git
synced 2026-11-12 05:03:07 +00:00
fix: preserve repository ownership and Flatpak update results
This commit is contained in:
5 files changed
+44
-12
No files matched your search
@@ -379,13 +379,6 @@ impl NativeBackend {
|
||||
// One installer call can cover several apps, and fail after some of them went in.
|
||||
let latest = shared.latest.lock().unwrap_or_else(PoisonError::into_inner).get(app.id).cloned();
|
||||
let result = match (result, latest) {
|
||||
(Ok(_), _)
|
||||
if existing.as_ref().is_some_and(|e| e.externally_managed)
|
||||
&& found.is_some()
|
||||
&& existing.as_ref().and_then(|e| e.version.as_ref()) == found.as_ref().and_then(|f| f.version.as_ref()) =>
|
||||
{
|
||||
Ok(format!("{} is already up to date", app.name))
|
||||
}
|
||||
(Err(e), Some(release))
|
||||
if !uninstall && release.version.as_ref().is_some_and(|v| landed_despite(&e, existing.as_ref(), found.as_ref(), v)) =>
|
||||
{
|
||||
|
||||
@@ -620,7 +620,7 @@ pub mod linux {
|
||||
// A Flatpak runs under the id it was found under, which may be an older one.
|
||||
let location = if p.manager == InstallSource::Flatpak { p.name.clone() } else { binary_on_path(app.id) };
|
||||
let externally_managed = p.manager == InstallSource::Flatpak
|
||||
&& p.origin.as_deref().is_some_and(|origin| {
|
||||
&& p.origin.as_deref().is_none_or(|origin| {
|
||||
if packages::is_flatpark_origin(origin) {
|
||||
return true;
|
||||
}
|
||||
@@ -629,8 +629,8 @@ pub mod linux {
|
||||
Some("system") | None => "--system".to_string(),
|
||||
Some(name) => format!("--installation={name}"),
|
||||
};
|
||||
crate::process::capture_flatpak(&["remotes", &scope, "--columns=name,url"], Duration::from_secs(10))
|
||||
.is_some_and(|remotes| packages::is_artcraft_remote(origin, &remotes))
|
||||
crate::process::capture_flatpak(&["remotes", &scope, "--show-disabled", "--columns=name,url"], Duration::from_secs(10))
|
||||
.is_none_or(|remotes| packages::remote_manages_flatpak(origin, &remotes))
|
||||
});
|
||||
return Some(Installed {
|
||||
version: packages::version_of(p),
|
||||
|
||||
@@ -121,6 +121,11 @@ pub fn install_at(
|
||||
{
|
||||
return Err(format!("{} is running. Quit it, then try again.", app.name));
|
||||
}
|
||||
if kind == PackageKind::Flatpak
|
||||
&& let Some(installed) = existing.filter(|installed| installed.source == InstallSource::Flatpak && installed.externally_managed)
|
||||
{
|
||||
return Err(managed_elsewhere(app, installed, false).unwrap_or_else(|| "Update this app through its Flatpak repository".into()));
|
||||
}
|
||||
bind_artifact_version(app, release, asset)?;
|
||||
// A feed can't send an app back to an older build; only a version the person chose by name
|
||||
// (a downgrade with a way back if it fails) gets past this.
|
||||
@@ -1262,7 +1267,7 @@ pub(crate) mod linux {
|
||||
if !reference.starts_with(&format!("app/{id}/")) || !reference.ends_with("/stable") {
|
||||
return Ok(false);
|
||||
}
|
||||
let remotes = run(&["remotes", "--columns=name,url"])?;
|
||||
let remotes = run(&["remotes", "--show-disabled", "--columns=name,url"])?;
|
||||
let remote = remotes.lines().find_map(|line| {
|
||||
let (name, _) = line.split_once('\t')?;
|
||||
crate::packages::is_artcraft_remote(name, line).then(|| name.to_string())
|
||||
@@ -1274,7 +1279,7 @@ pub(crate) mod linux {
|
||||
return Err("The artcraft-oci remote points to a different repository".into());
|
||||
}
|
||||
run(&["remote-add", "--noninteractive", "artcraft-oci", "https://getartcraft.com/artcraft-oci.flatpakrepo"])?;
|
||||
let remotes = run(&["remotes", "--columns=name,url"])?;
|
||||
let remotes = run(&["remotes", "--show-disabled", "--columns=name,url"])?;
|
||||
if !crate::packages::is_artcraft_remote("artcraft-oci", &remotes) {
|
||||
return Err("The ArtCraft OCI descriptor configured an unexpected repository".into());
|
||||
}
|
||||
|
||||
@@ -305,3 +305,31 @@ mod migration_tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only a confirmed bundle origin with no repository URL permits bundle replacement.
|
||||
/// Missing rows are unknown, so preserve remote ownership conservatively.
|
||||
pub fn remote_manages_flatpak(origin: &str, remotes: &str) -> bool {
|
||||
remotes
|
||||
.lines()
|
||||
.find_map(|line| {
|
||||
let mut fields = line.split('\t');
|
||||
if fields.next().map(str::trim) != Some(origin) {
|
||||
return None;
|
||||
}
|
||||
Some(fields.next().is_some_and(|url| !url.trim().is_empty()))
|
||||
})
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod remote_ownership_tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn only_confirmed_empty_urls_allow_bundle_replacement() {
|
||||
assert!(!remote_manages_flatpak("app-origin", "app-origin\t\n"));
|
||||
assert!(remote_manages_flatpak("renamed", "renamed\thttps://example.org/repo\n"));
|
||||
assert!(remote_manages_flatpak("renamed", "renamed\toci+https://getartcraft.com\n"));
|
||||
assert!(remote_manages_flatpak("missing", "other\t\n"));
|
||||
assert!(!remote_manages_flatpak("app-origin", "app-origin"));
|
||||
}
|
||||
}
|
||||
@@ -797,7 +797,13 @@ pub(crate) fn cancellable_output(mut cmd: Command, check: impl Fn() -> Result<()
|
||||
let mut child =
|
||||
cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn().map_err(|e| format!("couldn't run flatpak ({e})"))?;
|
||||
let (stdout, stderr) = (read_all(child.stdout.take()), read_all(child.stderr.take()));
|
||||
let started = Instant::now();
|
||||
let status = loop {
|
||||
if started.elapsed() >= Duration::from_secs(60 * 60) {
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
return Err("Flatpak did not finish within one hour".into());
|
||||
}
|
||||
if let Err(e) = check() {
|
||||
let _ = child.kill();
|
||||
let _ = child.wait();
|
||||
|
||||
Reference in new issue
Block a user