fix(updater): preserve file extension of updater package (fix: #3283) (#3285)

* fix: preserve file extension of updated package (fix: #3283)

Otherwise users may get confused when seing a sudo dialog
which suggests a `rpm` package is installed using `dpkg -i`

* pass on package extension more thoroughly

* add changes file

Update the updater package to preserve file extension, clarifying installation prompts for users.

* Apply suggestion from @hrzlgnm

* Apply suggestion from @hrzlgnm

* Apply suggestion from @Legend-Master

* More rpm and log `pkg_path` instead

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
This commit is contained in:
hrzlgnm
2026-03-03 06:53:48 +01:00
committed by GitHub
parent 21ae430ea3
commit 31ab6f8d24
2 changed files with 24 additions and 13 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"updater": patch
"updater-js": patch
---
fix: preserve file extension of updater package, otherwise users may get confused when presented with a sudo dialog suggesting to install a file with the extension `.rpm` using `dpkg -i`
+18 -13
View File
@@ -949,7 +949,7 @@ impl Update {
}
}
/// Linux (AppImage and Deb)
/// Linux (AppImage, Deb, RPM)
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
@@ -962,6 +962,7 @@ impl Update {
/// ├── [AppName]_[version]_amd64.AppImage.tar.gz # GZ generated by tauri-bundler
/// │ └──[AppName]_[version]_amd64.AppImage # Application AppImage
/// ├── [AppName]_[version]_amd64.deb # Debian package
/// ├── [AppName]_[version]_amd64.rpm # RPM package
/// └── ...
///
fn install_inner(&self, bytes: &[u8]) -> Result<()> {
@@ -1052,7 +1053,7 @@ impl Update {
return Err(Error::InvalidUpdaterFormat);
}
self.try_tmp_locations(bytes, "dpkg", "-i")
self.try_tmp_locations(bytes, "dpkg", "-i", "deb")
}
fn install_rpm(&self, bytes: &[u8]) -> Result<()> {
@@ -1060,10 +1061,16 @@ impl Update {
if !infer::archive::is_rpm(bytes) {
return Err(Error::InvalidUpdaterFormat);
}
self.try_tmp_locations(bytes, "rpm", "-U")
self.try_tmp_locations(bytes, "rpm", "-U", "rpm")
}
fn try_tmp_locations(&self, bytes: &[u8], install_cmd: &str, install_arg: &str) -> Result<()> {
fn try_tmp_locations(
&self,
bytes: &[u8],
install_cmd: &str,
install_arg: &str,
package_extension: &str,
) -> Result<()> {
// Try different temp directories
let tmp_dir_locations = vec![
Box::new(|| Some(std::env::temp_dir())) as Box<dyn FnOnce() -> Option<PathBuf>>,
@@ -1074,13 +1081,11 @@ impl Update {
// Try writing to multiple temp locations until one succeeds
for tmp_dir_location in tmp_dir_locations {
if let Some(path) = tmp_dir_location() {
if let Ok(tmp_dir) = tempfile::Builder::new()
.prefix("tauri_rpm_update")
.tempdir_in(path)
{
let pkg_path = tmp_dir.path().join("package.rpm");
let prefix = format!("tauri_{package_extension}_update");
if let Ok(tmp_dir) = tempfile::Builder::new().prefix(&prefix).tempdir_in(path) {
let pkg_path = tmp_dir.path().join(format!("package.{package_extension}"));
// Try writing the .deb file
// Try writing the .deb / .rpm file
if std::fs::write(&pkg_path, bytes).is_ok() {
// If write succeeds, proceed with installation
return self.try_install_with_privileges(
@@ -1112,7 +1117,7 @@ impl Update {
.status()
{
if status.success() {
log::debug!("installed deb with pkexec");
log::debug!("installed {pkg_path:?} with pkexec");
return Ok(());
}
}
@@ -1120,7 +1125,7 @@ impl Update {
// 2. Try zenity or kdialog for a graphical sudo experience
if let Ok(password) = self.get_password_graphically() {
if self.install_with_sudo(pkg_path, &password, install_cmd, install_arg)? {
log::debug!("installed deb with GUI sudo");
log::debug!("installed {pkg_path:?} with GUI sudo");
return Ok(());
}
}
@@ -1133,7 +1138,7 @@ impl Update {
.status()?;
if status.success() {
log::debug!("installed deb with sudo");
log::debug!("installed {pkg_path:?} with sudo");
Ok(())
} else {
Err(Error::PackageInstallFailed)