RPM installation

pull/2624/head
Krzysztof Andrelczyk 5 months ago
parent ae7a2e3198
commit dc75b76c0a

@ -73,8 +73,8 @@ pub enum Error {
TempDirNotFound, TempDirNotFound,
#[error("Authentication failed or was cancelled")] #[error("Authentication failed or was cancelled")]
AuthenticationFailed, AuthenticationFailed,
#[error("Failed to install .deb package")] #[error("Failed to install package")]
DebInstallFailed, PackageInstallFailed,
#[error("invalid updater binary format")] #[error("invalid updater binary format")]
InvalidUpdaterFormat, InvalidUpdaterFormat,
#[error(transparent)] #[error(transparent)]

@ -940,6 +940,7 @@ impl Update {
fn install_inner(&self, bytes: &[u8]) -> Result<()> { fn install_inner(&self, bytes: &[u8]) -> Result<()> {
match self.installer { match self.installer {
Some(Installer::Deb) => self.install_deb(bytes), Some(Installer::Deb) => self.install_deb(bytes),
Some(Installer::Rpm) => self.install_rpm(bytes),
_ =>self.install_appimage(bytes) _ =>self.install_appimage(bytes)
} }
} }
@ -1022,6 +1023,19 @@ impl Update {
return Err(Error::InvalidUpdaterFormat); return Err(Error::InvalidUpdaterFormat);
} }
self.try_tmp_locations(bytes, "dpkg", "-i")
}
fn install_rpm(&self, bytes: &[u8]) -> Result<()> {
// First verify the bytes are actually a .rpm package
if !infer::archive::is_rpm(bytes) {
return Err(Error::InvalidUpdaterFormat);
}
self.try_tmp_locations(bytes, "rpm", "-U")
}
fn try_tmp_locations(&self, bytes: &[u8], install_cmd: &str, install_arg: &str) -> Result<()> {
// Try different temp directories // Try different temp directories
let tmp_dir_locations = vec![ let tmp_dir_locations = vec![
Box::new(|| Some(std::env::temp_dir())) as Box<dyn FnOnce() -> Option<PathBuf>>, Box::new(|| Some(std::env::temp_dir())) as Box<dyn FnOnce() -> Option<PathBuf>>,
@ -1033,15 +1047,15 @@ impl Update {
for tmp_dir_location in tmp_dir_locations { for tmp_dir_location in tmp_dir_locations {
if let Some(path) = tmp_dir_location() { if let Some(path) = tmp_dir_location() {
if let Ok(tmp_dir) = tempfile::Builder::new() if let Ok(tmp_dir) = tempfile::Builder::new()
.prefix("tauri_deb_update") .prefix("tauri_rpm_update")
.tempdir_in(path) .tempdir_in(path)
{ {
let deb_path = tmp_dir.path().join("package.deb"); let pkg_path = tmp_dir.path().join("package.rpm");
// Try writing the .deb file // Try writing the .deb file
if std::fs::write(&deb_path, bytes).is_ok() { if std::fs::write(&pkg_path, bytes).is_ok() {
// If write succeeds, proceed with installation // If write succeeds, proceed with installation
return self.try_install_with_privileges(&deb_path); return self.try_install_with_privileges(&pkg_path, install_cmd, install_arg);
} }
// If write fails, continue to next temp location // If write fails, continue to next temp location
} }
@ -1050,14 +1064,15 @@ impl Update {
// If we get here, all temp locations failed // If we get here, all temp locations failed
Err(Error::TempDirNotFound) Err(Error::TempDirNotFound)
} }
fn try_install_with_privileges(&self, deb_path: &Path) -> Result<()> { fn try_install_with_privileges(&self, pkg_path: &Path, install_cmd: &str, install_arg: &str) -> Result<()> {
// 1. First try using pkexec (graphical sudo prompt) // 1. First try using pkexec (graphical sudo prompt)
if let Ok(status) = std::process::Command::new("pkexec") if let Ok(status) = std::process::Command::new("pkexec")
.arg("dpkg") .arg(install_cmd)
.arg("-i") .arg(install_arg)
.arg(deb_path) .arg(pkg_path)
.status() .status()
{ {
if status.success() { if status.success() {
@ -1067,22 +1082,22 @@ impl Update {
// 2. Try zenity or kdialog for a graphical sudo experience // 2. Try zenity or kdialog for a graphical sudo experience
if let Ok(password) = self.get_password_graphically() { if let Ok(password) = self.get_password_graphically() {
if self.install_with_sudo(deb_path, &password)? { if self.install_with_sudo(pkg_path, &password, install_cmd, install_arg)? {
return Ok(()); return Ok(());
} }
} }
// 3. Final fallback: terminal sudo // 3. Final fallback: terminal sudo
let status = std::process::Command::new("sudo") let status = std::process::Command::new("sudo")
.arg("dpkg") .arg(install_cmd)
.arg("-i") .arg(install_arg)
.arg(deb_path) .arg(pkg_path)
.status()?; .status()?;
if status.success() { if status.success() {
Ok(()) Ok(())
} else { } else {
Err(Error::DebInstallFailed) Err(Error::PackageInstallFailed)
} }
} }
@ -1116,15 +1131,15 @@ impl Update {
Err(Error::AuthenticationFailed) Err(Error::AuthenticationFailed)
} }
fn install_with_sudo(&self, deb_path: &Path, password: &str) -> Result<bool> { fn install_with_sudo(&self, pkg_path: &Path, password: &str, install_cmd: &str, install_arg: &str) -> Result<bool> {
use std::io::Write; use std::io::Write;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
let mut child = Command::new("sudo") let mut child = Command::new("sudo")
.arg("-S") // read password from stdin .arg("-S") // read password from stdin
.arg("dpkg") .arg(install_cmd)
.arg("-i") .arg(install_arg)
.arg(deb_path) .arg(pkg_path)
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())

@ -372,15 +372,13 @@ fn update_app() {
.1, .1,
); );
c c
} else if matches!(bundle_target, BundleTarget::AppImage) { } else {
Command::new( Command::new(
&test_cases(&root_dir, "0.1.0", target.clone()) &test_cases(&root_dir, "0.1.0", target.clone())
.first() .first()
.unwrap() .unwrap()
.1, .1,
) )
} else {
Command::new(root_dir.join("target/debug/app-updater"))
}; };
binary_cmd.env("TARGET", bundle_target.name()); binary_cmd.env("TARGET", bundle_target.name());

Loading…
Cancel
Save