mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-11 10:43:31 +02:00
This commit is contained in:
committed by
GitHub
parent
f6edc6df29
commit
fd125f76d7
5
.changes/fix-updater-linux.md
Normal file
5
.changes/fix-updater-linux.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch
|
||||
---
|
||||
|
||||
Adjust the updater to fallback to `$HOME/.cache` or the current working directory as temp directory if the system default is in a different mount point.
|
||||
@@ -3,7 +3,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use super::error::{Error, Result};
|
||||
#[cfg(feature = "updater")]
|
||||
use crate::api::file::{ArchiveFormat, Extract, Move};
|
||||
use crate::{
|
||||
api::http::{ClientBuilder, HttpRequestBuilder},
|
||||
@@ -21,7 +20,6 @@ use tauri_utils::{platform::current_exe, Env};
|
||||
use time::OffsetDateTime;
|
||||
use url::Url;
|
||||
|
||||
#[cfg(feature = "updater")]
|
||||
use std::io::Seek;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@@ -33,7 +31,6 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
#[cfg(feature = "updater")]
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
use std::ffi::OsStr;
|
||||
|
||||
@@ -602,29 +599,27 @@ impl<R: Runtime> Update<R> {
|
||||
// if there is no signature, bail out.
|
||||
verify_signature(&mut archive_buffer, &self.signature, &pub_key)?;
|
||||
|
||||
#[cfg(feature = "updater")]
|
||||
{
|
||||
// we copy the files depending of the operating system
|
||||
// we run the setup, appimage re-install or overwrite the
|
||||
// macos .app
|
||||
#[cfg(target_os = "windows")]
|
||||
copy_files_and_run(
|
||||
archive_buffer,
|
||||
&self.extract_path,
|
||||
self.with_elevated_task,
|
||||
self
|
||||
.app
|
||||
.config()
|
||||
.tauri
|
||||
.updater
|
||||
.windows
|
||||
.install_mode
|
||||
.clone()
|
||||
.msiexec_args(),
|
||||
)?;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
copy_files_and_run(archive_buffer, &self.extract_path)?;
|
||||
}
|
||||
// we copy the files depending of the operating system
|
||||
// we run the setup, appimage re-install or overwrite the
|
||||
// macos .app
|
||||
#[cfg(target_os = "windows")]
|
||||
copy_files_and_run(
|
||||
archive_buffer,
|
||||
&self.extract_path,
|
||||
self.with_elevated_task,
|
||||
self
|
||||
.app
|
||||
.config()
|
||||
.tauri
|
||||
.updater
|
||||
.windows
|
||||
.install_mode
|
||||
.clone()
|
||||
.msiexec_args(),
|
||||
)?;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
copy_files_and_run(archive_buffer, &self.extract_path)?;
|
||||
|
||||
// We are done!
|
||||
Ok(())
|
||||
}
|
||||
@@ -640,42 +635,60 @@ impl<R: Runtime> Update<R> {
|
||||
// We should have an AppImage already installed to be able to copy and install
|
||||
// the extract_path is the current AppImage path
|
||||
// tmp_dir is where our new AppImage is found
|
||||
#[cfg(feature = "updater")]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn copy_files_and_run<R: Read + Seek>(archive_buffer: R, extract_path: &Path) -> Result {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
let tmp_dir = tempfile::Builder::new()
|
||||
.prefix("tauri_current_app")
|
||||
.tempdir()?;
|
||||
let mut perms = std::fs::metadata(tmp_dir.path())?.permissions();
|
||||
perms.set_mode(0o700);
|
||||
std::fs::set_permissions(tmp_dir.path(), perms)?;
|
||||
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
||||
|
||||
let tmp_app_image = &tmp_dir.path().join("current_app.AppImage");
|
||||
let extract_path_metadata = extract_path.metadata()?;
|
||||
|
||||
// create a backup of our current app image
|
||||
Move::from_source(extract_path).to_dest(tmp_app_image)?;
|
||||
let tmp_dir_locations = vec![
|
||||
Box::new(|| Some(env::temp_dir())) as Box<dyn FnOnce() -> Option<PathBuf>>,
|
||||
Box::new(dirs_next::cache_dir),
|
||||
Box::new(|| Some(extract_path.parent().unwrap().to_path_buf())),
|
||||
];
|
||||
|
||||
// extract the buffer to the tmp_dir
|
||||
// we extract our signed archive into our final directory without any temp file
|
||||
let mut extractor =
|
||||
Extract::from_cursor(archive_buffer, ArchiveFormat::Tar(Some(Compression::Gz)));
|
||||
for tmp_dir_location in tmp_dir_locations {
|
||||
if let Some(tmp_dir_location) = tmp_dir_location() {
|
||||
let tmp_dir = tempfile::Builder::new()
|
||||
.prefix("tauri_current_app")
|
||||
.tempdir_in(tmp_dir_location)?;
|
||||
let tmp_dir_metadata = tmp_dir.path().metadata()?;
|
||||
|
||||
extractor.with_files(|entry| {
|
||||
let path = entry.path()?;
|
||||
if path.extension() == Some(OsStr::new("AppImage")) {
|
||||
// if something went wrong during the extraction, we should restore previous app
|
||||
if let Err(err) = entry.extract(extract_path) {
|
||||
Move::from_source(tmp_app_image).to_dest(extract_path)?;
|
||||
return Err(crate::api::Error::Extract(err.to_string()));
|
||||
if extract_path_metadata.dev() == tmp_dir_metadata.dev() {
|
||||
let mut perms = tmp_dir_metadata.permissions();
|
||||
perms.set_mode(0o700);
|
||||
std::fs::set_permissions(tmp_dir.path(), perms)?;
|
||||
|
||||
let tmp_app_image = &tmp_dir.path().join("current_app.AppImage");
|
||||
|
||||
// create a backup of our current app image
|
||||
Move::from_source(extract_path).to_dest(tmp_app_image)?;
|
||||
|
||||
// extract the buffer to the tmp_dir
|
||||
// we extract our signed archive into our final directory without any temp file
|
||||
let mut extractor =
|
||||
Extract::from_cursor(archive_buffer, ArchiveFormat::Tar(Some(Compression::Gz)));
|
||||
|
||||
return extractor
|
||||
.with_files(|entry| {
|
||||
let path = entry.path()?;
|
||||
if path.extension() == Some(OsStr::new("AppImage")) {
|
||||
// if something went wrong during the extraction, we should restore previous app
|
||||
if let Err(err) = entry.extract(extract_path) {
|
||||
Move::from_source(tmp_app_image).to_dest(extract_path)?;
|
||||
return Err(crate::api::Error::Extract(err.to_string()));
|
||||
}
|
||||
// early finish we have everything we need here
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
})
|
||||
.map_err(Into::into);
|
||||
}
|
||||
// early finish we have everything we need here
|
||||
return Ok(true);
|
||||
}
|
||||
Ok(false)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Err(Error::TempDirNotOnSameMountPoint)
|
||||
}
|
||||
|
||||
// Windows
|
||||
@@ -692,7 +705,6 @@ fn copy_files_and_run<R: Read + Seek>(archive_buffer: R, extract_path: &Path) ->
|
||||
|
||||
// ## EXE
|
||||
// Update server can provide a custom EXE (installer) who can run any task.
|
||||
#[cfg(feature = "updater")]
|
||||
#[cfg(target_os = "windows")]
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn copy_files_and_run<R: Read + Seek>(
|
||||
@@ -795,7 +807,6 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
// │ └── Contents # Application contents...
|
||||
// │ └── ...
|
||||
// └── ...
|
||||
#[cfg(feature = "updater")]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn copy_files_and_run<R: Read + Seek>(archive_buffer: R, extract_path: &Path) -> Result {
|
||||
let mut extracted_files: Vec<PathBuf> = Vec::new();
|
||||
|
||||
@@ -65,6 +65,10 @@ pub enum Error {
|
||||
/// HTTP error.
|
||||
#[error(transparent)]
|
||||
Http(#[from] http::Error),
|
||||
/// Temp dir is not on same mount mount. This prevents our updater to rename the AppImage to a temp file.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[error("temp directory is not on the same mount point as the AppImage")]
|
||||
TempDirNotOnSameMountPoint,
|
||||
}
|
||||
|
||||
pub type Result<T = ()> = std::result::Result<T, Error>;
|
||||
|
||||
Reference in New Issue
Block a user