diff --git a/.changes/add-pacman-support.md b/.changes/add-pacman-support.md deleted file mode 100644 index d7636008..00000000 --- a/.changes/add-pacman-support.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"cargo-packager": minor -"@crabnebula/packager": minor ---- - -Add Arch Linux package manager, `pacman` support for cargo packager. diff --git a/.changes/resource-resolver-initial-release.md b/.changes/resource-resolver-initial-release.md deleted file mode 100644 index f8e8f385..00000000 --- a/.changes/resource-resolver-initial-release.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"cargo-packager-utils": minor -"cargo-packager-resource-resolver": minor -"@crabnebula/packager-resource-resolver": minor ---- - -Initial Release. diff --git a/.github/workflows/covector-version-or-publish.yml b/.github/workflows/covector-version-or-publish.yml index 467d429b..d2df9582 100644 --- a/.github/workflows/covector-version-or-publish.yml +++ b/.github/workflows/covector-version-or-publish.yml @@ -53,7 +53,7 @@ jobs: if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, '@crabnebula/packager') - uses: peter-evans/repository-dispatch@v2 + uses: peter-evans/repository-dispatch@v3 with: event-type: publish-packager-nodejs client-payload: >- @@ -63,7 +63,7 @@ jobs: if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, '@crabnebula/updater') - uses: peter-evans/repository-dispatch@v2 + uses: peter-evans/repository-dispatch@v3 with: event-type: publish-updater-nodejs client-payload: >- @@ -73,7 +73,7 @@ jobs: if: | steps.covector.outputs.successfulPublish == 'true' && contains(steps.covector.outputs.packagesPublished, '@crabnebula/packager-resource-resolver') - uses: peter-evans/repository-dispatch@v2 + uses: peter-evans/repository-dispatch@v3 with: event-type: publish-packager-resource-resolver-nodejs client-payload: >- diff --git a/.github/workflows/publish-packager-resource-resolver-nodejs.yml b/.github/workflows/publish-packager-resource-resolver-nodejs.yml index a539b5b9..a6d43739 100644 --- a/.github/workflows/publish-packager-resource-resolver-nodejs.yml +++ b/.github/workflows/publish-packager-resource-resolver-nodejs.yml @@ -58,7 +58,7 @@ jobs: - host: macos-latest target: aarch64-apple-darwin build: | - pnpm build --target aarch64-apple-darwin --features native-tls-vendored --cargo-flags="--no-default-features" + pnpm build --target aarch64-apple-darwin strip -x *.node - host: ubuntu-latest target: aarch64-unknown-linux-gnu @@ -87,7 +87,7 @@ jobs: /aarch64-linux-musl-cross/bin/aarch64-linux-musl-strip *.node - host: windows-latest target: aarch64-pc-windows-msvc - build: pnpm build --target aarch64-pc-windows-msvc --features native-tls-vendored --cargo-flags="--no-default-features" + build: pnpm build --target aarch64-pc-windows-msvc name: stable - ${{ matrix.settings.target }} - node@18 runs-on: ${{ matrix.settings.host }} steps: diff --git a/Cargo.lock b/Cargo.lock index 973c16ed..60f8d60d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -978,7 +978,7 @@ dependencies = [ [[package]] name = "cargo-packager" -version = "0.4.5" +version = "0.5.0" dependencies = [ "ar", "base64 0.21.7", @@ -1035,7 +1035,7 @@ dependencies = [ [[package]] name = "cargo-packager-resource-resolver" -version = "0.0.0" +version = "0.1.0" dependencies = [ "cargo-packager-utils", "heck", @@ -1045,7 +1045,7 @@ dependencies = [ [[package]] name = "cargo-packager-updater" -version = "0.1.1" +version = "0.1.2" dependencies = [ "base64 0.21.7", "cargo-packager-utils", @@ -1076,7 +1076,7 @@ dependencies = [ [[package]] name = "cargo-packager-utils" -version = "0.0.0" +version = "0.1.0" dependencies = [ "clap", "ctor 0.2.6", @@ -4487,9 +4487,9 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.14.6" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61bec1ee990ae3e9a5f443484c65fb38e571a898437f0ad283ed69c82fc59c0" +checksum = "7622f0dbe0968af2dacdd64870eee6dee94f93c989c841f1ad8f300cf1abd514" dependencies = [ "cfg-if", "convert_case 0.6.0", @@ -4501,9 +4501,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2314f777bc9cde51705d991c44466cee4de4a3f41c6d3d019fcbbebb5cdd47c4" +checksum = "8ec514d65fce18a959be55e7f683ac89c6cb850fb59b09e25ab777fd5a4a8d9e" dependencies = [ "convert_case 0.6.0", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 251c4e0f..27c96719 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ tracing = "0.1" time = "0.3" tar = "0.4" napi = { version = "2.15", default-features = false } -napi-derive = "2.14" +napi-derive = "2.15" napi-build = "2.1.0" [profile.release-size-optimized] diff --git a/bindings/packager/nodejs/CHANGELOG.md b/bindings/packager/nodejs/CHANGELOG.md index ea63b1f8..f8d20a5d 100644 --- a/bindings/packager/nodejs/CHANGELOG.md +++ b/bindings/packager/nodejs/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## \[0.2.0] + +- [`9bdb953`](https://www.github.com/crabnebula-dev/cargo-packager/commit/9bdb953f1b48c8d69d86e9e42295cd36453c1648)([#137](https://www.github.com/crabnebula-dev/cargo-packager/pull/137)) Add Arch Linux package manager, `pacman` support for cargo packager. +- [`a29943e`](https://www.github.com/crabnebula-dev/cargo-packager/commit/a29943e8c95d70e8b77c23021ce52f6ee13314c8)([#140](https://www.github.com/crabnebula-dev/cargo-packager/pull/140)) Fix codesigning failing on macOS under certain circumstances when the order in which files were signed was not + deterministic and nesting required signing files nested more deeply first. + +### Dependencies + +- Upgraded to `cargo-packager@0.5.0` +- Upgraded to `cargo-packager-utils@0.1.0` + ## \[0.1.5] - [`f08e4b8`](https://www.github.com/crabnebula-dev/cargo-packager/commit/f08e4b8972b072617fdb78f11e222427e49ebe8e) Fix the signing and notarization process for MacOS bundles diff --git a/bindings/packager/nodejs/package.json b/bindings/packager/nodejs/package.json index a3768300..56fae085 100644 --- a/bindings/packager/nodejs/package.json +++ b/bindings/packager/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@crabnebula/packager", - "version": "0.1.5", + "version": "0.2.0", "main": "build/index.js", "module": "build/index.js", "types": "build/index.d.ts", diff --git a/bindings/packager/nodejs/packager.js b/bindings/packager/nodejs/packager.js old mode 100644 new mode 100755 diff --git a/bindings/resource-resolver/nodejs/CHANGELOG.md b/bindings/resource-resolver/nodejs/CHANGELOG.md new file mode 100644 index 00000000..dec05536 --- /dev/null +++ b/bindings/resource-resolver/nodejs/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +## \[0.1.0] + +- [`cd0242b`](https://www.github.com/crabnebula-dev/cargo-packager/commit/cd0242b8a41b2f7ecb78dfbae04b3a2e1c72c931) Initial Release. + +### Dependencies + +- Upgraded to `cargo-packager-utils@0.1.0` +- Upgraded to `cargo-packager-resource-resolver@0.1.0` diff --git a/bindings/resource-resolver/nodejs/__test__/index.spec.mjs b/bindings/resource-resolver/nodejs/__test__/index.spec.mjs new file mode 100644 index 00000000..c69ce3cd --- /dev/null +++ b/bindings/resource-resolver/nodejs/__test__/index.spec.mjs @@ -0,0 +1,8 @@ +import test from "ava"; + +import { resourcesDir, PackageFormat } from "../index.js"; + +test("resolve resource directory", async (t) => { + const dir = resourcesDir(PackageFormat.Nsis); + t.is(typeof dir, "string"); +}); diff --git a/bindings/resource-resolver/nodejs/package.json b/bindings/resource-resolver/nodejs/package.json index 76628ed1..887170e6 100644 --- a/bindings/resource-resolver/nodejs/package.json +++ b/bindings/resource-resolver/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@crabnebula/packager-resource-resolver", - "version": "0.0.0", + "version": "0.1.0", "main": "./index.js", "types": "./index.d.ts", "napi": { @@ -24,12 +24,17 @@ "postbuild": "node ./fix-types.js", "build:debug": "napi build --platform", "prepublishOnly": "napi prepublish -t npm --gh-release-id $RELEASE_ID", + "test": "ava --no-worker-threads --timeout 30m", "universal": "napi universal", "version": "napi version" }, "devDependencies": { "@napi-rs/cli": "^2.16.5", - "@types/node": "^20.8.10" + "@types/node": "^20.8.10", + "ava": "^6.0.0" + }, + "ava": { + "timeout": "3m" }, "engines": { "node": ">= 10" diff --git a/bindings/updater/nodejs/CHANGELOG.md b/bindings/updater/nodejs/CHANGELOG.md index 5aadaf4e..7a48212f 100644 --- a/bindings/updater/nodejs/CHANGELOG.md +++ b/bindings/updater/nodejs/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## \[0.1.2] + +- [`005a55f`](https://www.github.com/crabnebula-dev/cargo-packager/commit/005a55fb27b92503b3d6f936cffb088ccf346c40)([#143](https://www.github.com/crabnebula-dev/cargo-packager/pull/143)) Fix the download callback parameters to be accurate to typescript definitions + +### Dependencies + +- Upgraded to `cargo-packager-utils@0.1.0` +- Upgraded to `cargo-packager-updater@0.1.2` + ## \[0.1.1] - [`feb53a2`](https://www.github.com/crabnebula-dev/cargo-packager/commit/feb53a2f16ef2c8d93ff2d73a4eb318490f33471)([#102](https://www.github.com/crabnebula-dev/cargo-packager/pull/102)) Fix NSIS updater failing to launch when using `basicUi` mode. diff --git a/bindings/updater/nodejs/index.d.ts b/bindings/updater/nodejs/index.d.ts index 0a3455f0..2e67c3b7 100644 --- a/bindings/updater/nodejs/index.d.ts +++ b/bindings/updater/nodejs/index.d.ts @@ -75,7 +75,7 @@ export class Update { date?: string /** Request timeout */ timeout?: number - download(onChunk?: (chunkLength: number, contentLength: number | null) => void, onDownloadFinished?: () => void): Promise> - install(bytes: Array): Promise + download(onChunk?: (chunkLength: number, contentLength: number | null) => void, onDownloadFinished?: () => void): Promise + install(buffer: ArrayBuffer): Promise downloadAndInstall(onChunk?: (chunkLength: number, contentLength?: number) => void, onDownloadFinished?: () => void): Promise } diff --git a/bindings/updater/nodejs/package.json b/bindings/updater/nodejs/package.json index 6c4e45ba..39612b29 100644 --- a/bindings/updater/nodejs/package.json +++ b/bindings/updater/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@crabnebula/updater", - "version": "0.1.1", + "version": "0.1.2", "main": "./index.js", "types": "./index.d.ts", "napi": { diff --git a/bindings/updater/nodejs/src/lib.rs b/bindings/updater/nodejs/src/lib.rs index 26824277..0880f0ae 100644 --- a/bindings/updater/nodejs/src/lib.rs +++ b/bindings/updater/nodejs/src/lib.rs @@ -6,8 +6,9 @@ use cargo_packager_updater::{ Updater, UpdaterBuilder, }; use napi::{ + bindgen_prelude::AsyncTask, threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode}, - Error, Result, Status, + Env, Error, JsArrayBuffer, Result, Status, Task, }; mod from_impls; @@ -178,94 +179,196 @@ impl Update { } } +type TaskCallbackFunction = Option>; + +pub struct DownloadTask { + update: cargo_packager_updater::Update, + on_chunk: TaskCallbackFunction<(u32, Option)>, + on_download_finished: TaskCallbackFunction<()>, +} + +impl DownloadTask { + pub fn create( + update: &Update, + on_chunk: TaskCallbackFunction<(u32, Option)>, + on_download_finished: TaskCallbackFunction<()>, + ) -> Result { + Ok(Self { + update: update.create_update()?, + on_chunk, + on_download_finished, + }) + } +} + +impl Task for DownloadTask { + type Output = Vec; + type JsValue = JsArrayBuffer; + + fn compute(&mut self) -> Result { + let on_chunk = |chunk_len: usize, content_len: Option| { + if let Some(on_chunk) = &self.on_chunk { + on_chunk.call( + (chunk_len as _, content_len.map(|v| v as _)), + ThreadsafeFunctionCallMode::NonBlocking, + ); + } + }; + + let on_finish = || { + if let Some(on_download_finished) = &self.on_download_finished { + on_download_finished.call((), ThreadsafeFunctionCallMode::NonBlocking); + } + }; + + self.update + .download_extended(on_chunk, on_finish) + .map_err(|e| Error::new(Status::GenericFailure, e)) + } + + fn resolve(&mut self, env: Env, output: Self::Output) -> Result { + let mut buffer = env.create_arraybuffer(output.len())?; + unsafe { std::ptr::copy(output.as_ptr(), buffer.as_mut_ptr(), output.len()) }; + + Ok(buffer.into_raw()) + } +} + +pub struct InstallTask { + update: cargo_packager_updater::Update, + bytes: Option>, +} + +impl InstallTask { + pub fn create(update: &Update, bytes: Vec) -> Result { + Ok(Self { + update: update.create_update()?, + bytes: Some(bytes), + }) + } +} + +impl Task for InstallTask { + type Output = (); + type JsValue = (); + + fn compute(&mut self) -> Result { + self.update + .install(self.bytes.take().unwrap()) + .map_err(|e| Error::new(Status::GenericFailure, e)) + } + + fn resolve(&mut self, _env: Env, _output: Self::Output) -> Result { + Ok(()) + } +} + +pub struct DownloadAndInstallTask { + download_task: DownloadTask, +} + +impl DownloadAndInstallTask { + pub fn new(download_task: DownloadTask) -> Self { + Self { download_task } + } +} + +impl Task for DownloadAndInstallTask { + type Output = (); + type JsValue = (); + + fn compute(&mut self) -> Result { + let bytes = self.download_task.compute()?; + self.download_task + .update + .install(bytes) + .map_err(|e| Error::new(Status::GenericFailure, e)) + } + + fn resolve(&mut self, _env: Env, _output: Self::Output) -> Result { + Ok(()) + } +} + +pub struct CheckUpdateTask { + updater: Updater, +} + +impl CheckUpdateTask { + pub fn create(current_version: String, options: Options) -> Result { + let current_version = current_version.parse().map_err(|e| { + Error::new( + Status::InvalidArg, + format!("Failed to parse string as a valid semver, {e}"), + ) + })?; + + let updater = options.into_updater(current_version)?; + + Ok(Self { updater }) + } +} + +impl Task for CheckUpdateTask { + type Output = Option; + type JsValue = Option; + + fn compute(&mut self) -> Result { + self.updater.check().map_err(|e| { + Error::new( + Status::GenericFailure, + format!("Failed to check for update, {e}"), + ) + }) + } + + fn resolve(&mut self, _env: Env, output: Self::Output) -> Result { + Ok(output.map(Into::into)) + } +} + #[napi_derive::napi] impl Update { #[napi( - ts_args_type = "onChunk?: (chunkLength: number, contentLength: number | null) => void, onDownloadFinished?: () => void" + ts_args_type = "onChunk?: (chunkLength: number, contentLength: number | null) => void, onDownloadFinished?: () => void", + ts_return_type = "Promise" )] - pub async fn download( + pub fn download( &self, - on_chunk: Option), ErrorStrategy::CalleeHandled>>, - on_download_finish: Option>, - ) -> Result> { - let update = self.create_update()?; - - update - .download_extended( - |c, l| { - if let Some(on_chunk) = &on_chunk { - on_chunk.call( - Ok((c as u32, l.map(|l| l as u32))), - ThreadsafeFunctionCallMode::Blocking, - ); - } - }, - || { - if let Some(on_download_finish) = on_download_finish { - on_download_finish.call(Ok(()), ThreadsafeFunctionCallMode::Blocking); - } - }, - ) - .map_err(|e| Error::new(Status::GenericFailure, e.to_string())) + on_chunk: TaskCallbackFunction<(u32, Option)>, + on_download_finish: TaskCallbackFunction<()>, + ) -> Result> { + DownloadTask::create(self, on_chunk, on_download_finish).map(AsyncTask::new) } - #[napi] - pub async fn install(&self, bytes: Vec) -> Result<()> { - let update = self.create_update()?; - update - .install(bytes) - .map_err(|e| Error::new(Status::GenericFailure, e.to_string())) + #[napi(ts_return_type = "Promise", ts_args_type = "buffer: ArrayBuffer")] + pub fn install(&self, bytes: JsArrayBuffer) -> Result> { + let bytes = bytes.into_value()?; + let bytes = bytes.as_ref().to_vec(); + InstallTask::create(self, bytes).map(AsyncTask::new) } #[napi( - ts_args_type = "onChunk?: (chunkLength: number, contentLength?: number) => void, onDownloadFinished?: () => void" + ts_args_type = "onChunk?: (chunkLength: number, contentLength?: number) => void, onDownloadFinished?: () => void", + ts_return_type = "Promise" )] - pub async fn download_and_install( + pub fn download_and_install( &self, - on_chunk: Option), ErrorStrategy::CalleeHandled>>, - on_download_finish: Option>, - ) -> Result<()> { - let update = self.create_update()?; - let bytes = update - .download_extended( - |c, l| { - if let Some(on_chunk) = &on_chunk { - on_chunk.call( - Ok((c as u32, l.map(|l| l as u32))), - ThreadsafeFunctionCallMode::Blocking, - ); - } - }, - || { - if let Some(on_download_finish) = on_download_finish { - on_download_finish.call(Ok(()), ThreadsafeFunctionCallMode::Blocking); - } - }, - ) - .map_err(|e| Error::new(Status::GenericFailure, e.to_string()))?; - update - .install(bytes) - .map_err(|e| Error::new(Status::GenericFailure, e.to_string())) + on_chunk: TaskCallbackFunction<(u32, Option)>, + on_download_finish: TaskCallbackFunction<()>, + ) -> Result> { + let download_task = DownloadTask::create(self, on_chunk, on_download_finish)?; + Ok(AsyncTask::new(DownloadAndInstallTask::new(download_task))) } } -#[napi_derive::napi] -pub async fn check_update(current_version: String, options: Options) -> Result> { - let current_version = current_version.parse().map_err(|e| { - Error::new( - Status::InvalidArg, - format!("Failed to parse string as a valid semver, {e}"), - ) - })?; - - let updater = options.into_updater(current_version)?; - - let update = updater.check().map_err(|e| { - Error::new( - Status::GenericFailure, - format!("Failed to check for update, {e}"), - ) - })?; - - Ok(update.map(Into::into)) +#[napi_derive::napi(ts_return_type = "Promise")] +pub fn check_update( + current_version: String, + options: Options, +) -> Result> { + Ok(AsyncTask::new(CheckUpdateTask::create( + current_version, + options, + )?)) } diff --git a/crates/packager/CHANGELOG.md b/crates/packager/CHANGELOG.md index c25dea14..9a290d9d 100644 --- a/crates/packager/CHANGELOG.md +++ b/crates/packager/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## \[0.5.0] + +- [`9bdb953`](https://www.github.com/crabnebula-dev/cargo-packager/commit/9bdb953f1b48c8d69d86e9e42295cd36453c1648)([#137](https://www.github.com/crabnebula-dev/cargo-packager/pull/137)) Add Arch Linux package manager, `pacman` support for cargo packager. +- [`a29943e`](https://www.github.com/crabnebula-dev/cargo-packager/commit/a29943e8c95d70e8b77c23021ce52f6ee13314c8)([#140](https://www.github.com/crabnebula-dev/cargo-packager/pull/140)) Fix codesigning failing on macOS under certain circumstances when the order in which files were signed was not + deterministic and nesting required signing files nested more deeply first. + +### Dependencies + +- Upgraded to `cargo-packager-utils@0.1.0` + ## \[0.4.5] - [`f08e4b8`](https://www.github.com/crabnebula-dev/cargo-packager/commit/f08e4b8972b072617fdb78f11e222427e49ebe8e) Fix the signing and notarization process for MacOS bundles diff --git a/crates/packager/Cargo.toml b/crates/packager/Cargo.toml index 55fec3d9..96b65415 100644 --- a/crates/packager/Cargo.toml +++ b/crates/packager/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cargo-packager" -version = "0.4.5" +version = "0.5.0" description = "Executable packager and bundler distributed as a CLI and library." authors = [ "CrabNebula Ltd.", @@ -32,7 +32,7 @@ targets = [ default = [ "cli", "rustls-tls" ] cli = [ "clap", "dep:tracing-subscriber" ] schema = [ "schemars", "cargo-packager-utils/schema" ] -clap = ["dep:clap", "cargo-packager-utils/clap" ] +clap = [ "dep:clap", "cargo-packager-utils/clap" ] native-tls = [ "ureq/native-tls" ] native-tls-vendored = [ "native-tls", "native-tls/vendored" ] rustls-tls = [ "ureq/tls" ] @@ -66,7 +66,7 @@ flate2 = "1.0" strsim = "0.10" schemars = { workspace = true, optional = true } native-tls = { version = "0.2", optional = true } -cargo-packager-utils = { version = "0.0.0", path = "../utils" , features = ["serde"] } +cargo-packager-utils = { version = "0.1.0", path = "../utils", features = [ "serde" ] } [target."cfg(target_os = \"windows\")".dependencies] winreg = "0.52" diff --git a/crates/packager/src/codesign/macos.rs b/crates/packager/src/codesign/macos.rs index 04a1e883..a474f7ba 100644 --- a/crates/packager/src/codesign/macos.rs +++ b/crates/packager/src/codesign/macos.rs @@ -4,6 +4,7 @@ // SPDX-License-Identifier: MIT use std::{ + cmp::Ordering, ffi::OsString, fs::File, io::prelude::*, @@ -145,12 +146,29 @@ pub fn delete_keychain() { .output_ok(); } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub struct SignTarget { pub path: PathBuf, pub is_native_binary: bool, } +impl Ord for SignTarget { + fn cmp(&self, other: &Self) -> Ordering { + let self_count = self.path.components().count(); + let other_count = other.path.components().count(); + + // Sort by path depth (note that we compare other to self, not self to other) so + // that longer paths have a smaller value! + other_count.cmp(&self_count) + } +} + +impl PartialOrd for SignTarget { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + #[tracing::instrument(level = "trace")] pub fn try_sign(targets: Vec, identity: &str, config: &Config) -> crate::Result<()> { let packager_keychain = if let (Some(certificate_encoded), Some(certificate_password)) = ( diff --git a/crates/packager/src/package/app/mod.rs b/crates/packager/src/package/app/mod.rs index e62f38ea..0210498a 100644 --- a/crates/packager/src/package/app/mod.rs +++ b/crates/packager/src/package/app/mod.rs @@ -5,6 +5,7 @@ // SPDX-License-Identifier: MIT use std::{ + collections::BinaryHeap, ffi::OsStr, path::{Path, PathBuf}, process::Command, @@ -43,7 +44,7 @@ pub(crate) fn package(ctx: &Context) -> crate::Result> { let bin_dir = contents_directory.join("MacOS"); std::fs::create_dir_all(&bin_dir)?; - let mut sign_paths = Vec::new(); + let mut sign_paths = BinaryHeap::new(); let bundle_icon_file = util::create_icns_file(&resources_dir, config)?; @@ -53,67 +54,12 @@ pub(crate) fn package(ctx: &Context) -> crate::Result> { tracing::debug!("Copying frameworks"); let framework_paths = copy_frameworks_to_bundle(&contents_directory, config)?; - // All dylib files and native executables should be signed manually - // It is highly discouraged by Apple to use the --deep codesign parameter in larger projects. - // https://developer.apple.com/forums/thread/129980 - for framework_path in &framework_paths { - if let Some(framework_path) = framework_path.to_str() { - // Find all files in the current framework folder - let files = walkdir::WalkDir::new(framework_path) - .into_iter() - .flatten() - .map(|dir| dir.into_path()) - .collect::>(); - - // Filter all files for Mach-O headers. This will target all .dylib and native executable files - for file in files { - let metadata = match std::fs::metadata(&file) { - Ok(f) => f, - Err(err) => { - tracing::warn!("Failed to get metadata for {}: {err}, this file will not be scanned for Mach-O header!", file.display()); - continue; - } - }; - - if !metadata.is_file() { - continue; - } - - let mut open_file = match std::fs::File::open(&file) { - Ok(f) => f, - Err(err) => { - tracing::warn!("Failed to open {} for reading: {err}, this file will not be scanned for Mach-O header!", file.display()); - continue; - } - }; - - let mut buffer = [0; 4]; - std::io::Read::read_exact(&mut open_file, &mut buffer)?; - - const MACH_O_MAGIC_NUMBERS: [u32; 5] = - [0xfeedface, 0xfeedfacf, 0xcafebabe, 0xcefaedfe, 0xcffaedfe]; - - let magic = u32::from_be_bytes(buffer); - - let is_mach = MACH_O_MAGIC_NUMBERS.contains(&magic); - if !is_mach { - continue; - } - - sign_paths.push(SignTarget { - path: file, - is_native_binary: true, - }); - } - } - } - sign_paths.extend( framework_paths .into_iter() .filter(|p| { let ext = p.extension(); - ext == Some(OsStr::new("framework")) || ext == Some(OsStr::new("dylib")) + ext == Some(OsStr::new("framework")) }) .map(|path| SignTarget { path, @@ -125,19 +71,61 @@ pub(crate) fn package(ctx: &Context) -> crate::Result> { config.copy_resources(&resources_dir)?; tracing::debug!("Copying external binaries"); - let bin_paths = config.copy_external_binaries(&bin_dir)?; - sign_paths.extend(bin_paths.into_iter().map(|path| SignTarget { - path, - is_native_binary: true, - })); - + config.copy_external_binaries(&bin_dir)?; tracing::debug!("Copying binaries"); for bin in &config.binaries { let bin_path = config.binary_path(bin); let dest_path = bin_dir.join(bin.path.file_name().unwrap()); std::fs::copy(&bin_path, &dest_path)?; + } + + // All dylib files and native executables should be signed manually + // It is highly discouraged by Apple to use the --deep codesign parameter in larger projects. + // https://developer.apple.com/forums/thread/129980 + + // Find all files in the app bundle + let files = walkdir::WalkDir::new(&app_bundle_path) + .into_iter() + .flatten() + .map(|dir| dir.into_path()); + + // Filter all files for Mach-O headers. This will target all .dylib and native executable files + for file in files { + let metadata = match std::fs::metadata(&file) { + Ok(f) => f, + Err(err) => { + tracing::warn!("Failed to get metadata for {}: {err}, this file will not be scanned for Mach-O header!", file.display()); + continue; + } + }; + + if !metadata.is_file() { + continue; + } + + let mut open_file = match std::fs::File::open(&file) { + Ok(f) => f, + Err(err) => { + tracing::warn!("Failed to open {} for reading: {err}, this file will not be scanned for Mach-O header!", file.display()); + continue; + } + }; + + let mut buffer = [0; 4]; + std::io::Read::read_exact(&mut open_file, &mut buffer)?; + + const MACH_O_MAGIC_NUMBERS: [u32; 5] = + [0xfeedface, 0xfeedfacf, 0xcafebabe, 0xcefaedfe, 0xcffaedfe]; + + let magic = u32::from_be_bytes(buffer); + + let is_mach = MACH_O_MAGIC_NUMBERS.contains(&magic); + if !is_mach { + continue; + } + sign_paths.push(SignTarget { - path: dest_path, + path: file, is_native_binary: true, }); } @@ -159,6 +147,7 @@ pub(crate) fn package(ctx: &Context) -> crate::Result> { remove_extra_attr(&app_bundle_path)?; // sign application + let sign_paths = sign_paths.into_sorted_vec(); codesign::try_sign(sign_paths, identity, config)?; // notarization is required for distribution diff --git a/crates/resource-resolver/CHANGELOG.md b/crates/resource-resolver/CHANGELOG.md new file mode 100644 index 00000000..58678e35 --- /dev/null +++ b/crates/resource-resolver/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## \[0.1.0] + +- [`cd0242b`](https://www.github.com/crabnebula-dev/cargo-packager/commit/cd0242b8a41b2f7ecb78dfbae04b3a2e1c72c931) Initial Release. + +### Dependencies + +- Upgraded to `cargo-packager-utils@0.1.0` diff --git a/crates/resource-resolver/Cargo.toml b/crates/resource-resolver/Cargo.toml index 43d4544a..cca64047 100644 --- a/crates/resource-resolver/Cargo.toml +++ b/crates/resource-resolver/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "cargo-packager-resource-resolver" description = "Cargo packager resource resolver" -version = "0.0.0" +version = "0.1.0" authors = { workspace = true } edition = { workspace = true } license = { workspace = true } repository = { workspace = true } [package.metadata.docs.rs] -features = ["auto-detect-format"] +features = [ "auto-detect-format" ] [dependencies] thiserror = { workspace = true } -cargo-packager-utils = { version = "0.0.0", path = "../utils", default-features = false } +cargo-packager-utils = { version = "0.1.0", path = "../utils", default-features = false } log = "0.4.20" heck = "0.4.1" [features] -process-relaunch-dangerous-allow-symlink-macos = [] -auto-detect-format = [] +process-relaunch-dangerous-allow-symlink-macos = [ ] +auto-detect-format = [ ] diff --git a/crates/updater/CHANGELOG.md b/crates/updater/CHANGELOG.md index f3cb238a..a6eccdba 100644 --- a/crates/updater/CHANGELOG.md +++ b/crates/updater/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## \[0.1.2] + +### Dependencies + +- Upgraded to `cargo-packager-utils@0.1.0` + ## \[0.1.1] - [`feb53a2`](https://www.github.com/crabnebula-dev/cargo-packager/commit/feb53a2f16ef2c8d93ff2d73a4eb318490f33471)([#102](https://www.github.com/crabnebula-dev/cargo-packager/pull/102)) Fix NSIS updater failing to launch when using `basicUi` mode. diff --git a/crates/updater/Cargo.toml b/crates/updater/Cargo.toml index 9a4b02a6..9ab3abb6 100644 --- a/crates/updater/Cargo.toml +++ b/crates/updater/Cargo.toml @@ -1,26 +1,24 @@ [package] name = "cargo-packager-updater" -version = "0.1.1" +version = "0.1.2" description = "Rust executable updater." -authors = ["CrabNebula Ltd.", "Tauri Programme within The Commons Conservancy"] +authors = [ + "CrabNebula Ltd.", + "Tauri Programme within The Commons Conservancy" +] edition = { workspace = true } license = { workspace = true } repository = { workspace = true } [features] -process-relaunch-dangerous-allow-symlink-macos = [] -native-tls = ["reqwest/native-tls"] -native-tls-vendored = ["reqwest/native-tls-vendored"] -rustls-tls = ["reqwest/rustls-tls"] +process-relaunch-dangerous-allow-symlink-macos = [ ] +native-tls = [ "reqwest/native-tls" ] +native-tls-vendored = [ "reqwest/native-tls-vendored" ] +rustls-tls = [ "reqwest/rustls-tls" ] [dependencies] -cargo-packager-utils = { version = "0.0.0", path = "../utils" } - -reqwest = { version = "0.11", default-features = false, features = [ - "json", - "stream", - "blocking", -] } +cargo-packager-utils = { version = "0.1.0", path = "../utils" } +reqwest = { version = "0.11", default-features = false, features = [ "json", "stream", "blocking" ] } thiserror = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -28,12 +26,13 @@ dunce = { workspace = true } dirs = { workspace = true } semver = { workspace = true } base64 = { workspace = true } -time = { workspace = true, features = ["parsing", "formatting"] } +time = { workspace = true, features = [ "parsing", "formatting" ] } http = "0.2" -url = { version = "2.5", features = ["serde"] } +url = { version = "2.5", features = [ "serde" ] } minisign-verify = "0.2" ctor = "0.2" tempfile = "3.9" + [target."cfg(target_os = \"macos\")".dependencies] tar = { workspace = true } flate2 = "1.0" diff --git a/crates/utils/CHANGELOG.md b/crates/utils/CHANGELOG.md new file mode 100644 index 00000000..3360b283 --- /dev/null +++ b/crates/utils/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## \[0.1.0] + +- [`cd0242b`](https://www.github.com/crabnebula-dev/cargo-packager/commit/cd0242b8a41b2f7ecb78dfbae04b3a2e1c72c931) Initial Release. diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 7441e18a..c1c5e39a 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "cargo-packager-utils" -version = "0.0.0" +description = "Utilities for cargo-packager crates" +version = "0.1.0" authors = { workspace = true } edition = { workspace = true } license = { workspace = true } @@ -13,8 +14,8 @@ clap = { workspace = true, optional = true } serde = { workspace = true, optional = true } [features] -default = ["cli"] -cli = [] -schema = ["schemars"] -clap = ["dep:clap"] -serde = ["dep:serde"] +default = [ "cli" ] +cli = [ ] +schema = [ "schemars" ] +clap = [ "dep:clap" ] +serde = [ "dep:serde" ] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c429f2c0..e2ea2458 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,6 +57,9 @@ importers: '@types/node': specifier: ^20.8.10 version: 20.9.1 + ava: + specifier: ^6.0.0 + version: 6.0.0 bindings/updater/nodejs: devDependencies: