mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
Co-authored-by: chip <chip@chip.sh> Co-authored-by: Lucas Nogueira <lucas@tauri.studio> Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
This commit is contained in:
@@ -6,7 +6,7 @@ use std::{
|
||||
borrow::Cow,
|
||||
fs,
|
||||
io::{self, Cursor, Read, Seek},
|
||||
path::{self, Path, PathBuf},
|
||||
path::{self, Component, Path, PathBuf},
|
||||
};
|
||||
|
||||
/// The archive reader.
|
||||
@@ -84,10 +84,22 @@ impl<'a, R: Read> Entry<'a, R> {
|
||||
|
||||
/// Extract this entry into `into_path`.
|
||||
/// If it's a directory, the target will be created, if it's a file, it'll be extracted at this location.
|
||||
/// If it's a symlink, it will be created.
|
||||
/// Note: You need to include the complete path, with file name and extension.
|
||||
pub fn extract(self, into_path: &path::Path) -> crate::api::Result<()> {
|
||||
match self {
|
||||
Self::Tar(mut entry) => {
|
||||
// validate path
|
||||
let path = entry.path()?;
|
||||
if path.components().any(|c| matches!(c, Component::ParentDir)) {
|
||||
return Err(
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"cannot extract path with parent dir component",
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
// determine if it's a file or a directory
|
||||
if entry.header().entry_type() == tar::EntryType::Directory {
|
||||
// this is a directory, lets create it
|
||||
@@ -100,13 +112,8 @@ impl<'a, R: Read> Entry<'a, R> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut out_file = fs::File::create(into_path)?;
|
||||
io::copy(&mut entry, &mut out_file)?;
|
||||
|
||||
// make sure we set permissions
|
||||
if let Ok(mode) = entry.header().mode() {
|
||||
set_perms(into_path, Some(&mut out_file), mode, true)?;
|
||||
}
|
||||
// handle files, symlinks, hard links, etc. and set permissions
|
||||
entry.unpack(into_path)?;
|
||||
}
|
||||
}
|
||||
Self::Zip(entry) => {
|
||||
@@ -270,59 +277,3 @@ impl<'a, R: Read + Seek> Extract<'a, R> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn set_perms(
|
||||
dst: &Path,
|
||||
f: Option<&mut std::fs::File>,
|
||||
mode: u32,
|
||||
preserve: bool,
|
||||
) -> crate::api::Result<()> {
|
||||
_set_perms(dst, f, mode, preserve).map_err(|_| {
|
||||
crate::api::Error::Extract(format!(
|
||||
"failed to set permissions to {mode:o} \
|
||||
for `{}`",
|
||||
dst.display()
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn _set_perms(
|
||||
dst: &Path,
|
||||
f: Option<&mut std::fs::File>,
|
||||
mode: u32,
|
||||
preserve: bool,
|
||||
) -> io::Result<()> {
|
||||
use std::os::unix::prelude::*;
|
||||
|
||||
let mode = if preserve { mode } else { mode & 0o777 };
|
||||
let perm = fs::Permissions::from_mode(mode as _);
|
||||
match f {
|
||||
Some(f) => f.set_permissions(perm),
|
||||
None => fs::set_permissions(dst, perm),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn _set_perms(
|
||||
dst: &Path,
|
||||
f: Option<&mut std::fs::File>,
|
||||
mode: u32,
|
||||
_preserve: bool,
|
||||
) -> io::Result<()> {
|
||||
if mode & 0o200 == 0o200 {
|
||||
return Ok(());
|
||||
}
|
||||
match f {
|
||||
Some(f) => {
|
||||
let mut perm = f.metadata()?.permissions();
|
||||
perm.set_readonly(true);
|
||||
f.set_permissions(perm)
|
||||
}
|
||||
None => {
|
||||
let mut perm = fs::metadata(dst)?.permissions();
|
||||
perm.set_readonly(true);
|
||||
fs::set_permissions(dst, perm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
core/tests/app-updater/frameworks/test.framework/Headers
Symbolic link
1
core/tests/app-updater/frameworks/test.framework/Headers
Symbolic link
@@ -0,0 +1 @@
|
||||
Versions/Current/Headers
|
||||
1
core/tests/app-updater/frameworks/test.framework/Resources
Symbolic link
1
core/tests/app-updater/frameworks/test.framework/Resources
Symbolic link
@@ -0,0 +1 @@
|
||||
Versions/Current/Resources
|
||||
@@ -0,0 +1 @@
|
||||
// Testing that a header can be included
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>test</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.tauri.test.framework</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>test</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1 @@
|
||||
Test that a LICENSE file can be included
|
||||
3
core/tests/app-updater/frameworks/test.framework/Versions/A/test
Executable file
3
core/tests/app-updater/frameworks/test.framework/Versions/A/test
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
echo "hello"
|
||||
@@ -0,0 +1 @@
|
||||
A
|
||||
1
core/tests/app-updater/frameworks/test.framework/test
Symbolic link
1
core/tests/app-updater/frameworks/test.framework/test
Symbolic link
@@ -0,0 +1 @@
|
||||
Versions/Current/test
|
||||
@@ -17,6 +17,11 @@
|
||||
"../../../examples/.icons/icon.ico"
|
||||
],
|
||||
"category": "DeveloperTool",
|
||||
"macOS": {
|
||||
"frameworks": [
|
||||
"./frameworks/test.framework"
|
||||
]
|
||||
},
|
||||
"windows": {
|
||||
"wix": {
|
||||
"skipWebviewInstall": true
|
||||
|
||||
@@ -310,6 +310,23 @@ fn update_app() {
|
||||
|
||||
let status = binary_cmd.status().expect("failed to run app");
|
||||
|
||||
// Verify the framework extracted symlinks correctly
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let meta = std::fs::symlink_metadata(
|
||||
bundle_paths(&root_dir, "0.1.0")
|
||||
.first()
|
||||
.unwrap()
|
||||
.1
|
||||
.join("Contents/Frameworks/test.framework/test"),
|
||||
)
|
||||
.expect("test.framework/test metadata");
|
||||
assert!(
|
||||
meta.file_type().is_symlink(),
|
||||
"test.framework/test should be a symlink"
|
||||
);
|
||||
}
|
||||
|
||||
if !status.success() {
|
||||
panic!("failed to run app");
|
||||
}
|
||||
|
||||
@@ -238,12 +238,22 @@ fn create_tar(src_dir: &Path, dest_path: &Path) -> crate::Result<PathBuf> {
|
||||
let gzip_encoder = libflate::gzip::Encoder::new(dest_file)?;
|
||||
|
||||
let gzip_encoder = create_tar_from_src(src_dir, gzip_encoder)?;
|
||||
|
||||
let mut dest_file = gzip_encoder.finish().into_result()?;
|
||||
dest_file.flush()?;
|
||||
Ok(dest_path.to_owned())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn create_tar_from_src<P: AsRef<Path>, W: Write>(src_dir: P, dest_file: W) -> crate::Result<W> {
|
||||
let src_dir = src_dir.as_ref();
|
||||
let mut builder = tar::Builder::new(dest_file);
|
||||
builder.follow_symlinks(false);
|
||||
builder.append_dir_all(src_dir.file_name().expect("Path has no file_name"), src_dir)?;
|
||||
builder.into_inner().map_err(Into::into)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn create_tar_from_src<P: AsRef<Path>, W: Write>(src_dir: P, dest_file: W) -> crate::Result<W> {
|
||||
let src_dir = src_dir.as_ref();
|
||||
let mut tar_builder = tar::Builder::new(dest_file);
|
||||
|
||||
Reference in New Issue
Block a user