From 8f788f9ad5cb072483d3d0faabf06086728b0ed6 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 11 Apr 2025 08:01:32 +0000
Subject: [PATCH 01/64] Update sample js packages
---
samples/NodeJSElectron/package-lock.json | 14 +++++++-------
samples/NodeJSElectron/package.json | 2 +-
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/samples/NodeJSElectron/package-lock.json b/samples/NodeJSElectron/package-lock.json
index 39a23ff1..4a1926a9 100644
--- a/samples/NodeJSElectron/package-lock.json
+++ b/samples/NodeJSElectron/package-lock.json
@@ -18,7 +18,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "35.1.4",
+ "electron": "35.1.5",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
@@ -3297,9 +3297,9 @@
"license": "MIT"
},
"node_modules/electron": {
- "version": "35.1.4",
- "resolved": "https://registry.npmjs.org/electron/-/electron-35.1.4.tgz",
- "integrity": "sha512-8HjE2wqxY//T09Of8k1eTpK/NeTG2FkTyRD+fyKXmec4wZVscGgZcmWFC0HYN4ktyHAjtplpxdFXjtqRnvzBMg==",
+ "version": "35.1.5",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-35.1.5.tgz",
+ "integrity": "sha512-LolvbKKQUSCGvEwbEQNt1cxD1t+YYClDNwBIjn4d28KM8FSqUn9zJuf6AbqNA7tVs9OFl/EQpmg/m4lZV1hH8g==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -9020,9 +9020,9 @@
}
},
"node_modules/typescript": {
- "version": "5.8.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
- "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
diff --git a/samples/NodeJSElectron/package.json b/samples/NodeJSElectron/package.json
index a965d110..f34d8cd5 100644
--- a/samples/NodeJSElectron/package.json
+++ b/samples/NodeJSElectron/package.json
@@ -23,7 +23,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "35.1.4",
+ "electron": "35.1.5",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
From 68fe654a5c3bce4ea697a8ae67a6c8e52c962dd8 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 11 Apr 2025 19:46:42 +0000
Subject: [PATCH 02/64] Update sample dotnet packages
---
samples/CSharpAvalonia/CSharpAvalonia.csproj | 10 +++++-----
samples/CSharpUno/global.json | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/samples/CSharpAvalonia/CSharpAvalonia.csproj b/samples/CSharpAvalonia/CSharpAvalonia.csproj
index 023e1d97..0283a789 100644
--- a/samples/CSharpAvalonia/CSharpAvalonia.csproj
+++ b/samples/CSharpAvalonia/CSharpAvalonia.csproj
@@ -10,12 +10,12 @@
-
-
-
-
+
+
+
+
-
+
diff --git a/samples/CSharpUno/global.json b/samples/CSharpUno/global.json
index e385cb20..bbbdbf58 100644
--- a/samples/CSharpUno/global.json
+++ b/samples/CSharpUno/global.json
@@ -1,7 +1,7 @@
{
// To update the version of Uno please update the version of the Uno.Sdk here. See https://aka.platform.uno/upgrade-uno-packages for more information.
"msbuild-sdks": {
- "Uno.Sdk": "5.6.51"
+ "Uno.Sdk": "5.6.54"
},
"sdk":{
"allowPrerelease": false
From 9db4290a7d19e457f6e1c48bf7e7ce79bf40fd9e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 15 Apr 2025 13:16:56 +0000
Subject: [PATCH 03/64] Update dotnet packages
---
.../Velopack.Deployment/Velopack.Deployment.csproj | 2 +-
src/vpk/Velopack.Flow/Velopack.Flow.csproj | 8 ++++----
src/vpk/Velopack.Packaging/Velopack.Packaging.csproj | 12 ++++++------
src/vpk/Velopack.Vpk/Velopack.Vpk.csproj | 10 +++++-----
.../Velopack.Packaging.Tests.csproj | 2 +-
test/Velopack.Tests/Velopack.Tests.csproj | 2 +-
6 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
index 2ae316e7..c952ead5 100644
--- a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
+++ b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/vpk/Velopack.Flow/Velopack.Flow.csproj b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
index 0532232c..926cc7dc 100644
--- a/src/vpk/Velopack.Flow/Velopack.Flow.csproj
+++ b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
@@ -9,10 +9,10 @@
-
-
-
-
+
+
+
+
diff --git a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
index 70942a3a..17063df3 100644
--- a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
+++ b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
@@ -16,12 +16,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
index 572097d6..ffa682a5 100644
--- a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
+++ b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
@@ -17,18 +17,18 @@
-
-
+
+
-
+
-
-
+
+
diff --git a/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj b/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj
index acf8d7bc..8faf8eaf 100644
--- a/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj
+++ b/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/test/Velopack.Tests/Velopack.Tests.csproj b/test/Velopack.Tests/Velopack.Tests.csproj
index 4abb87ee..d3eff951 100644
--- a/test/Velopack.Tests/Velopack.Tests.csproj
+++ b/test/Velopack.Tests/Velopack.Tests.csproj
@@ -19,7 +19,7 @@
-
+
From f9bd4145439374167db8c3465021a48bd146efad Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sun, 13 Apr 2025 09:37:14 +0000
Subject: [PATCH 04/64] Update npm packages
---
src/lib-nodejs/package-lock.json | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index 2488c0e8..81110107 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -1186,9 +1186,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.14.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz",
- "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==",
+ "version": "22.14.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
+ "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4161,9 +4161,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.1.tgz",
- "integrity": "sha512-FT2PIRtZABwl6+ZCry8IY7JZ3xMuppsEV9qFVHOVe8jDzggwUZ9TsM4chyJxL9yi6LvkqcZYU3LmapEE454zBQ==",
+ "version": "29.3.2",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz",
+ "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4175,7 +4175,7 @@
"lodash.memoize": "^4.1.2",
"make-error": "^1.3.6",
"semver": "^7.7.1",
- "type-fest": "^4.38.0",
+ "type-fest": "^4.39.1",
"yargs-parser": "^21.1.1"
},
"bin": {
@@ -4304,9 +4304,9 @@
}
},
"node_modules/typescript": {
- "version": "5.8.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
- "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
From 9518c5a1551b282c1f8a3bf370d87166cd504c3d Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 15 Apr 2025 22:13:14 +0000
Subject: [PATCH 05/64] Update rust crates
---
Cargo.lock | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 12c87345..c985940e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -93,9 +93,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.97"
+version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
+checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "arbitrary"
@@ -368,9 +368,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.35"
+version = "4.5.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
+checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
dependencies = [
"clap_builder",
"clap_derive",
@@ -378,9 +378,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.35"
+version = "4.5.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
+checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
dependencies = [
"anstream",
"anstyle",
@@ -634,7 +634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1122,9 +1122,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
-version = "0.2.171"
+version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libloading"
@@ -1596,7 +1596,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.4.15",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1609,7 +1609,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.9.2",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1902,7 +1902,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix 1.0.1",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2110,9 +2110,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
-version = "3.0.10"
+version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b0351ca625c7b41a8e4f9bb6c5d9755f67f62c2187ebedecacd9974674b271d"
+checksum = "b7a3e9af6113ecd57b8c63d3cd76a385b2e3881365f1f489e54f49801d0c83ea"
dependencies = [
"base64",
"flate2",
@@ -2128,9 +2128,9 @@ dependencies = [
[[package]]
name = "ureq-proto"
-version = "0.3.5"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae239d0a3341aebc94259414d1dc67cfce87d41cbebc816772c91b77902fafa4"
+checksum = "fadf18427d33828c311234884b7ba2afb57143e6e7e69fda7ee883b624661e36"
dependencies = [
"base64",
"http",
@@ -2950,9 +2950,9 @@ dependencies = [
[[package]]
name = "zip"
-version = "2.6.0"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "febbe83a485467affa75a75d28dc7494acd2f819e549536c47d46b3089b56164"
+checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744"
dependencies = [
"arbitrary",
"crc32fast",
From e5f61a4aaa01850f7083cbed21e242618b2180a4 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 18 Apr 2025 05:54:44 +0000
Subject: [PATCH 06/64] Update sample rust crates
---
samples/RustIced/Cargo.lock | 68 ++++++++++++++++++-------------------
1 file changed, 34 insertions(+), 34 deletions(-)
diff --git a/samples/RustIced/Cargo.lock b/samples/RustIced/Cargo.lock
index 2091ce50..ba098f3c 100644
--- a/samples/RustIced/Cargo.lock
+++ b/samples/RustIced/Cargo.lock
@@ -101,9 +101,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.97"
+version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
+checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "approx"
@@ -1041,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2005,7 +2005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -2487,9 +2487,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.21.2"
+version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2806eaa3524762875e21c3dcd057bc4b7bfa01ce4da8d46be1cd43649e1cc6b"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "orbclient"
@@ -3035,7 +3035,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.4.15",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -3469,7 +3469,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -3887,7 +3887,7 @@ dependencies = [
"ureq",
"url",
"uuid",
- "windows 0.60.0",
+ "windows 0.61.1",
"xml",
"zip",
"zstd",
@@ -4300,7 +4300,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -4335,12 +4335,12 @@ dependencies = [
[[package]]
name = "windows"
-version = "0.60.0"
+version = "0.61.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddf874e74c7a99773e62b1c671427abf01a425e77c3d3fb9fb1e4883ea934529"
+checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
dependencies = [
"windows-collections",
- "windows-core 0.60.1",
+ "windows-core 0.61.0",
"windows-future",
"windows-link",
"windows-numerics",
@@ -4348,11 +4348,11 @@ dependencies = [
[[package]]
name = "windows-collections"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5467f79cc1ba3f52ebb2ed41dbb459b8e7db636cc3429458d9a852e15bc24dec"
+checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
dependencies = [
- "windows-core 0.60.1",
+ "windows-core 0.61.0",
]
[[package]]
@@ -4366,9 +4366,9 @@ dependencies = [
[[package]]
name = "windows-core"
-version = "0.60.1"
+version = "0.61.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca21a92a9cae9bf4ccae5cf8368dce0837100ddf6e6d57936749e85f152f6247"
+checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
dependencies = [
"windows-implement",
"windows-interface",
@@ -4379,19 +4379,19 @@ dependencies = [
[[package]]
name = "windows-future"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a787db4595e7eb80239b74ce8babfb1363d8e343ab072f2ffe901400c03349f0"
+checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
dependencies = [
- "windows-core 0.60.1",
+ "windows-core 0.61.0",
"windows-link",
]
[[package]]
name = "windows-implement"
-version = "0.59.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
"proc-macro2",
"quote",
@@ -4400,9 +4400,9 @@ dependencies = [
[[package]]
name = "windows-interface"
-version = "0.59.0"
+version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
@@ -4411,34 +4411,34 @@ dependencies = [
[[package]]
name = "windows-link"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
name = "windows-numerics"
-version = "0.1.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "005dea54e2f6499f2cee279b8f703b3cf3b5734a2d8d21867c8f44003182eeed"
+checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
- "windows-core 0.60.1",
+ "windows-core 0.61.0",
"windows-link",
]
[[package]]
name = "windows-result"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
-version = "0.3.1"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
+checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
dependencies = [
"windows-link",
]
From 801671a703a254f8ee42cc0eb00b0a6211ce5115 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 18 Apr 2025 23:36:00 +0000
Subject: [PATCH 07/64] Update dotnet packages
---
src/vpk/Velopack.Deployment/Velopack.Deployment.csproj | 2 +-
src/vpk/Velopack.Flow/Velopack.Flow.csproj | 6 +++---
src/vpk/Velopack.Packaging/Velopack.Packaging.csproj | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
index c952ead5..b624f397 100644
--- a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
+++ b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/vpk/Velopack.Flow/Velopack.Flow.csproj b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
index 926cc7dc..3cdfe9c7 100644
--- a/src/vpk/Velopack.Flow/Velopack.Flow.csproj
+++ b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
@@ -9,9 +9,9 @@
-
-
-
+
+
+
diff --git a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
index 17063df3..16134dbe 100644
--- a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
+++ b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
@@ -18,9 +18,9 @@
-
-
-
+
+
+
From 6ea0d56b5ba170d739d01285bc3b67343461a652 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 24 Apr 2025 22:30:26 -0700
Subject: [PATCH 08/64] Update sample dotnet packages to 11.2.8 (#617)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
samples/CSharpAvalonia/CSharpAvalonia.csproj | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/samples/CSharpAvalonia/CSharpAvalonia.csproj b/samples/CSharpAvalonia/CSharpAvalonia.csproj
index 0283a789..deba4c72 100644
--- a/samples/CSharpAvalonia/CSharpAvalonia.csproj
+++ b/samples/CSharpAvalonia/CSharpAvalonia.csproj
@@ -10,12 +10,12 @@
-
-
-
-
+
+
+
+
-
+
From 1084bb5aaa9b71712e5a32fa2377d5586654714e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 24 Apr 2025 22:31:26 -0700
Subject: [PATCH 09/64] Update dotnet packages (#616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
src/vpk/Velopack.Build/Velopack.Build.csproj | 2 +-
src/vpk/Velopack.Deployment/Velopack.Deployment.csproj | 2 +-
src/vpk/Velopack.Flow/Velopack.Flow.csproj | 6 +++---
src/vpk/Velopack.Packaging/Velopack.Packaging.csproj | 6 +++---
src/vpk/Velopack.Vpk/Velopack.Vpk.csproj | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/vpk/Velopack.Build/Velopack.Build.csproj b/src/vpk/Velopack.Build/Velopack.Build.csproj
index e1bb45fe..81545ae0 100644
--- a/src/vpk/Velopack.Build/Velopack.Build.csproj
+++ b/src/vpk/Velopack.Build/Velopack.Build.csproj
@@ -24,7 +24,7 @@
-
+
diff --git a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
index b624f397..1b77b103 100644
--- a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
+++ b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/vpk/Velopack.Flow/Velopack.Flow.csproj b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
index 3cdfe9c7..b6ca6e14 100644
--- a/src/vpk/Velopack.Flow/Velopack.Flow.csproj
+++ b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
@@ -9,9 +9,9 @@
-
-
-
+
+
+
diff --git a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
index 16134dbe..54eb18ff 100644
--- a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
+++ b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
@@ -18,9 +18,9 @@
-
-
-
+
+
+
diff --git a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
index ffa682a5..d67aa8fe 100644
--- a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
+++ b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
@@ -25,7 +25,7 @@
-
+
From 3a94c06325c3e22fbcb2b3022a40f47791ae400f Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 25 Apr 2025 05:33:08 +0000
Subject: [PATCH 10/64] Update dependency electron to v35.2.1
---
samples/NodeJSElectron/package-lock.json | 8 ++++----
samples/NodeJSElectron/package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/samples/NodeJSElectron/package-lock.json b/samples/NodeJSElectron/package-lock.json
index 4a1926a9..d1c205a8 100644
--- a/samples/NodeJSElectron/package-lock.json
+++ b/samples/NodeJSElectron/package-lock.json
@@ -18,7 +18,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "35.1.5",
+ "electron": "35.2.1",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
@@ -3297,9 +3297,9 @@
"license": "MIT"
},
"node_modules/electron": {
- "version": "35.1.5",
- "resolved": "https://registry.npmjs.org/electron/-/electron-35.1.5.tgz",
- "integrity": "sha512-LolvbKKQUSCGvEwbEQNt1cxD1t+YYClDNwBIjn4d28KM8FSqUn9zJuf6AbqNA7tVs9OFl/EQpmg/m4lZV1hH8g==",
+ "version": "35.2.1",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-35.2.1.tgz",
+ "integrity": "sha512-LO4xXLpzkPPUVLvAbdHMlW7N9Z+Qqz+7QsmSWXluTIQMeJk+v7o36nUTZghyA2I1s//tlMvuaCtle6Qo2W0Ktg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
diff --git a/samples/NodeJSElectron/package.json b/samples/NodeJSElectron/package.json
index f34d8cd5..f94577bc 100644
--- a/samples/NodeJSElectron/package.json
+++ b/samples/NodeJSElectron/package.json
@@ -23,7 +23,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "35.1.5",
+ "electron": "35.2.1",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
From fc7c462ec626d4d64422a4a51c1bad74f091e63c Mon Sep 17 00:00:00 2001
From: Kevin B
Date: Sun, 27 Apr 2025 11:53:10 -0700
Subject: [PATCH 11/64] Updating HMAC signature (#621)
This fixes an issue with the API key auth with Flow assuming the external URL will match the internal one (which fails when put being a gateway with TLS termination)
---
src/vpk/Velopack.Flow/HmacAuthHttpClientHandler.cs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/vpk/Velopack.Flow/HmacAuthHttpClientHandler.cs b/src/vpk/Velopack.Flow/HmacAuthHttpClientHandler.cs
index ebd906df..8a744873 100644
--- a/src/vpk/Velopack.Flow/HmacAuthHttpClientHandler.cs
+++ b/src/vpk/Velopack.Flow/HmacAuthHttpClientHandler.cs
@@ -15,8 +15,14 @@ public class HmacAuthHttpClientHandler(HttpMessageHandler innerHandler) : Delega
var key = keyParts[1];
var nonce = Guid.NewGuid().ToString();
+ string requestUri = "";
+
+ if (request.RequestUri is { } reqUri) {
+ requestUri = $"{reqUri.Host}{reqUri.PathAndQuery}";
+ }
+
var secondsSinceEpoch = HmacHelper.GetSecondsSinceEpoch();
- var signature = HmacHelper.BuildSignature(hashedId, request.Method.Method, request.RequestUri?.AbsoluteUri ?? "", secondsSinceEpoch, nonce);
+ var signature = HmacHelper.BuildSignature(hashedId, request.Method.Method, requestUri, secondsSinceEpoch, nonce);
var secret = HmacHelper.Calculate(Convert.FromBase64String(key), signature);
request.Headers.Authorization = BuildHeader(hashedId, secret, nonce, secondsSinceEpoch);
}
From 932f04cbac00808dd07a0e9c010d4a11e6ad821a Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sun, 27 Apr 2025 11:53:23 -0700
Subject: [PATCH 12/64] Update dependency @types/node to v22.15.2 (#618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
src/lib-nodejs/package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index 81110107..f88dc1cd 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -1186,9 +1186,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.14.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
- "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
+ "version": "22.15.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz",
+ "integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==",
"dev": true,
"license": "MIT",
"dependencies": {
From c8845299dbedc75e05eaf9904ce9a649e3d3c51b Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sun, 27 Apr 2025 11:53:52 -0700
Subject: [PATCH 13/64] Update Node.js to >=18.0.0 <=22.15.0 (#620)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
src/lib-nodejs/package-lock.json | 2 +-
src/lib-nodejs/package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index f88dc1cd..5506ce8b 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -24,7 +24,7 @@
"typescript": "^5.3.3"
},
"engines": {
- "node": ">=18.0.0 <=22.14.0"
+ "node": ">=18.0.0 <=22.15.0"
}
},
"node_modules/@ampproject/remapping": {
diff --git a/src/lib-nodejs/package.json b/src/lib-nodejs/package.json
index c8d4545b..ae66f947 100644
--- a/src/lib-nodejs/package.json
+++ b/src/lib-nodejs/package.json
@@ -36,7 +36,7 @@
"author": "Velopack Ltd, Caelan Sayler",
"license": "MIT",
"engines": {
- "node": ">=18.0.0 <=22.14.0"
+ "node": ">=18.0.0 <=22.15.0"
},
"files": [
"lib/**/*.ts",
From fc6adc6636e8fe848c42c1c5cda2cb40165bc29f Mon Sep 17 00:00:00 2001
From: Caelan
Date: Wed, 30 Apr 2025 23:26:32 +0100
Subject: [PATCH 14/64] Update README.md
---
README.md | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index d025b3a7..c415e42b 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,10 @@
---
[](https://www.nuget.org/packages/Velopack/)
-[](https://discord.gg/CjrCrNzd3F)
+[](https://discord.gg/M6he8ZPAAJ)
[](https://github.com/velopack/velopack/actions)
[](https://app.codecov.io/gh/velopack/velopack)
[](https://github.com/velopack/velopack/blob/develop/LICENSE)
-[](https://hits.seeyoufarm.com)
Velopack is an installation and auto-update framework for cross-platform applications. It's opinionated, extremely easy to use with zero config needed. With just one command you can be up and running with an installable application, and it's lightning fast for your users, too.
@@ -50,4 +49,4 @@ I've used a lot of installer frameworks and Velopack is by far the best. Everyth
[- RandomEngy (Discord)](https://discord.com/channels/767856501477343282/947444323765583913/1200897478036299861)
I'm extremely impressed with Velopack's performance in creating releases, as well as checking for and applying updates. It is significantly faster than other tools. The vpk CLI is intuitive and easy to implement, even with my complex build pipeline. Thanks to Velopack, I've been able to streamline my workflow and save valuable time. It's a fantastic tool that I highly recommend!
-[- khdc (Discord)](https://discord.com/channels/767856501477343282/947444323765583913/1216460920696344576)
\ No newline at end of file
+[- khdc (Discord)](https://discord.com/channels/767856501477343282/947444323765583913/1216460920696344576)
From bea4679abd5edeb0be9dd07bcd45bbdd942842df Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 2 May 2025 11:43:14 +0000
Subject: [PATCH 15/64] Update dependency electron to v36
---
samples/NodeJSElectron/package-lock.json | 8 ++++----
samples/NodeJSElectron/package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/samples/NodeJSElectron/package-lock.json b/samples/NodeJSElectron/package-lock.json
index d1c205a8..ba365226 100644
--- a/samples/NodeJSElectron/package-lock.json
+++ b/samples/NodeJSElectron/package-lock.json
@@ -18,7 +18,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "35.2.1",
+ "electron": "36.1.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
@@ -3297,9 +3297,9 @@
"license": "MIT"
},
"node_modules/electron": {
- "version": "35.2.1",
- "resolved": "https://registry.npmjs.org/electron/-/electron-35.2.1.tgz",
- "integrity": "sha512-LO4xXLpzkPPUVLvAbdHMlW7N9Z+Qqz+7QsmSWXluTIQMeJk+v7o36nUTZghyA2I1s//tlMvuaCtle6Qo2W0Ktg==",
+ "version": "36.1.0",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-36.1.0.tgz",
+ "integrity": "sha512-gnp3BnbKdGsVc7cm1qlEaZc8pJsR08mIs8H/yTo8gHEtFkGGJbDTVZOYNAfbQlL0aXh+ozv+CnyiNeDNkT1Upg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
diff --git a/samples/NodeJSElectron/package.json b/samples/NodeJSElectron/package.json
index f94577bc..77472b70 100644
--- a/samples/NodeJSElectron/package.json
+++ b/samples/NodeJSElectron/package.json
@@ -23,7 +23,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "35.2.1",
+ "electron": "36.1.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
From 9ef0c46d1faa3fd19b81ba8de7ef93b9a809b6fb Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 2 May 2025 13:39:49 +0000
Subject: [PATCH 16/64] Update sample dotnet packages to 11.3.0
---
samples/CSharpAvalonia/CSharpAvalonia.csproj | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/samples/CSharpAvalonia/CSharpAvalonia.csproj b/samples/CSharpAvalonia/CSharpAvalonia.csproj
index deba4c72..54072f03 100644
--- a/samples/CSharpAvalonia/CSharpAvalonia.csproj
+++ b/samples/CSharpAvalonia/CSharpAvalonia.csproj
@@ -10,12 +10,12 @@
-
-
-
-
+
+
+
+
-
+
From 6cb6cd04ad38efb9a675463c5967eeab72f402ac Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 7 May 2025 23:47:16 +0000
Subject: [PATCH 17/64] Update dotnet packages
---
src/vpk/Velopack.Deployment/Velopack.Deployment.csproj | 2 +-
src/vpk/Velopack.Packaging/Velopack.Packaging.csproj | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
index 1b77b103..7cd7bf90 100644
--- a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
+++ b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
index 54eb18ff..a2bf2af9 100644
--- a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
+++ b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
@@ -17,7 +17,7 @@
-
+
From 1c7a091244b1fc0f8f4a95ada13c61d250baf417 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 2 May 2025 06:12:11 +0000
Subject: [PATCH 18/64] Update rust crates
---
Cargo.lock | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index c985940e..d3be8510 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -354,9 +354,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-version = "0.4.40"
+version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
+checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -368,9 +368,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.36"
+version = "4.5.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
+checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
dependencies = [
"clap_builder",
"clap_derive",
@@ -378,9 +378,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.36"
+version = "4.5.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
+checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
dependencies = [
"anstream",
"anstyle",
@@ -634,7 +634,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -1477,13 +1477,12 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
"rand_chacha",
"rand_core",
- "zerocopy 0.8.20",
]
[[package]]
@@ -1596,7 +1595,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.4.15",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -1609,7 +1608,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.9.2",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -1746,9 +1745,9 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
[[package]]
name = "sha2"
-version = "0.10.8"
+version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures",
@@ -1902,7 +1901,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix 1.0.1",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
]
[[package]]
From 7596dc26acc4a90ec09a88b4ea7c3403e509e8c0 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 8 May 2025 03:52:58 +0000
Subject: [PATCH 19/64] Update dependency @types/node to v22.15.16
---
src/lib-nodejs/package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index 5506ce8b..8a5f51f0 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -1186,9 +1186,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.15.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz",
- "integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==",
+ "version": "22.15.16",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.16.tgz",
+ "integrity": "sha512-3pr+KjwpVujqWqOKT8mNR+rd09FqhBLwg+5L/4t0cNYBzm/yEiYGCxWttjaPBsLtAo+WFNoXzGJfolM1JuRXoA==",
"dev": true,
"license": "MIT",
"dependencies": {
From 340a15149c536d2840936e9f7419275425b71efb Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 8 May 2025 08:39:59 +0000
Subject: [PATCH 20/64] Update dependency AWSSDK.S3 to v4
---
src/vpk/Velopack.Deployment/Velopack.Deployment.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
index 7cd7bf90..979a0a8a 100644
--- a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
+++ b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
@@ -7,7 +7,7 @@
-
+
From 36cf0780b2dbb91e679e7a896d1e9b499d2c1ded Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 9 May 2025 09:28:29 +0000
Subject: [PATCH 21/64] Update dependency @types/node to v22.15.17
---
src/lib-nodejs/package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index 8a5f51f0..f0c6cfb5 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -1186,9 +1186,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.15.16",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.16.tgz",
- "integrity": "sha512-3pr+KjwpVujqWqOKT8mNR+rd09FqhBLwg+5L/4t0cNYBzm/yEiYGCxWttjaPBsLtAo+WFNoXzGJfolM1JuRXoA==",
+ "version": "22.15.17",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz",
+ "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==",
"dev": true,
"license": "MIT",
"dependencies": {
From 05a443fb849e0279bce2bfa9fbbb0379718fe1dc Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Fri, 9 May 2025 22:57:13 +0100
Subject: [PATCH 22/64] Restrict renovate to friday mornings
---
.github/renovate.json5 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/renovate.json5 b/.github/renovate.json5
index 2cf0eff3..f8e7a79e 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -5,7 +5,7 @@
":semanticCommitsDisabled"
],
"labels": ["renovate"],
- "schedule": ["on friday"],
+ "schedule": ["on friday before 11am"],
"timezone": "Europe/London",
"ignorePaths": [
"**/node_modules/**",
From 1af5c1cf3a80f21c8aa71223c103b5b4a7582356 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 9 May 2025 21:58:35 +0000
Subject: [PATCH 23/64] Update sample js packages
---
samples/NodeJSElectron/package-lock.json | 255 ++++++++++++-----------
samples/NodeJSElectron/package.json | 2 +-
2 files changed, 134 insertions(+), 123 deletions(-)
diff --git a/samples/NodeJSElectron/package-lock.json b/samples/NodeJSElectron/package-lock.json
index ba365226..c84e1fdd 100644
--- a/samples/NodeJSElectron/package-lock.json
+++ b/samples/NodeJSElectron/package-lock.json
@@ -18,7 +18,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "36.1.0",
+ "electron": "36.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
@@ -78,9 +78,9 @@
}
},
"node_modules/@electron-forge/cli": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.8.0.tgz",
- "integrity": "sha512-XZ+Hg7pxeE9pgrahqcpMlND+VH0l0UTZLyO5wkI+YfanNyBQksB2mw24XeEtCA6x8F2IaEYdIGgijmPF6qpjzA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.8.1.tgz",
+ "integrity": "sha512-QI3EShutfq9Y+2TWWrPjm4JZM3eSAKzoQvRZdVhAfVpUbyJ8K23VqJShg3kGKlPf9BXHAGvE+8LyH5s2yDr1qA==",
"dev": true,
"funding": [
{
@@ -94,9 +94,9 @@
],
"license": "MIT",
"dependencies": {
- "@electron-forge/core": "7.8.0",
- "@electron-forge/core-utils": "7.8.0",
- "@electron-forge/shared-types": "7.8.0",
+ "@electron-forge/core": "7.8.1",
+ "@electron-forge/core-utils": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1",
"@electron/get": "^3.0.0",
"chalk": "^4.0.0",
"commander": "^11.1.0",
@@ -116,9 +116,9 @@
}
},
"node_modules/@electron-forge/core": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-7.8.0.tgz",
- "integrity": "sha512-7byf660ECZND+irOhGxvpmRXjk1bMrsTWh5J2AZMEvaXI8tub9OrZY9VSbi5fcDt0lpHPKmgVk7NRf/ZjJ+beQ==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-7.8.1.tgz",
+ "integrity": "sha512-jkh0QPW5p0zmruu1E8+2XNufc4UMxy13WLJcm7hn9jbaXKLkMbKuEvhrN1tH/9uGp1mhr/t8sC4N67gP+gS87w==",
"dev": true,
"funding": [
{
@@ -132,17 +132,17 @@
],
"license": "MIT",
"dependencies": {
- "@electron-forge/core-utils": "7.8.0",
- "@electron-forge/maker-base": "7.8.0",
- "@electron-forge/plugin-base": "7.8.0",
- "@electron-forge/publisher-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0",
- "@electron-forge/template-base": "7.8.0",
- "@electron-forge/template-vite": "7.8.0",
- "@electron-forge/template-vite-typescript": "7.8.0",
- "@electron-forge/template-webpack": "7.8.0",
- "@electron-forge/template-webpack-typescript": "7.8.0",
- "@electron-forge/tracer": "7.8.0",
+ "@electron-forge/core-utils": "7.8.1",
+ "@electron-forge/maker-base": "7.8.1",
+ "@electron-forge/plugin-base": "7.8.1",
+ "@electron-forge/publisher-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1",
+ "@electron-forge/template-base": "7.8.1",
+ "@electron-forge/template-vite": "7.8.1",
+ "@electron-forge/template-vite-typescript": "7.8.1",
+ "@electron-forge/template-webpack": "7.8.1",
+ "@electron-forge/template-webpack-typescript": "7.8.1",
+ "@electron-forge/tracer": "7.8.1",
"@electron/get": "^3.0.0",
"@electron/packager": "^18.3.5",
"@electron/rebuild": "^3.7.0",
@@ -156,6 +156,7 @@
"global-dirs": "^3.0.0",
"got": "^11.8.5",
"interpret": "^3.1.1",
+ "jiti": "^2.4.2",
"listr2": "^7.0.2",
"lodash": "^4.17.20",
"log-symbols": "^4.0.0",
@@ -171,13 +172,13 @@
}
},
"node_modules/@electron-forge/core-utils": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-7.8.0.tgz",
- "integrity": "sha512-ZioRzqkXVOGuwkfvXN/FPZxcssJ9AkOZx6RvxomQn90F77G2KfEbw4ZwAxVTQ+jWNUzydTic5qavWle++Y5IeA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-7.8.1.tgz",
+ "integrity": "sha512-mRoPLDNZgmjyOURE/K0D3Op53XGFmFRgfIvFC7c9S/BqsRpovVblrqI4XxPRdNmH9dvhd8On9gGz+XIYAKD3aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0",
+ "@electron-forge/shared-types": "7.8.1",
"@electron/rebuild": "^3.7.0",
"@malept/cross-spawn-promise": "^2.0.0",
"chalk": "^4.0.0",
@@ -192,13 +193,13 @@
}
},
"node_modules/@electron-forge/maker-base": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-7.8.0.tgz",
- "integrity": "sha512-yGRvz70w+NnKO7PhzNFRgYM+x6kxYFgpbChJIQBs3WChd9bGjL+MZLrwYqmxOFLpWNwRAJ6PEi4E/8U5GgV6AQ==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-7.8.1.tgz",
+ "integrity": "sha512-GUZqschGuEBzSzE0bMeDip65IDds48DZXzldlRwQ+85SYVA6RMU2AwDDqx3YiYsvP2OuxKruuqIJZtOF5ps4FQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0",
+ "@electron-forge/shared-types": "7.8.1",
"fs-extra": "^10.0.0",
"which": "^2.0.2"
},
@@ -207,14 +208,14 @@
}
},
"node_modules/@electron-forge/maker-deb": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-7.8.0.tgz",
- "integrity": "sha512-9jjhLm/1IBIo0UuRdELgvBhUkNjK3tHNlUsrqeb8EJwWJZShbPwHYZJj+VbgjQfJFFzhHwBBDJViBXJ/4ePv+g==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-7.8.1.tgz",
+ "integrity": "sha512-tjjeesQtCP5Xht1X7gl4+K9bwoETPmQfBkOVAY/FZIxPj40uQh/hOUtLX2tYENNGNVZ1ryDYRs8TuPi+I41Vfw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/maker-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0"
+ "@electron-forge/maker-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1"
},
"engines": {
"node": ">= 16.4.0"
@@ -224,14 +225,14 @@
}
},
"node_modules/@electron-forge/maker-rpm": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/maker-rpm/-/maker-rpm-7.8.0.tgz",
- "integrity": "sha512-oTH951NE39LOX2wYMg+C06vBZDWUP/0dsK01PlXEl5e5YfQM5Cifsk3E7BzE6BpZdWRJL3k/ETqpyYeIGNb1jw==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/maker-rpm/-/maker-rpm-7.8.1.tgz",
+ "integrity": "sha512-TF6wylft3BHkw9zdHcxmjEPBZYgTIc0jE31skFnMEQ/aExbNRiNaCZvsXy+7ptTWZxhxUKRc9KHhLFRMCmOK8g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/maker-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0"
+ "@electron-forge/maker-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1"
},
"engines": {
"node": ">= 16.4.0"
@@ -241,14 +242,14 @@
}
},
"node_modules/@electron-forge/maker-zip": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-7.8.0.tgz",
- "integrity": "sha512-7MLD7GkZdlGecC9GvgBu0sWYt48p3smYvr+YCwlpdH1CTeLmWhvCqeH33a2AB0XI5CY8U8jnkG2jgdTkzr/EQw==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-7.8.1.tgz",
+ "integrity": "sha512-unIxEoV1lnK4BLVqCy3L2y897fTyg8nKY1WT4rrpv0MUKnQG4qmigDfST5zZNNHHaulEn/ElAic2GEiP7d6bhQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/maker-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0",
+ "@electron-forge/maker-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1",
"cross-zip": "^4.0.0",
"fs-extra": "^10.0.0",
"got": "^11.8.5"
@@ -258,41 +259,41 @@
}
},
"node_modules/@electron-forge/plugin-auto-unpack-natives": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.8.0.tgz",
- "integrity": "sha512-JGal5ltZmbTQ5rNq67OgGC4MJ2zjjFW0fqykHy8X9J8cgaH7SRdKkT4yYZ8jH01IAF1J57FD2zIob1MvcBqjcg==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.8.1.tgz",
+ "integrity": "sha512-4URAgWX9qqqKe6Bfad0VmpFRrwINYMODfKGd2nFQrfHxmBtdpXnsWlLwVGE/wGssIQaTMI5bWQ6F2RNeXTgnhA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/plugin-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0"
+ "@electron-forge/plugin-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1"
},
"engines": {
"node": ">= 16.4.0"
}
},
"node_modules/@electron-forge/plugin-base": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.8.0.tgz",
- "integrity": "sha512-rDeeChRWIp5rQVo3Uc1q0ncUvA+kWWURW7tMuQjPvy2qVSgX+jIf5krk+T1Dp06+D4YZzEIrkibRaamAaIcR1w==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.8.1.tgz",
+ "integrity": "sha512-iCZC2d7CbsZ9l6j5d+KPIiyQx0U1QBfWAbKnnQhWCSizjcrZ7A9V4sMFZeTO6+PVm48b/r9GFPm+slpgZtYQLg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0"
+ "@electron-forge/shared-types": "7.8.1"
},
"engines": {
"node": ">= 16.4.0"
}
},
"node_modules/@electron-forge/plugin-fuses": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/plugin-fuses/-/plugin-fuses-7.8.0.tgz",
- "integrity": "sha512-ZxFtol3aHNY+oYrZWa7EDBLl4uk/+NlOCJmqC7C32R/3S/Kn2ebVRxpLwrFM12KtHeD+Z3gmZNBhwOe0TECgOA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/plugin-fuses/-/plugin-fuses-7.8.1.tgz",
+ "integrity": "sha512-dYTwvbV1HcDOIQ0wTybpdtPq6YoBYXIWBTb7DJuvFu/c/thj1eoEdnbwr8mT9hEivjlu5p4ls46n16P5EtZ0oA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/plugin-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0"
+ "@electron-forge/plugin-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1"
},
"engines": {
"node": ">= 16.4.0"
@@ -302,16 +303,16 @@
}
},
"node_modules/@electron-forge/plugin-webpack": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/plugin-webpack/-/plugin-webpack-7.8.0.tgz",
- "integrity": "sha512-9X/+OLoGgzCjqdDAT12O1UQeS+P0RjoEdD4ms53yiWUaKAwrSI4rJeb4gJBrLuYxUH5jcLD7mzQj+yDswZfGNQ==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/plugin-webpack/-/plugin-webpack-7.8.1.tgz",
+ "integrity": "sha512-4SqQyX7abx6wcMSB8JwsM6gm72r3/8b//JcYZxWihYaqoz9ZMWQqci47FFSpncRlYZjUi7mbRpC2dSAjuQks2A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/core-utils": "7.8.0",
- "@electron-forge/plugin-base": "7.8.0",
- "@electron-forge/shared-types": "7.8.0",
- "@electron-forge/web-multi-logger": "7.8.0",
+ "@electron-forge/core-utils": "7.8.1",
+ "@electron-forge/plugin-base": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1",
+ "@electron-forge/web-multi-logger": "7.8.1",
"chalk": "^4.0.0",
"debug": "^4.3.1",
"fast-glob": "^3.2.7",
@@ -327,26 +328,26 @@
}
},
"node_modules/@electron-forge/publisher-base": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-7.8.0.tgz",
- "integrity": "sha512-wrZyptJ0Uqvlh2wYzDZfIu2HgCQ+kdGiBlcucmLY4W+GUqf043O8cbYso3D9NXQxOow55QC/1saCQkgLphprPA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-7.8.1.tgz",
+ "integrity": "sha512-z2C+C4pcFxyCXIFwXGDcxhU8qtVUPZa3sPL6tH5RuMxJi77768chLw2quDWk2/dfupcSELXcOMYCs7aLysCzeQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0"
+ "@electron-forge/shared-types": "7.8.1"
},
"engines": {
"node": ">= 16.4.0"
}
},
"node_modules/@electron-forge/shared-types": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-7.8.0.tgz",
- "integrity": "sha512-Ul+7HPvAZiAirqpZm0vc9YvlkAE+2bcrI10p3t50mEtuxn5VO/mB72NXiEKfWzHm8F31JySIe9bUV6s1MHQcCw==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-7.8.1.tgz",
+ "integrity": "sha512-guLyGjIISKQQRWHX+ugmcjIOjn2q/BEzCo3ioJXFowxiFwmZw/oCZ2KlPig/t6dMqgUrHTH5W/F0WKu0EY4M+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/tracer": "7.8.0",
+ "@electron-forge/tracer": "7.8.1",
"@electron/packager": "^18.3.5",
"@electron/rebuild": "^3.7.0",
"listr2": "^7.0.2"
@@ -356,14 +357,14 @@
}
},
"node_modules/@electron-forge/template-base": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-7.8.0.tgz",
- "integrity": "sha512-hc8NwoDqEEmZFH/p0p3MK/7xygMmI+cm8Gavoj2Mr2xS7VUUu4r3b5PwIGKvkLfPG34uwsiVwtid2t1rWGF4UA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-7.8.1.tgz",
+ "integrity": "sha512-k8jEUr0zWFWb16ZGho+Es2OFeKkcbTgbC6mcH4eNyF/sumh/4XZMcwRtX1i7EiZAYiL9sVxyI6KVwGu254g+0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/core-utils": "7.8.0",
- "@electron-forge/shared-types": "7.8.0",
+ "@electron-forge/core-utils": "7.8.1",
+ "@electron-forge/shared-types": "7.8.1",
"@malept/cross-spawn-promise": "^2.0.0",
"debug": "^4.3.1",
"fs-extra": "^10.0.0",
@@ -374,14 +375,14 @@
}
},
"node_modules/@electron-forge/template-vite": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-7.8.0.tgz",
- "integrity": "sha512-bf/jd8WzD0gU7Jet+WSi0Lm0SQmseb08WY27ZfJYEs2EVNMiwDfPicgQnOaqP++2yTrXhj1OY/rolZCP9CUyVw==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-7.8.1.tgz",
+ "integrity": "sha512-qzSlJaBYYqQAbBdLk4DqAE3HCNz4yXbpkb+VC74ddL4JGwPdPU57DjCthr6YetKJ2FsOVy9ipovA8HX5UbXpAg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0",
- "@electron-forge/template-base": "7.8.0",
+ "@electron-forge/shared-types": "7.8.1",
+ "@electron-forge/template-base": "7.8.1",
"fs-extra": "^10.0.0"
},
"engines": {
@@ -389,14 +390,14 @@
}
},
"node_modules/@electron-forge/template-vite-typescript": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.8.0.tgz",
- "integrity": "sha512-kW3CaVxKHUYuVfY+rT3iepeZ69frBRGh3YZOngLY2buCvGIqNEx+VCgrFBRDDbOKGmwQtwO1E9wp2rtC8q6Ztg==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.8.1.tgz",
+ "integrity": "sha512-CccQhwUjZcc6svzuOi3BtbDal591DzyX2J5GPa6mwVutDP8EMtqJL1VyOHdcWO/7XjI6GNAD0fiXySOJiUAECA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0",
- "@electron-forge/template-base": "7.8.0",
+ "@electron-forge/shared-types": "7.8.1",
+ "@electron-forge/template-base": "7.8.1",
"fs-extra": "^10.0.0"
},
"engines": {
@@ -404,14 +405,14 @@
}
},
"node_modules/@electron-forge/template-webpack": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-7.8.0.tgz",
- "integrity": "sha512-AdLGC6NVgrd7Q0SaaeiwJKmSBjN6C2EHxZgLMy1yxNSpazU9m3DtYQilDjXqmCWfxkeNzdke0NaeDvLgdJSw5A==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-7.8.1.tgz",
+ "integrity": "sha512-DA77o9kTCHrq+W211pyNP49DyAt0d1mzMp2gisyNz7a+iKvlv2DsMAeRieLoCQ44akb/z8ZsL0YLteSjKLy4AA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0",
- "@electron-forge/template-base": "7.8.0",
+ "@electron-forge/shared-types": "7.8.1",
+ "@electron-forge/template-base": "7.8.1",
"fs-extra": "^10.0.0"
},
"engines": {
@@ -419,14 +420,14 @@
}
},
"node_modules/@electron-forge/template-webpack-typescript": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.8.0.tgz",
- "integrity": "sha512-Pl8l+gv3HzqCfFIMLxlEsoAkNd0VEWeZZ675SYyqs0/kBQUifn0bKNhVE4gUZwKGgQCcG1Gvb23KdVGD3H3XmA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.8.1.tgz",
+ "integrity": "sha512-h922E+6zWwym1RT6WKD79BLTc4H8YxEMJ7wPWkBX59kw/exsTB/KFdiJq6r82ON5jSJ+Q8sDGqSmDWdyCfo+Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@electron-forge/shared-types": "7.8.0",
- "@electron-forge/template-base": "7.8.0",
+ "@electron-forge/shared-types": "7.8.1",
+ "@electron-forge/template-base": "7.8.1",
"fs-extra": "^10.0.0"
},
"engines": {
@@ -434,9 +435,9 @@
}
},
"node_modules/@electron-forge/tracer": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/tracer/-/tracer-7.8.0.tgz",
- "integrity": "sha512-t4fIATZEX6/7PJNfyh6tLzKEsNMpO01Nz/rgHWBxeRvjCw5UNul9OOxoM7b43vfFAO9Jv++34oI3VJ09LeVQ2Q==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/tracer/-/tracer-7.8.1.tgz",
+ "integrity": "sha512-r2i7aHVp2fylGQSPDw3aTcdNfVX9cpL1iL2MKHrCRNwgrfR+nryGYg434T745GGm1rNQIv5Egdkh5G9xf00oWA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -447,9 +448,9 @@
}
},
"node_modules/@electron-forge/web-multi-logger": {
- "version": "7.8.0",
- "resolved": "https://registry.npmjs.org/@electron-forge/web-multi-logger/-/web-multi-logger-7.8.0.tgz",
- "integrity": "sha512-2nUP7O9auXDsoa185AsZPlIbpargj1lNFweNH1Lch1MCwLlJOI9ZJHiCTAB4qviS4usRs00WeebWg/uN/zOWvA==",
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/@electron-forge/web-multi-logger/-/web-multi-logger-7.8.1.tgz",
+ "integrity": "sha512-Z8oU39sbrVDvyk0yILBqL0CFIysVlxkM5m4RWyeo+GLoc/t4LYAhGLSquFTOD1t20nzqZzgzG8M56zIgYuyX1w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -764,9 +765,9 @@
}
},
"node_modules/@electron/rebuild": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.1.tgz",
- "integrity": "sha512-sKGD+xav4Gh25+LcLY0rjIwcCFTw+f/HU1pB48UVbwxXXRGaXEqIH0AaYKN46dgd/7+6kuiDXzoyAEvx1zCsdw==",
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.2.tgz",
+ "integrity": "sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -793,9 +794,9 @@
}
},
"node_modules/@electron/universal": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.2.tgz",
- "integrity": "sha512-mqY1szx5/d5YLvfCDWWoJdkSIjIz+NdWN4pN0r78lYiE7De+slLpuF3lVxIT+hlJnwk5sH2wFRMl6/oUgUVO3A==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz",
+ "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -853,9 +854,9 @@
}
},
"node_modules/@electron/windows-sign": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.1.tgz",
- "integrity": "sha512-YfASnrhJ+ve6Q43ZiDwmpBgYgi2u0bYjeAVi2tDfN7YWAKO8X9EEOuPGtqbJpPLM6TfAHimghICjWe2eaJ8BAg==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz",
+ "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -3137,9 +3138,9 @@
}
},
"node_modules/detect-libc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
- "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
+ "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -3297,9 +3298,9 @@
"license": "MIT"
},
"node_modules/electron": {
- "version": "36.1.0",
- "resolved": "https://registry.npmjs.org/electron/-/electron-36.1.0.tgz",
- "integrity": "sha512-gnp3BnbKdGsVc7cm1qlEaZc8pJsR08mIs8H/yTo8gHEtFkGGJbDTVZOYNAfbQlL0aXh+ozv+CnyiNeDNkT1Upg==",
+ "version": "36.2.0",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-36.2.0.tgz",
+ "integrity": "sha512-5yldoRjBKxPQfI0QMX+qq750o3Nl8N1SZnJqOPMq0gZ6rIJ+7y4ZLp808GrFwjfTm05TYgq3GSD8FGuKQZqwEw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -5732,6 +5733,16 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
+ "node_modules/jiti": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
+ "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -6465,9 +6476,9 @@
}
},
"node_modules/node-abi": {
- "version": "3.74.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
- "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
+ "version": "3.75.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
+ "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
"dev": true,
"license": "MIT",
"dependencies": {
diff --git a/samples/NodeJSElectron/package.json b/samples/NodeJSElectron/package.json
index 77472b70..122cd94a 100644
--- a/samples/NodeJSElectron/package.json
+++ b/samples/NodeJSElectron/package.json
@@ -23,7 +23,7 @@
"@electron/fuses": "^1.8.0",
"@vercel/webpack-asset-relocator-loader": "=1.7.3",
"css-loader": "^7.0.0",
- "electron": "36.1.0",
+ "electron": "36.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0",
"node-loader": "^2.0.0",
"style-loader": "^4.0.0",
From c1f33c19a029e022272453801ba81d4bc3e4a693 Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 08:59:46 +0100
Subject: [PATCH 24/64] Fix Squirrel CLI migrations by adding --updateSelf
---
src/bins/src/update.rs | 50 +++++++++++
.../WindowsPackTests.cs | 86 +++++++++++++++++--
2 files changed, 131 insertions(+), 5 deletions(-)
diff --git a/src/bins/src/update.rs b/src/bins/src/update.rs
index 414131e8..90706722 100644
--- a/src/bins/src/update.rs
+++ b/src/bins/src/update.rs
@@ -56,6 +56,13 @@ fn root_command() -> Command {
.about("Remove all app shortcuts, files, and registry entries.")
.long_flag_alias("uninstall")
);
+
+ #[cfg(target_os = "windows")]
+ let cmd = cmd.subcommand(Command::new("update-self")
+ .about("Copy the currently executing Update.exe into the default location.")
+ .long_flag_alias("updateSelf")
+ .hide(true)
+ );
cmd
}
@@ -155,6 +162,8 @@ fn main() -> Result<()> {
let result = match subcommand {
#[cfg(target_os = "windows")]
"uninstall" => uninstall(subcommand_matches).map_err(|e| anyhow!("Uninstall error: {}", e)),
+ #[cfg(target_os = "windows")]
+ "update-self" => update_self(subcommand_matches).map_err(|e| anyhow!("Update-self error: {}", e)),
"start" => start(subcommand_matches).map_err(|e| anyhow!("Start error: {}", e)),
"apply" => apply(subcommand_matches).map_err(|e| anyhow!("Apply error: {}", e)),
"patch" => patch(subcommand_matches).map_err(|e| anyhow!("Patch error: {}", e)),
@@ -243,6 +252,47 @@ fn uninstall(_matches: &ArgMatches) -> Result<()> {
commands::uninstall(&locator, true)
}
+#[cfg(target_os = "windows")]
+fn update_self(_matches: &ArgMatches) -> Result<()> {
+ info!("Command: Update Self");
+ let my_path = env::current_exe()?;
+ const RETRY_DELAY: i32 = 500;
+ const RETRY_COUNT: i32 = 20;
+ match auto_locate_app_manifest(LocationContext::IAmUpdateExe) {
+ Ok(locator) => {
+ let target_update_path = locator.get_update_path();
+ if same_file::is_same_file(&target_update_path, &my_path)? {
+ bail!("Update.exe is already in the default location. No need to update.");
+ } else {
+ info!("Copying Update.exe to the default location: {:?}", target_update_path);
+ shared::retry_io_ex(|| std::fs::copy(&my_path, &target_update_path), RETRY_DELAY, RETRY_COUNT)?;
+ info!("Update.exe copied successfully.");
+ }
+ }
+ Err(e) => {
+ warn!("Failed to initialise locator: {}", e);
+ // search for an Update.exe in parent directories (at least 2 levels up)
+ let mut current_dir = env::current_dir()?;
+ let mut found = false;
+ for _ in 0..2 {
+ current_dir.pop();
+ let target_update_path = current_dir.join("Update.exe");
+ if target_update_path.exists() {
+ info!("Found Update.exe in parent directory: {:?}", target_update_path);
+ shared::retry_io_ex(|| std::fs::copy(&my_path, &target_update_path), RETRY_DELAY, RETRY_COUNT)?;
+ info!("Update.exe copied successfully.");
+ found = true;
+ break;
+ }
+ }
+ if !found {
+ bail!("Failed to locate Update.exe in parent directories, so it could not be updated.");
+ }
+ }
+ }
+ Ok(())
+}
+
#[cfg(target_os = "windows")]
#[test]
fn test_cli_parse_handles_equals_spaces() {
diff --git a/test/Velopack.Packaging.Tests/WindowsPackTests.cs b/test/Velopack.Packaging.Tests/WindowsPackTests.cs
index 759aa00e..ad5500c5 100644
--- a/test/Velopack.Packaging.Tests/WindowsPackTests.cs
+++ b/test/Velopack.Packaging.Tests/WindowsPackTests.cs
@@ -253,7 +253,7 @@ public class WindowsPackTests
Assert.False(File.Exists(appPath));
using var key2 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default)
- .OpenSubKey(uninstallRegSubKey + "\\" + id, RegistryKeyPermissionCheck.ReadSubTree);
+ .OpenSubKey(uninstallRegSubKey + "\\" + id, RegistryKeyPermissionCheck.ReadSubTree);
Assert.Null(key2);
}
@@ -508,12 +508,74 @@ public class WindowsPackTests
logger.Info("TEST: uninstalled / complete");
}
+ [SkippableTheory]
+ [InlineData("LegacyTestApp-ClowdV2-Setup.exe", "app-1.0.0")]
+ [InlineData("LegacyTestApp-SquirrelWinV2-Setup.exe", "app-1.0.0")]
+ public void LegacyAppCanMigrateUsingCli(string fixture, string origDirName)
+ {
+ Skip.IfNot(VelopackRuntimeInfo.IsWindows);
+ using var logger = _output.BuildLoggerFor();
+
+ var rootDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "LegacyTestApp");
+ if (Directory.Exists(rootDir)) {
+ IoUtil.Retry(() => IoUtil.DeleteFileOrDirectoryHard(rootDir), 10, 1000);
+ }
+
+ var setup = PathHelper.GetFixture(fixture);
+ var p = Process.Start(setup);
+ p!.WaitForExit();
+
+ var currentDir = Path.Combine(rootDir, origDirName);
+ var appExe = Path.Combine(currentDir, "LegacyTestApp.exe");
+ var stubExe = Path.Combine(rootDir, "LegacyTestApp.exe");
+ var updateExe = Path.Combine(rootDir, "Update.exe");
+
+ var assertAppExe = appExe;
+ IoUtil.Retry(
+ () => {
+ Assert.True(File.Exists(assertAppExe));
+ Assert.True(File.Exists(updateExe));
+ },
+ retries: 10,
+ retryDelay: 1000);
+
+ using var _1 = TempUtil.GetTempDirectory(out var releaseDir);
+ PackTestApp("LegacyTestApp", "2.0.0", "hello!", releaseDir, logger, assemblyNameOverride: "LegacyTestApp");
+
+ RunNoCoverage(updateExe, ["--update", releaseDir], currentDir, logger, exitCode: 0);
+ Thread.Sleep(2000); // update.exe does a self update after
+
+ RunNoCoverage(stubExe, [], currentDir, logger, exitCode: 0);
+ Thread.Sleep(8000); // update.exe will do migration here
+
+ string logContents = ReadFileWithRetry(Path.Combine(rootDir, "Velopack.log"), logger);
+ logger.Info("Velopack.log:" + Environment.NewLine + logContents);
+
+ if (origDirName != "current") {
+ Assert.False(Directory.Exists(currentDir));
+ currentDir = Path.Combine(rootDir, "current");
+ }
+
+ Assert.True(Directory.Exists(currentDir));
+ appExe = Path.Combine(currentDir, "LegacyTestApp.exe");
+ Assert.True(File.Exists(appExe));
+
+ Assert.False(Directory.EnumerateDirectories(rootDir, "app-*").Any());
+ Assert.False(Directory.Exists(Path.Combine(rootDir, "staging")));
+
+ // this is the file written by TestApp when it's detected the squirrel restart. if this is here, everything went smoothly.
+ Assert.True(File.Exists(Path.Combine(rootDir, "restarted")));
+
+ var chk3version = RunNoCoverage(appExe, ["version"], currentDir, logger);
+ Assert.EndsWith(Environment.NewLine + "2.0.0", chk3version);
+ }
+
[SkippableTheory]
[InlineData("LegacyTestApp-ClowdV2-Setup.exe", "app-1.0.0")]
[InlineData("LegacyTestApp-ClowdV3-Setup.exe", "current")]
[InlineData("LegacyTestApp-SquirrelWinV2-Setup.exe", "app-1.0.0")]
[InlineData("LegacyTestApp-Velopack0084-Setup.exe", "current")]
- public void LegacyAppCanSuccessfullyMigrate(string fixture, string origDirName)
+ public void LegacyAppCanMigrate(string fixture, string origDirName)
{
Skip.IfNot(VelopackRuntimeInfo.IsWindows);
using var logger = _output.BuildLoggerFor();
@@ -807,7 +869,8 @@ public class WindowsPackTests
return RunImpl(psi, logger, exitCode);
}
- private static void PackTestApp(string id, string version, string testString, string releaseDir, ILogger logger, bool addNewFile = false)
+ private static void PackTestApp(string id, string version, string testString, string releaseDir, ILogger logger,
+ bool addNewFile = false, string assemblyNameOverride = null)
{
var projDir = PathHelper.GetTestRootPath("TestApp");
var testStringFile = Path.Combine(projDir, "Const.cs");
@@ -815,7 +878,10 @@ public class WindowsPackTests
try {
File.WriteAllText(testStringFile, $"class Const {{ public const string TEST_STRING = \"{testString}\"; }}");
- var args = new string[] { "publish", "--no-self-contained", "-c", "Release", "-r", "win-x64", "-o", "publish" };
+ var args = new string[] {
+ "publish", "--no-self-contained", "-c", "Release", "-r", "win-x64", "-o", "publish",
+ $"-p:PublishSingleFile=true", "--tl:off"
+ };
var psi = new ProcessStartInfo("dotnet");
psi.WorkingDirectory = projDir;
@@ -839,10 +905,20 @@ public class WindowsPackTests
}
}
+ var publishDir = Path.Combine(projDir, "publish");
+
+ if (assemblyNameOverride != null) {
+ var targetExe = Path.Combine(publishDir, assemblyNameOverride + ".exe");
+ if (File.Exists(targetExe)) {
+ File.Delete(targetExe);
+ }
+ File.Move(Path.Combine(publishDir, "TestApp.exe"), targetExe);
+ }
+
//RunNoCoverage("dotnet", args, projDir, logger);
var options = new WindowsPackOptions {
- EntryExecutableName = "TestApp.exe",
+ EntryExecutableName = assemblyNameOverride + ".exe",
ReleaseDir = new DirectoryInfo(releaseDir),
PackId = id,
PackVersion = version,
From 03d9ad702f15b72bd4faeb5ae266a57bebf4becd Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 09:09:16 +0100
Subject: [PATCH 25/64] Try to fix flaky build
---
src/vpk/Velopack.Vpk/Velopack.Vpk.csproj | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
index d67aa8fe..ed730fcb 100644
--- a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
+++ b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
@@ -5,6 +5,7 @@
net6.0;net8.0;net9.0
vpk
latest
+ false
$(NoWarn);CA2007;CS8002
From 49fd9577d43ced8b642f2219d8e0fae626e380b8 Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 09:25:16 +0100
Subject: [PATCH 26/64] Fix failing tests
---
test/Velopack.Packaging.Tests/WindowsPackTests.cs | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/test/Velopack.Packaging.Tests/WindowsPackTests.cs b/test/Velopack.Packaging.Tests/WindowsPackTests.cs
index ad5500c5..b7cb2818 100644
--- a/test/Velopack.Packaging.Tests/WindowsPackTests.cs
+++ b/test/Velopack.Packaging.Tests/WindowsPackTests.cs
@@ -878,11 +878,14 @@ public class WindowsPackTests
try {
File.WriteAllText(testStringFile, $"class Const {{ public const string TEST_STRING = \"{testString}\"; }}");
- var args = new string[] {
- "publish", "--no-self-contained", "-c", "Release", "-r", "win-x64", "-o", "publish",
- $"-p:PublishSingleFile=true", "--tl:off"
+ var args = new List {
+ "publish", "--no-self-contained", "-c", "Release", "-r", "win-x64", "-o", "publish", "--tl:off"
};
+ if (assemblyNameOverride != null) {
+ args.Add("-p:PublishSingleFile=true");
+ }
+
var psi = new ProcessStartInfo("dotnet");
psi.WorkingDirectory = projDir;
psi.AppendArgumentListSafe(args, out var debug);
@@ -918,7 +921,7 @@ public class WindowsPackTests
//RunNoCoverage("dotnet", args, projDir, logger);
var options = new WindowsPackOptions {
- EntryExecutableName = assemblyNameOverride + ".exe",
+ EntryExecutableName = (assemblyNameOverride ?? "TestApp") + ".exe",
ReleaseDir = new DirectoryInfo(releaseDir),
PackId = id,
PackVersion = version,
From a4e3fc4dd4394cbfafc08bdd028afb1163c2ed7e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 06:14:15 +0000
Subject: [PATCH 27/64] Update rust crates
---
Cargo.lock | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index d3be8510..16f6eb3f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -254,9 +254,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.9.0"
+version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "block-buffer"
@@ -368,9 +368,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.37"
+version = "4.5.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
+checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000"
dependencies = [
"clap_builder",
"clap_derive",
@@ -378,9 +378,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.37"
+version = "4.5.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
+checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120"
dependencies = [
"anstream",
"anstyle",
@@ -1128,9 +1128,9 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libloading"
-version = "0.8.6"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
+checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
dependencies = [
"cfg-if 1.0.0",
"windows-targets 0.48.5",
@@ -1142,7 +1142,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
- "bitflags 2.9.0",
+ "bitflags 2.9.1",
"libc",
]
@@ -1336,9 +1336,9 @@ checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "os_info"
-version = "3.10.0"
+version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5"
+checksum = "41fc863e2ca13dc2d5c34fb22ea4a588248ac14db929616ba65c45f21744b1e9"
dependencies = [
"log",
"serde",
@@ -1591,7 +1591,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
- "bitflags 2.9.0",
+ "bitflags 2.9.1",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -1604,7 +1604,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657"
dependencies = [
- "bitflags 2.9.0",
+ "bitflags 2.9.1",
"errno",
"libc",
"linux-raw-sys 0.9.2",
@@ -1893,9 +1893,9 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.19.1"
+version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
+checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
dependencies = [
"fastrand",
"getrandom 0.3.1",
@@ -2205,7 +2205,7 @@ name = "velopack"
version = "0.0.0-local"
dependencies = [
"async-std",
- "bitflags 2.9.0",
+ "bitflags 2.9.1",
"derivative",
"file-rotate",
"glob",
@@ -2240,7 +2240,7 @@ name = "velopack_bins"
version = "0.0.0-local"
dependencies = [
"anyhow",
- "bitflags 2.9.0",
+ "bitflags 2.9.1",
"chrono",
"clap",
"core-foundation",
@@ -2797,7 +2797,7 @@ version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
- "bitflags 2.9.0",
+ "bitflags 2.9.1",
]
[[package]]
From c618758f66e67324d089ba4b62c3bab5224f679b Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 03:46:31 +0000
Subject: [PATCH 28/64] Update dotnet packages
---
src/lib-csharp/Velopack.csproj | 2 +-
src/vpk/Velopack.Build/Velopack.Build.csproj | 2 +-
.../Velopack.Deployment/Velopack.Deployment.csproj | 2 +-
src/vpk/Velopack.Flow/Velopack.Flow.csproj | 8 ++++----
src/vpk/Velopack.Packaging/Velopack.Packaging.csproj | 12 ++++++------
src/vpk/Velopack.Vpk/Velopack.Vpk.csproj | 10 +++++-----
.../Velopack.Packaging.Tests.csproj | 6 +++---
test/Velopack.Tests/Velopack.Tests.csproj | 2 +-
8 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/src/lib-csharp/Velopack.csproj b/src/lib-csharp/Velopack.csproj
index ba86c8f6..07a80bbf 100644
--- a/src/lib-csharp/Velopack.csproj
+++ b/src/lib-csharp/Velopack.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/src/vpk/Velopack.Build/Velopack.Build.csproj b/src/vpk/Velopack.Build/Velopack.Build.csproj
index 81545ae0..02afa6e9 100644
--- a/src/vpk/Velopack.Build/Velopack.Build.csproj
+++ b/src/vpk/Velopack.Build/Velopack.Build.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
index 979a0a8a..39150bac 100644
--- a/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
+++ b/src/vpk/Velopack.Deployment/Velopack.Deployment.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/src/vpk/Velopack.Flow/Velopack.Flow.csproj b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
index b6ca6e14..41beadb2 100644
--- a/src/vpk/Velopack.Flow/Velopack.Flow.csproj
+++ b/src/vpk/Velopack.Flow/Velopack.Flow.csproj
@@ -9,10 +9,10 @@
-
-
-
-
+
+
+
+
diff --git a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
index a2bf2af9..9e94b5c3 100644
--- a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
+++ b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
@@ -16,14 +16,14 @@
-
+
-
-
-
-
+
+
+
+
-
+
diff --git a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
index ed730fcb..edd4cd93 100644
--- a/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
+++ b/src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
@@ -18,18 +18,18 @@
-
-
+
+
-
+
-
-
+
+
diff --git a/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj b/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj
index 8faf8eaf..11f61a3a 100644
--- a/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj
+++ b/test/Velopack.Packaging.Tests/Velopack.Packaging.Tests.csproj
@@ -9,10 +9,10 @@
-
+
-
-
+
+
diff --git a/test/Velopack.Tests/Velopack.Tests.csproj b/test/Velopack.Tests/Velopack.Tests.csproj
index d3eff951..71ca90ae 100644
--- a/test/Velopack.Tests/Velopack.Tests.csproj
+++ b/test/Velopack.Tests/Velopack.Tests.csproj
@@ -19,7 +19,7 @@
-
+
From cccefe774ae1b3cb80c4f3e98aef8e52acc79c94 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 06:13:20 +0000
Subject: [PATCH 29/64] Update npm packages
---
src/lib-nodejs/package-lock.json | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index f0c6cfb5..ea440072 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -1186,9 +1186,9 @@
}
},
"node_modules/@types/node": {
- "version": "22.15.17",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz",
- "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==",
+ "version": "22.15.18",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz",
+ "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4161,9 +4161,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.3.2",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz",
- "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==",
+ "version": "29.3.3",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.3.tgz",
+ "integrity": "sha512-y6jLm19SL4GroiBmHwFK4dSHUfDNmOrJbRfp6QmDIlI9p5tT5Q8ItccB4pTIslCIqOZuQnBwpTR0bQ5eUMYwkw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4174,8 +4174,8 @@
"json5": "^2.2.3",
"lodash.memoize": "^4.1.2",
"make-error": "^1.3.6",
- "semver": "^7.7.1",
- "type-fest": "^4.39.1",
+ "semver": "^7.7.2",
+ "type-fest": "^4.41.0",
"yargs-parser": "^21.1.1"
},
"bin": {
@@ -4211,9 +4211,9 @@
}
},
"node_modules/ts-jest/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -4224,9 +4224,9 @@
}
},
"node_modules/ts-jest/node_modules/type-fest": {
- "version": "4.39.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz",
- "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==",
+ "version": "4.41.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
+ "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
From 4cdbb49fad34b5fca0bda9c668e13c22a61bc2f6 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 16:20:15 +0000
Subject: [PATCH 30/64] Update Node.js to >=18.0.0 <=22.15.1
---
src/lib-nodejs/package-lock.json | 2 +-
src/lib-nodejs/package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/lib-nodejs/package-lock.json b/src/lib-nodejs/package-lock.json
index ea440072..802344b2 100644
--- a/src/lib-nodejs/package-lock.json
+++ b/src/lib-nodejs/package-lock.json
@@ -24,7 +24,7 @@
"typescript": "^5.3.3"
},
"engines": {
- "node": ">=18.0.0 <=22.15.0"
+ "node": ">=18.0.0 <=22.15.1"
}
},
"node_modules/@ampproject/remapping": {
diff --git a/src/lib-nodejs/package.json b/src/lib-nodejs/package.json
index ae66f947..b3bb223a 100644
--- a/src/lib-nodejs/package.json
+++ b/src/lib-nodejs/package.json
@@ -36,7 +36,7 @@
"author": "Velopack Ltd, Caelan Sayler",
"license": "MIT",
"engines": {
- "node": ">=18.0.0 <=22.15.0"
+ "node": ">=18.0.0 <=22.15.1"
},
"files": [
"lib/**/*.ts",
From a1a740b10af43601c0d947a9b9e82344d2097299 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 23 May 2025 06:08:15 +0000
Subject: [PATCH 31/64] Update Rust crate uuid to v1.17.0
---
samples/RustIced/Cargo.lock | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/samples/RustIced/Cargo.lock b/samples/RustIced/Cargo.lock
index ba098f3c..804429c0 100644
--- a/samples/RustIced/Cargo.lock
+++ b/samples/RustIced/Cargo.lock
@@ -2005,7 +2005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
- "windows-targets 0.52.6",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -3831,21 +3831,23 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
+checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
dependencies = [
"getrandom 0.3.1",
+ "js-sys",
"rand 0.9.0",
"serde",
"uuid-macro-internal",
+ "wasm-bindgen",
]
[[package]]
name = "uuid-macro-internal"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72dcd78c4f979627a754f5522cea6e6a25e55139056535fe6e69c506cd64a862"
+checksum = "26b682e8c381995ea03130e381928e0e005b7c9eb483c6c8682f50e07b33c2b7"
dependencies = [
"proc-macro2",
"quote",
From d71acd5a20fb4c695375000776f9feddd08a839a Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 15:57:03 +0100
Subject: [PATCH 32/64] First cut of a rust delta implementation
---
Cargo.lock | 213 +++++++++++++++++++++++++++++++--
Cargo.toml | 5 +-
src/bins/Cargo.toml | 8 +-
src/bins/src/commands/mod.rs | 3 +
src/bins/src/commands/patch.rs | 206 +++++++++++++++++++++++++++++++
src/bins/src/update.rs | 31 +++--
src/bins/tests/commands.rs | 42 ++++++-
src/lib-rust/Cargo.toml | 8 +-
src/lib-rust/src/delta.rs | 48 --------
src/lib-rust/src/lib.rs | 3 -
src/lib-rust/src/logging.rs | 15 ++-
11 files changed, 494 insertions(+), 88 deletions(-)
create mode 100644 src/bins/src/commands/patch.rs
delete mode 100644 src/lib-rust/src/delta.rs
diff --git a/Cargo.lock b/Cargo.lock
index 16f6eb3f..6ce860fd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8,6 +8,17 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+[[package]]
+name = "aes"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cipher",
+ "cpufeatures",
+]
+
[[package]]
name = "aho-corasick"
version = "1.1.3"
@@ -310,6 +321,25 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
+[[package]]
+name = "bzip2"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47"
+dependencies = [
+ "bzip2-sys",
+]
+
+[[package]]
+name = "bzip2-sys"
+version = "0.1.13+1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
+dependencies = [
+ "cc",
+ "pkg-config",
+]
+
[[package]]
name = "cbindgen"
version = "0.28.0"
@@ -366,6 +396,16 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
[[package]]
name = "clap"
version = "4.5.38"
@@ -427,6 +467,12 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "constant_time_eq"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+
[[package]]
name = "core-foundation"
version = "0.10.0"
@@ -452,6 +498,21 @@ dependencies = [
"libc",
]
+[[package]]
+name = "crc"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
+
[[package]]
name = "crc32fast"
version = "1.4.2"
@@ -521,6 +582,12 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "deflate64"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
+
[[package]]
name = "deranged"
version = "0.4.1"
@@ -576,6 +643,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
+ "subtle",
]
[[package]]
@@ -634,7 +702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -796,8 +864,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if 1.0.0",
+ "js-sys",
"libc",
"wasi 0.13.3+wasi-0.2.2",
+ "wasm-bindgen",
"windows-targets 0.52.6",
]
@@ -853,6 +923,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
[[package]]
name = "http"
version = "1.2.0"
@@ -1064,6 +1143,15 @@ dependencies = [
"hashbrown",
]
+[[package]]
+name = "inout"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
+dependencies = [
+ "generic-array",
+]
+
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
@@ -1133,7 +1221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
dependencies = [
"cfg-if 1.0.0",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -1200,6 +1288,27 @@ dependencies = [
"log",
]
+[[package]]
+name = "lzma-rs"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
+dependencies = [
+ "byteorder",
+ "crc",
+]
+
+[[package]]
+name = "lzma-sys"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
[[package]]
name = "memchr"
version = "2.7.4"
@@ -1351,6 +1460,16 @@ version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
+[[package]]
+name = "pbkdf2"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
+dependencies = [
+ "digest",
+ "hmac",
+]
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -1382,9 +1501,9 @@ dependencies = [
[[package]]
name = "pkg-config"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "png"
@@ -1595,7 +1714,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.4.15",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1608,7 +1727,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.9.2",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1841,6 +1960,15 @@ dependencies = [
"syn 2.0.98",
]
+[[package]]
+name = "substring"
+version = "1.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "subtle"
version = "2.6.1"
@@ -1901,7 +2029,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix 1.0.1",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2232,7 +2360,6 @@ dependencies = [
"windows",
"xml",
"zip",
- "zstd",
]
[[package]]
@@ -2273,15 +2400,20 @@ dependencies = [
"simplelog",
"strsim 0.11.1",
"strum",
+ "substring",
"tempfile",
"time 0.3.41",
"velopack",
"wait-timeout",
"waitpid-any",
+ "walkdir",
"webview2-com-sys",
"windows",
"winres",
"winsafe",
+ "zip",
+ "zip-extensions",
+ "zstd",
]
[[package]]
@@ -2338,6 +2470,16 @@ dependencies = [
"windows-sys 0.59.0",
]
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
@@ -2500,7 +2642,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
- "windows-sys 0.48.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2827,6 +2969,15 @@ version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4"
+[[package]]
+name = "xz2"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
+dependencies = [
+ "lzma-sys",
+]
+
[[package]]
name = "yansi"
version = "1.0.1"
@@ -2924,6 +3075,20 @@ name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
[[package]]
name = "zerovec"
@@ -2953,13 +3118,35 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dcb24d0152526ae49b9b96c1dcf71850ca1e0b882e4e28ed898a93c41334744"
dependencies = [
+ "aes",
"arbitrary",
+ "bzip2",
+ "constant_time_eq",
"crc32fast",
"crossbeam-utils",
+ "deflate64",
"flate2",
+ "getrandom 0.3.1",
+ "hmac",
"indexmap",
+ "lzma-rs",
"memchr",
+ "pbkdf2",
+ "sha1",
+ "time 0.3.41",
+ "xz2",
+ "zeroize",
"zopfli",
+ "zstd",
+]
+
+[[package]]
+name = "zip-extensions"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79cdbf826e5a6eec81fc5a0d33cd7c09c31fd8f9918f15434f74c42d39ef337a"
+dependencies = [
+ "zip",
]
[[package]]
@@ -2987,18 +3174,18 @@ dependencies = [
[[package]]
name = "zstd-safe"
-version = "7.2.3"
+version = "7.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722"
+checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
-version = "2.0.14+zstd.1.5.7"
+version = "2.0.15+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5"
+checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
dependencies = [
"cc",
"pkg-config",
diff --git a/Cargo.toml b/Cargo.toml
index 6af625bb..69113a48 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,8 @@ derivative = "2.2"
glob = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
-zip = { version = "2.2", default-features = false, features = ["deflate"] }
+zip = { version = "2.6", default-features = false, features = ["deflate"] }
+zip-extensions = "0.8.2"
thiserror = "2.0"
lazy_static = "1.5"
regex = "1.10"
@@ -83,6 +84,8 @@ log-panics = "2.1.0"
core-foundation = "0.10"
core-foundation-sys = "0.8"
uuid = { version = "1.13.1", features = ["v4", "fast-rng", "macro-diagnostics"] }
+walkdir = "2.5"
+substring = " 1.4"
# default to small, optimized workspace release binaries
[profile.release]
diff --git a/src/bins/Cargo.toml b/src/bins/Cargo.toml
index 780c533f..76427c28 100644
--- a/src/bins/Cargo.toml
+++ b/src/bins/Cargo.toml
@@ -63,6 +63,12 @@ wait-timeout.workspace = true
pretty-bytes-rust.workspace = true
enum-flags.workspace = true
log-panics.workspace = true
+zstd.workspace = true
+zip.workspace = true
+zip-extensions.workspace = true
+walkdir.workspace = true
+sha1_smol.workspace = true
+substring.workspace = true
[target.'cfg(target_os="linux")'.dependencies]
waitpid-any.workspace = true
@@ -101,6 +107,7 @@ windows = { workspace = true, features = [
"Win32_UI_Shell_Common",
"Win32_UI_Shell_PropertiesSystem",
"Win32_UI_WindowsAndMessaging",
+ "Win32_System_ApplicationInstallationAndServicing",
"Win32_System_Kernel",
"Wdk",
"Wdk_System",
@@ -116,7 +123,6 @@ same-file.workspace = true
tempfile.workspace = true
ntest.workspace = true
pretty_assertions.workspace = true
-sha1_smol.workspace = true
[build-dependencies]
semver.workspace = true
diff --git a/src/bins/src/commands/mod.rs b/src/bins/src/commands/mod.rs
index e6de8bfe..29d9b652 100644
--- a/src/bins/src/commands/mod.rs
+++ b/src/bins/src/commands/mod.rs
@@ -4,6 +4,9 @@ pub use apply::*;
mod start;
pub use start::*;
+mod patch;
+pub use patch::*;
+
#[cfg(target_os = "linux")]
mod apply_linux_impl;
#[cfg(target_os = "macos")]
diff --git a/src/bins/src/commands/patch.rs b/src/bins/src/commands/patch.rs
new file mode 100644
index 00000000..c5d1acbe
--- /dev/null
+++ b/src/bins/src/commands/patch.rs
@@ -0,0 +1,206 @@
+use anyhow::{anyhow, bail, Result};
+use std::os::windows::fs::MetadataExt;
+use std::{
+ collections::HashSet,
+ fs, io,
+ path::{Path, PathBuf},
+};
+use walkdir::WalkDir;
+use zip::{write::SimpleFileOptions, CompressionMethod};
+use zip_extensions::{zip_create_from_directory_with_options, zip_extract};
+
+pub fn zstd_patch_single, P2: AsRef, P3: AsRef>(old_file: P1, patch_file: P2, output_file: P3) -> Result<()> {
+ let old_file = old_file.as_ref();
+ let patch_file = patch_file.as_ref();
+ let output_file = output_file.as_ref();
+
+ if !old_file.exists() {
+ bail!("Old file does not exist: {}", old_file.to_string_lossy());
+ }
+
+ if !patch_file.exists() {
+ bail!("Patch file does not exist: {}", patch_file.to_string_lossy());
+ }
+
+ let dict = fs::read(old_file)?;
+
+ // info!("Loading Dictionary (Size: {})", dict.len());
+ let patch = fs::OpenOptions::new().read(true).open(patch_file)?;
+ let patch_reader = io::BufReader::new(patch);
+ let mut decoder = zstd::Decoder::with_dictionary(patch_reader, &dict)?;
+
+ let window_log = fio_highbit64(dict.len() as u64) + 1;
+ if window_log >= 27 {
+ info!("Large File detected. Overriding windowLog to {}", window_log);
+ decoder.window_log_max(window_log)?;
+ }
+
+ // info!("Decoder loaded. Beginning patch...");
+ let mut output = fs::OpenOptions::new().write(true).create(true).truncate(true).open(output_file)?;
+ io::copy(&mut decoder, &mut output)?;
+
+ // info!("Patch applied successfully.");
+ Ok(())
+}
+
+fn fio_highbit64(v: u64) -> u32 {
+ let mut count: u32 = 0;
+ let mut v = v;
+ v >>= 1;
+ while v > 0 {
+ v >>= 1;
+ count += 1;
+ }
+ return count;
+}
+
+pub fn delta, P2: AsRef, P3: AsRef>(
+ old_file: P1,
+ delta_files: Vec<&PathBuf>,
+ temp_dir: P2,
+ output_file: P3,
+) -> Result<()> {
+ let old_file = old_file.as_ref().to_path_buf();
+ let temp_dir = temp_dir.as_ref().to_path_buf();
+ let output_file = output_file.as_ref().to_path_buf();
+
+ if !old_file.exists() {
+ bail!("Old file does not exist: {}", old_file.to_string_lossy());
+ }
+
+ if delta_files.is_empty() {
+ bail!("No delta files provided.");
+ }
+
+ for delta_file in &delta_files {
+ if !delta_file.exists() {
+ bail!("Delta file does not exist: {}", delta_file.to_string_lossy());
+ }
+ }
+
+ let time = simple_stopwatch::Stopwatch::start_new();
+
+ info!("Extracting base package for delta patching: {}", temp_dir.to_string_lossy());
+ let work_dir = temp_dir.join("_work");
+ fs::create_dir_all(&work_dir)?;
+ zip_extract(&old_file, &work_dir)?;
+
+ info!("Base package extracted. {} delta packages to apply.", delta_files.len());
+
+ for (i, delta_file) in delta_files.iter().enumerate() {
+ info!("{}: extracting apply delta patch: {}", i, delta_file.to_string_lossy());
+ let delta_dir = temp_dir.join(format!("delta_{}", i));
+ fs::create_dir_all(&delta_dir)?;
+ zip_extract(delta_file, &delta_dir)?;
+
+ let delta_relative_paths: Vec = WalkDir::new(&delta_dir)
+ .follow_links(false)
+ .into_iter()
+ .filter_map(|entry| entry.ok())
+ .filter(|entry| entry.file_type().is_file())
+ .map(|entry| entry.path().strip_prefix(&delta_dir).map(|p| p.to_path_buf()))
+ .filter_map(|entry| entry.ok())
+ .collect();
+
+ let mut visited_paths = HashSet::new();
+
+ // apply all the zsdiff patches for files which exist in both the delta and the base package
+ for relative_path in &delta_relative_paths {
+ if relative_path.starts_with("lib") {
+ let file_name = relative_path.file_name().ok_or(anyhow!("Failed to get file name"))?;
+ let file_name_str = file_name.to_string_lossy();
+ if file_name_str.ends_with(".zsdiff") || file_name_str.ends_with(".diff") || file_name_str.ends_with(".bsdiff") {
+ // this is a zsdiff patch, we need to apply it to the old file
+ let file_without_extension = relative_path.with_extension("");
+ // let shasum_path = delta_dir.join(relative_path).with_extension("shasum");
+ let old_file_path = work_dir.join(&file_without_extension);
+ let patch_file_path = delta_dir.join(&relative_path);
+ let output_file_path = delta_dir.join(&file_without_extension);
+
+ visited_paths.insert(file_without_extension);
+
+ if fs::metadata(&patch_file_path)?.file_size() == 0 {
+ // file has not changed, so we can continue.
+ continue;
+ }
+
+ if file_name_str.ends_with(".zsdiff") {
+ info!("{}: applying zsdiff patch: {:?}", i, relative_path);
+ zstd_patch_single(&old_file_path, &patch_file_path, &output_file_path)?;
+ } else {
+ bail!("Unsupported patch format: {:?}", relative_path);
+ }
+
+ fs::rename(&output_file_path, &old_file_path)?;
+ } else if file_name_str.ends_with(".shasum") {
+ // skip shasum files
+ } else {
+ // if this file is inside the lib folder without a known extension, it is a new file
+ let file_path = delta_dir.join(relative_path);
+ let dest_path = work_dir.join(relative_path);
+ info!("{}: new file: {:?}", i, relative_path);
+ fs::copy(&file_path, &dest_path)?;
+ visited_paths.insert(relative_path.clone());
+ }
+ } else {
+ // if this file is not inside the lib folder, we always copy it over
+ let file_path = delta_dir.join(relative_path);
+ let dest_path = work_dir.join(relative_path);
+ info!("{}: copying metadata file: {:?}", i, relative_path);
+ fs::copy(&file_path, &dest_path)?;
+ visited_paths.insert(relative_path.clone());
+ }
+ }
+
+ // anything in the work dir which was not visited is an old / deleted file and should be removed
+ let workdir_relative_paths: Vec = WalkDir::new(&work_dir)
+ .follow_links(false)
+ .into_iter()
+ .filter_map(|entry| entry.ok())
+ .filter(|entry| entry.file_type().is_file())
+ .map(|entry| entry.path().strip_prefix(&work_dir).map(|p| p.to_path_buf()))
+ .filter_map(|entry| entry.ok())
+ .collect();
+
+ for relative_path in &workdir_relative_paths {
+ if !visited_paths.contains(relative_path) {
+ let file_to_delete = work_dir.join(relative_path);
+ info!("{}: deleting old/removed file: {:?}", i, relative_path);
+ let _ = fs::remove_file(file_to_delete); // soft error
+ }
+ }
+ }
+
+ info!("All delta patches applied. Asembling output package at: {}", output_file.to_string_lossy());
+
+ // NOTE: zstd is not supported by older versions of Squirrel/Velopack, but
+ // it's assumed if someone is using this code, they are using a recent enough version
+ let options = SimpleFileOptions::default().compression_method(CompressionMethod::Zstd);
+ zip_create_from_directory_with_options(&output_file, &work_dir, |_| options)?;
+
+ info!("Successfully applied {} delta patches in {}s.", delta_files.len(), time.s());
+ Ok(())
+}
+
+// NOTE: this is some code to do checksum verification, but it is not being used
+// by the current implementation because zstd patching already has checksum verification
+//
+// let actual_checksum = get_sha1(&output_file_path);
+// let expected_checksum = load_release_entry_shasum(&shasum_path)?;
+//
+// if !actual_checksum.eq_ignore_ascii_case(&expected_checksum) {
+// bail!("Checksum mismatch for: {:?}. Expected: {}, Actual: {}", relative_path, expected_checksum, actual_checksum);
+// }
+// fn load_release_entry_shasum(file: &PathBuf) -> Result {
+// let raw_text = fs::read_to_string(file)?.trim().to_string();
+// let first_word = raw_text.splitn(2, ' ').next().unwrap();
+// let cleaned = first_word.trim().trim_matches(|c: char| !c.is_ascii_hexdigit());
+// Ok(cleaned.to_string())
+// }
+//
+// fn get_sha1(file: &PathBuf) -> String {
+// let file_bytes = fs::read(file).unwrap();
+// let mut sha1 = sha1_smol::Sha1::new();
+// sha1.update(&file_bytes);
+// sha1.digest().to_string()
+// }
diff --git a/src/bins/src/update.rs b/src/bins/src/update.rs
index 90706722..80563b74 100644
--- a/src/bins/src/update.rs
+++ b/src/bins/src/update.rs
@@ -5,7 +5,7 @@
extern crate log;
use anyhow::{anyhow, bail, Result};
-use clap::{arg, value_parser, ArgMatches, Command};
+use clap::{arg, value_parser, ArgAction, ArgMatches, Command};
use std::{env, path::PathBuf};
use velopack::locator::{auto_locate_app_manifest, LocationContext};
use velopack::logging::*;
@@ -34,9 +34,9 @@ fn root_command() -> Command {
.long_flag_aliases(vec!["processStart", "processStartAndWait"])
)
.subcommand(Command::new("patch")
- .about("Applies a Zstd patch file")
+ .about("Applies a series of delta bundles to a base file")
.arg(arg!(--old "Base / old file to apply the patch to").required(true).value_parser(value_parser!(PathBuf)))
- .arg(arg!(--patch "The Zstd patch to apply to the old file").required(true).value_parser(value_parser!(PathBuf)))
+ .arg(arg!(--delta "The delta bundle to apply to the base package").required(true).action(ArgAction::Append).value_parser(value_parser!(PathBuf)))
.arg(arg!(--output "The file to create with the patch applied").required(true).value_parser(value_parser!(PathBuf)))
)
.arg(arg!(--verbose "Print debug messages to console / log").global(true))
@@ -180,19 +180,34 @@ fn main() -> Result<()> {
fn patch(matches: &ArgMatches) -> Result<()> {
let old_file = matches.get_one::("old");
- let patch_file = matches.get_one::("patch");
+ let deltas: Vec<&PathBuf> = matches.get_many::("delta").unwrap_or_default().collect();
let output_file = matches.get_one::("output");
info!("Command: Patch");
info!(" Old File: {:?}", old_file);
- info!(" Patch File: {:?}", patch_file);
+ info!(" Delta Files: {:?}", deltas);
info!(" Output File: {:?}", output_file);
- if old_file.is_none() || patch_file.is_none() || output_file.is_none() {
- bail!("Missing required arguments. Please provide --old, --patch, and --output.");
+ if old_file.is_none() || deltas.is_empty() || output_file.is_none() {
+ bail!("Missing required arguments. Please provide --old, --delta, and --output.");
}
- velopack::delta::zstd_patch_single(old_file.unwrap(), patch_file.unwrap(), output_file.unwrap())?;
+ let temp_dir = match auto_locate_app_manifest(LocationContext::IAmUpdateExe) {
+ Ok(locator) => locator.get_temp_dir_rand16(),
+ Err(_) => {
+ let mut temp_dir = std::env::temp_dir();
+ let rand = shared::random_string(16);
+ temp_dir.push("velopack_".to_owned() + &rand);
+ temp_dir
+ }
+ };
+
+ let result = commands::delta(old_file.unwrap(), deltas, &temp_dir, output_file.unwrap());
+ let _ = remove_dir_all::remove_dir_all(temp_dir);
+
+ if let Err(e) = result {
+ bail!("Delta error: {}", e);
+ }
Ok(())
}
diff --git a/src/bins/tests/commands.rs b/src/bins/tests/commands.rs
index 32a8bb79..f6defce8 100644
--- a/src/bins/tests/commands.rs
+++ b/src/bins/tests/commands.rs
@@ -3,13 +3,14 @@
mod common;
use common::*;
use std::{fs, path::Path, path::PathBuf};
+use std::hint::assert_unchecked;
use tempfile::tempdir;
use velopack_bins::*;
-#[cfg(target_os = "windows")]
-use winsafe::{self as w, co};
use velopack::bundle::load_bundle_from_file;
use velopack::locator::{auto_locate_app_manifest, LocationContext};
+#[cfg(target_os = "windows")]
+use winsafe::{self as w, co};
#[cfg(target_os = "windows")]
#[test]
@@ -87,7 +88,7 @@ pub fn test_install_preserve_symlinks() {
let tmp_dir = tempdir().unwrap();
let tmp_buf = tmp_dir.path().to_path_buf();
let mut tmp_zip = load_bundle_from_file(nupkg).unwrap();
-
+
commands::install(&mut tmp_zip, Some(&tmp_buf), None).unwrap();
assert!(tmp_buf.join("current").join("actual").join("file.txt").exists());
@@ -119,13 +120,42 @@ pub fn test_patch_apply() {
let expected_sha1 = get_sha1(&new_file);
let tmp_file = Path::new("temp.patch").to_path_buf();
- velopack::delta::zstd_patch_single(&old_file, &p1, &tmp_file).unwrap();
+ velopack_bins::commands::zstd_patch_single(&old_file, &p1, &tmp_file).unwrap();
let tmp_sha1 = get_sha1(&tmp_file);
fs::remove_file(&tmp_file).unwrap();
assert_eq!(expected_sha1, tmp_sha1);
- velopack::delta::zstd_patch_single(&old_file, &p2, &tmp_file).unwrap();
+ velopack_bins::commands::zstd_patch_single(&old_file, &p2, &tmp_file).unwrap();
let tmp_sha1 = get_sha1(&tmp_file);
fs::remove_file(&tmp_file).unwrap();
assert_eq!(expected_sha1, tmp_sha1);
-}
+}
+
+#[test]
+pub fn test_delta_apply_legacy() {
+ dialogs::set_silent(true);
+ let fixtures = find_fixtures();
+ let base = fixtures.join("Clowd-3.4.287-full.nupkg");
+ let d1 = fixtures.join("Clowd-3.4.288-delta-zstd.nupkg");
+ let d2 = fixtures.join("Clowd-3.4.291-delta-zstd.nupkg");
+ let d3 = fixtures.join("Clowd-3.4.292-delta-zstd.nupkg");
+ let d4 = fixtures.join("Clowd-3.4.293-delta-zstd.nupkg");
+
+ let deltas = vec![&d1, &d2, &d3, &d4];
+
+ let tmp_dir = tempdir().unwrap();
+ let temp_output = tmp_dir.path().join("Clowd-3.4.293-full.nupkg");
+ commands::delta(&base, deltas, tmp_dir.path(), &temp_output).unwrap();
+
+ let mut bundle = load_bundle_from_file(temp_output).unwrap();
+ let manifest = bundle.read_manifest().unwrap();
+
+ assert_eq!(manifest.id, "Clowd");
+ assert_eq!(manifest.version, semver::Version::parse("3.4.293").unwrap());
+
+ let extract_dir = tmp_dir.path().join("_extracted");
+ bundle.extract_lib_contents_to_path(&extract_dir, |_| {}).unwrap();
+
+ let extracted = extract_dir.join("Clowd.dll");
+ assert!(extracted.exists());
+}
diff --git a/src/lib-rust/Cargo.toml b/src/lib-rust/Cargo.toml
index 158f1752..f522432e 100644
--- a/src/lib-rust/Cargo.toml
+++ b/src/lib-rust/Cargo.toml
@@ -14,14 +14,13 @@ edition.workspace = true
rust-version.workspace = true
[features]
-default = ["zstd"]
-delta = ["zstd"]
+default = []
async = ["async-std"]
typescript = ["ts-rs"]
file-logging = ["log-panics", "simplelog", "file-rotate", "time"]
[package.metadata.docs.rs]
-features = ["async", "delta"]
+features = ["async"]
[lib]
name = "velopack"
@@ -54,9 +53,6 @@ uuid.workspace = true
# typescript
ts-rs = { workspace = true, optional = true }
-# delta packages
-zstd = { workspace = true, optional = true }
-
# async
async-std = { workspace = true, optional = true }
diff --git a/src/lib-rust/src/delta.rs b/src/lib-rust/src/delta.rs
deleted file mode 100644
index 40ea7222..00000000
--- a/src/lib-rust/src/delta.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use std::{fs, io, path::Path};
-use crate::Error;
-
-/// Applies a zstd patch to a single file by loading the patch as a dictionary.
-pub fn zstd_patch_single, P2: AsRef, P3: AsRef>(old_file: P1, patch_file: P2, output_file: P3) -> Result<(), Error> {
- let old_file = old_file.as_ref();
- let patch_file = patch_file.as_ref();
- let output_file = output_file.as_ref();
-
- if !old_file.exists() {
- return Err(Error::FileNotFound(old_file.to_string_lossy().to_string()));
- }
-
- if !patch_file.exists() {
- return Err(Error::FileNotFound(patch_file.to_string_lossy().to_string()));
- }
-
- let dict = fs::read(old_file)?;
-
- info!("Loading Dictionary (Size: {})", dict.len());
- let patch = fs::OpenOptions::new().read(true).open(patch_file)?;
- let patch_reader = io::BufReader::new(patch);
- let mut decoder = zstd::Decoder::with_dictionary(patch_reader, &dict)?;
-
- let window_log = fio_highbit64(dict.len() as u64) + 1;
- if window_log >= 27 {
- info!("Large File detected. Overriding windowLog to {}", window_log);
- decoder.window_log_max(window_log)?;
- }
-
- info!("Decoder loaded. Beginning patch...");
- let mut output = fs::OpenOptions::new().write(true).create(true).truncate(true).open(output_file)?;
- io::copy(&mut decoder, &mut output)?;
-
- info!("Patch applied successfully.");
- Ok(())
-}
-
-fn fio_highbit64(v: u64) -> u32 {
- let mut count: u32 = 0;
- let mut v = v;
- v >>= 1;
- while v > 0 {
- v >>= 1;
- count += 1;
- }
- return count;
-}
\ No newline at end of file
diff --git a/src/lib-rust/src/lib.rs b/src/lib-rust/src/lib.rs
index e2bf7580..dfe36739 100644
--- a/src/lib-rust/src/lib.rs
+++ b/src/lib-rust/src/lib.rs
@@ -97,9 +97,6 @@ pub mod locator;
/// Sources contains abstractions for custom update sources (eg. url, local file, github releases, etc).
pub mod sources;
-/// Functions to patch files and reconstruct Velopack delta packages.
-pub mod delta;
-
/// Acquire and manage file-system based lock files.
pub mod lockfile;
diff --git a/src/lib-rust/src/logging.rs b/src/lib-rust/src/logging.rs
index 4e208c8c..ddebcf41 100644
--- a/src/lib-rust/src/logging.rs
+++ b/src/lib-rust/src/logging.rs
@@ -76,12 +76,18 @@ pub fn default_logfile_path>(locator: L) -> PathBuf
/// It can only be called once per process, and should be called early in the process lifecycle.
/// Future calls to this function will fail.
#[cfg(feature = "file-logging")]
-pub fn init_logging(process_name: &str, file: Option<&PathBuf>, console: bool, verbose: bool, custom_log_cb: Option>) {
+pub fn init_logging(
+ process_name: &str,
+ file: Option<&PathBuf>,
+ console: bool,
+ verbose: bool,
+ custom_log_cb: Option>,
+) {
let mut loggers: Vec> = Vec::new();
if let Some(cb) = custom_log_cb {
loggers.push(cb);
}
-
+
let color_choice = ColorChoice::Never;
if console {
let console_level = if verbose { LevelFilter::Debug } else { LevelFilter::Info };
@@ -105,6 +111,11 @@ pub fn init_logging(process_name: &str, file: Option<&PathBuf>, console: bool, v
}
}
+/// Initialize a Trace / Console logger for the current process.
+pub fn trace_logger() {
+ TermLogger::init(LevelFilter::Trace, get_config(None), TerminalMode::Mixed, ColorChoice::Never).unwrap();
+}
+
#[cfg(feature = "file-logging")]
fn get_config(process_name: Option<&str>) -> Config {
let mut c = ConfigBuilder::default();
From f4c82bed9d26bcf47ab5e0c623aa7784990f9099 Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 18:43:10 +0100
Subject: [PATCH 33/64] Rename compression files
---
src/lib-csharp/{Compression => Util}/EasyZip.cs | 0
.../Velopack.Packaging}/Compression/BZip2Stream.cs | 0
.../Velopack.Packaging}/Compression/BinaryPatchUtility.cs | 0
src/vpk/Velopack.Packaging/{ => Compression}/DeltaEmbedded.cs | 0
src/vpk/Velopack.Packaging/{ => Compression}/DeltaMode.cs | 0
.../Velopack.Packaging}/Compression/DeltaPackage.cs | 0
.../Velopack.Packaging/{ => Compression}/DeltaPackageBuilder.cs | 0
.../Velopack.Packaging}/Compression/DeltaUpdateExe.cs | 0
.../Velopack.Packaging}/Compression/MsDeltaCompression.cs | 0
9 files changed, 0 insertions(+), 0 deletions(-)
rename src/lib-csharp/{Compression => Util}/EasyZip.cs (100%)
rename src/{lib-csharp => vpk/Velopack.Packaging}/Compression/BZip2Stream.cs (100%)
rename src/{lib-csharp => vpk/Velopack.Packaging}/Compression/BinaryPatchUtility.cs (100%)
rename src/vpk/Velopack.Packaging/{ => Compression}/DeltaEmbedded.cs (100%)
rename src/vpk/Velopack.Packaging/{ => Compression}/DeltaMode.cs (100%)
rename src/{lib-csharp => vpk/Velopack.Packaging}/Compression/DeltaPackage.cs (100%)
rename src/vpk/Velopack.Packaging/{ => Compression}/DeltaPackageBuilder.cs (100%)
rename src/{lib-csharp => vpk/Velopack.Packaging}/Compression/DeltaUpdateExe.cs (100%)
rename src/{lib-csharp => vpk/Velopack.Packaging}/Compression/MsDeltaCompression.cs (100%)
diff --git a/src/lib-csharp/Compression/EasyZip.cs b/src/lib-csharp/Util/EasyZip.cs
similarity index 100%
rename from src/lib-csharp/Compression/EasyZip.cs
rename to src/lib-csharp/Util/EasyZip.cs
diff --git a/src/lib-csharp/Compression/BZip2Stream.cs b/src/vpk/Velopack.Packaging/Compression/BZip2Stream.cs
similarity index 100%
rename from src/lib-csharp/Compression/BZip2Stream.cs
rename to src/vpk/Velopack.Packaging/Compression/BZip2Stream.cs
diff --git a/src/lib-csharp/Compression/BinaryPatchUtility.cs b/src/vpk/Velopack.Packaging/Compression/BinaryPatchUtility.cs
similarity index 100%
rename from src/lib-csharp/Compression/BinaryPatchUtility.cs
rename to src/vpk/Velopack.Packaging/Compression/BinaryPatchUtility.cs
diff --git a/src/vpk/Velopack.Packaging/DeltaEmbedded.cs b/src/vpk/Velopack.Packaging/Compression/DeltaEmbedded.cs
similarity index 100%
rename from src/vpk/Velopack.Packaging/DeltaEmbedded.cs
rename to src/vpk/Velopack.Packaging/Compression/DeltaEmbedded.cs
diff --git a/src/vpk/Velopack.Packaging/DeltaMode.cs b/src/vpk/Velopack.Packaging/Compression/DeltaMode.cs
similarity index 100%
rename from src/vpk/Velopack.Packaging/DeltaMode.cs
rename to src/vpk/Velopack.Packaging/Compression/DeltaMode.cs
diff --git a/src/lib-csharp/Compression/DeltaPackage.cs b/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
similarity index 100%
rename from src/lib-csharp/Compression/DeltaPackage.cs
rename to src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
diff --git a/src/vpk/Velopack.Packaging/DeltaPackageBuilder.cs b/src/vpk/Velopack.Packaging/Compression/DeltaPackageBuilder.cs
similarity index 100%
rename from src/vpk/Velopack.Packaging/DeltaPackageBuilder.cs
rename to src/vpk/Velopack.Packaging/Compression/DeltaPackageBuilder.cs
diff --git a/src/lib-csharp/Compression/DeltaUpdateExe.cs b/src/vpk/Velopack.Packaging/Compression/DeltaUpdateExe.cs
similarity index 100%
rename from src/lib-csharp/Compression/DeltaUpdateExe.cs
rename to src/vpk/Velopack.Packaging/Compression/DeltaUpdateExe.cs
diff --git a/src/lib-csharp/Compression/MsDeltaCompression.cs b/src/vpk/Velopack.Packaging/Compression/MsDeltaCompression.cs
similarity index 100%
rename from src/lib-csharp/Compression/MsDeltaCompression.cs
rename to src/vpk/Velopack.Packaging/Compression/MsDeltaCompression.cs
From 53bf55cacefbcaeddaf3ad635611234ad6b0904c Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 18:45:44 +0100
Subject: [PATCH 34/64] Refactor namespaces
---
src/lib-csharp/UpdateManager.cs | 88 ++++++++-----------
src/lib-csharp/Util/EasyZip.cs | 2 +-
src/vpk/Velopack.Build/TaskOptionsMapper.cs | 1 +
.../VelopackFlowServiceClient.cs | 1 +
.../Velopack.Packaging.Unix/AppImageTool.cs | 1 -
.../Commands/LinuxPackCommandRunner.cs | 1 +
.../Commands/LinuxPackOptions.cs | 1 +
.../Commands/OsxPackOptions.cs | 1 +
.../Commands/WindowsPackCommandRunner.cs | 1 -
.../Commands/WindowsReleasifyOptions.cs | 4 +-
.../Abstractions/IPackOptions.cs | 4 +-
.../Commands/DeltaGenCommandRunner.cs | 1 +
.../Commands/DeltaGenOptions.cs | 1 +
.../Commands/DeltaPatchCommandRunner.cs | 2 +-
.../Compression/BZip2Stream.cs | 4 +-
.../Compression/BinaryPatchUtility.cs | 5 +-
.../Compression/DeltaEmbedded.cs | 3 +-
.../Compression/DeltaMode.cs | 2 +-
.../Compression/DeltaPackage.cs | 7 +-
.../Compression/DeltaPackageBuilder.cs | 3 +-
.../Compression/DeltaUpdateExe.cs | 5 +-
.../Compression/MsDeltaCompression.cs | 4 +-
src/vpk/Velopack.Packaging/PackageBuilder.cs | 2 +-
src/vpk/Velopack.Packaging/Zstd.cs | 1 +
.../Commands/Packaging/DeltaGenCommand.cs | 1 +
.../Commands/Packaging/PackCommand.cs | 1 +
.../Commands/WindowsCommandTests.cs | 2 +-
test/Velopack.Packaging.Tests/OsxPackTests.cs | 1 -
.../WindowsPackTests.cs | 2 +-
test/Velopack.Tests/SymbolicLinkTests.cs | 1 -
test/Velopack.Tests/UpdateManagerTests.cs | 1 -
test/Velopack.Tests/ZipPackageTests.cs | 4 +-
32 files changed, 70 insertions(+), 88 deletions(-)
diff --git a/src/lib-csharp/UpdateManager.cs b/src/lib-csharp/UpdateManager.cs
index 4f57a07b..7e1e7f76 100644
--- a/src/lib-csharp/UpdateManager.cs
+++ b/src/lib-csharp/UpdateManager.cs
@@ -1,11 +1,12 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Versioning;
-using Velopack.Compression;
using Velopack.Exceptions;
using Velopack.Locators;
using Velopack.Logging;
@@ -231,8 +232,6 @@ namespace Velopack
EnsureInstalled();
using var _mut = await AcquireUpdateLock().ConfigureAwait(false);
- var appTempDir = Locator.AppTempDir!;
-
var completeFile = Locator.GetLocalPackagePath(targetRelease);
var incompleteFile = completeFile + ".partial";
@@ -262,33 +261,9 @@ namespace Velopack
$"There are too many delta's ({deltasCount} > 10) or the sum of their size ({deltasSize} > {targetRelease.Size}) is too large. " +
$"Only full update will be available.");
} else {
- using var _1 = TempUtil.GetTempDirectory(out var deltaStagingDir, appTempDir);
- string basePackagePath = Locator.GetLocalPackagePath(updates.BaseRelease);
- if (!File.Exists(basePackagePath))
- throw new Exception($"Unable to find base package {basePackagePath} for delta update.");
- EasyZip.ExtractZipToDirectory(Log, basePackagePath, deltaStagingDir);
-
- reportProgress(10);
- await DownloadAndApplyDeltaUpdates(
- deltaStagingDir,
- updates,
- x => reportProgress(CoreUtil.CalculateProgress(x, 10, 80)),
- cancelToken)
- .ConfigureAwait(false);
- reportProgress(80);
-
- Log.Info("Delta updates completed, creating final update package.");
- File.Delete(incompleteFile);
- await EasyZip.CreateZipFromDirectoryAsync(
- Log,
- incompleteFile,
- deltaStagingDir,
- x => reportProgress(CoreUtil.CalculateProgress(x, 80, 100)),
- cancelToken: cancelToken).ConfigureAwait(false);
- File.Delete(completeFile);
- File.Move(incompleteFile, completeFile);
- Log.Info("Delta release preparations complete. Package moved to: " + completeFile);
- reportProgress(100);
+ await DownloadAndApplyDeltaUpdates(updates, incompleteFile, progress, cancelToken).ConfigureAwait(false);
+ IoUtil.MoveFile(incompleteFile, completeFile, true);
+ Log.Info("Delta update download complete. Package moved to: " + completeFile);
return; // success!
}
}
@@ -336,19 +311,17 @@ namespace Velopack
/// Given a folder containing the extracted base package, and a list of delta updates, downloads and applies the
/// delta updates to the base package.
///
- /// A folder containing the application files to apply the delta's to.
/// An update object containing one or more delta's
+ /// The reconstructed full update after all delta's are applied
/// A callback reporting process of delta application progress (from 0-100).
/// A token to use to cancel the request.
- protected virtual async Task DownloadAndApplyDeltaUpdates(string extractedBasePackage, UpdateInfo updates, Action progress,
+ protected virtual async Task DownloadAndApplyDeltaUpdates(UpdateInfo updates, string targetFile, Action progress,
CancellationToken cancelToken)
{
var releasesToDownload = updates.DeltasToTarget.OrderBy(d => d.Version).ToArray();
-
- var appTempDir = Locator.AppTempDir!;
var updateExe = Locator.UpdateExePath!;
- // downloading accounts for 0%-50% of progress
+ // downloading accounts for 0%-70% of progress
double current = 0;
double toIncrement = 100.0 / releasesToDownload.Count();
await releasesToDownload.ForEachAsync(
@@ -365,7 +338,7 @@ namespace Velopack
current -= component;
component = toIncrement / 100.0 * p;
var progressOfStep = (int) Math.Round(current += component);
- progress(CoreUtil.CalculateProgress(progressOfStep, 0, 50));
+ progress(CoreUtil.CalculateProgress(progressOfStep, 0, 70));
}
},
cancelToken).ConfigureAwait(false);
@@ -374,23 +347,34 @@ namespace Velopack
Log.Debug($"Download complete for delta version {x.Version}");
}).ConfigureAwait(false);
- Log.Info("All delta packages downloaded and verified, applying them to the base now. The delta staging dir is: " + extractedBasePackage);
+ Log.Info("All delta packages downloaded and verified, applying them to the base now.");
- // applying deltas accounts for 50%-100% of progress
- double progressStepSize = 100d / releasesToDownload.Length;
- var builder = new DeltaUpdateExe(Log, appTempDir, updateExe);
- for (var i = 0; i < releasesToDownload.Length; i++) {
- cancelToken.ThrowIfCancellationRequested();
- var rel = releasesToDownload[i];
- double baseProgress = i * progressStepSize;
- var packageFile = Locator.GetLocalPackagePath(rel);
- builder.ApplyDeltaPackageFast(
- extractedBasePackage,
- packageFile,
- x => {
- var progressOfStep = (int) (baseProgress + (progressStepSize * (x / 100d)));
- progress(CoreUtil.CalculateProgress(progressOfStep, 50, 100));
- });
+ // applying deltas accounts for 70%-100% of progress
+ var baseFile = Locator.GetLocalPackagePath(updates.BaseRelease!);
+ var args = new List {
+ "patch",
+ "--old",
+ baseFile,
+ "--output",
+ targetFile,
+ };
+
+ foreach (var x in releasesToDownload) {
+ args.Add("--delta");
+ args.Add(Locator.GetLocalPackagePath(x));
+ }
+
+ var psi = new ProcessStartInfo(updateExe);
+ psi.AppendArgumentListSafe(args, out var _);
+ psi.CreateNoWindow = true;
+ var p = psi.StartRedirectOutputToILogger(Log, VelopackLogLevel.Debug);
+ if (!p.WaitForExit((int)TimeSpan.FromMinutes(5).TotalMilliseconds)) {
+ p.Kill();
+ throw new TimeoutException("patch process timed out (5min).");
+ }
+
+ if (p.ExitCode != 0) {
+ throw new Exception($"patch process failed with exit code {p.ExitCode}.");
}
progress(100);
diff --git a/src/lib-csharp/Util/EasyZip.cs b/src/lib-csharp/Util/EasyZip.cs
index 26ffc5f7..c95c54ff 100644
--- a/src/lib-csharp/Util/EasyZip.cs
+++ b/src/lib-csharp/Util/EasyZip.cs
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
using Velopack.Logging;
using Velopack.Util;
-namespace Velopack.Compression
+namespace Velopack.Util
{
internal static class EasyZip
{
diff --git a/src/vpk/Velopack.Build/TaskOptionsMapper.cs b/src/vpk/Velopack.Build/TaskOptionsMapper.cs
index e3164e5a..07e12971 100644
--- a/src/vpk/Velopack.Build/TaskOptionsMapper.cs
+++ b/src/vpk/Velopack.Build/TaskOptionsMapper.cs
@@ -2,6 +2,7 @@
using System.IO;
using Riok.Mapperly.Abstractions;
using Velopack.Packaging;
+using Velopack.Packaging.Compression;
using Velopack.Packaging.Unix.Commands;
using Velopack.Packaging.Windows.Commands;
diff --git a/src/vpk/Velopack.Flow/VelopackFlowServiceClient.cs b/src/vpk/Velopack.Flow/VelopackFlowServiceClient.cs
index 483d7a41..a8338602 100644
--- a/src/vpk/Velopack.Flow/VelopackFlowServiceClient.cs
+++ b/src/vpk/Velopack.Flow/VelopackFlowServiceClient.cs
@@ -13,6 +13,7 @@ using Velopack.NuGet;
using Velopack.Packaging;
using Velopack.Util;
using System.Net;
+using Velopack.Packaging.Compression;
#if !NET6_0_OR_GREATER
using System.Net.Http;
diff --git a/src/vpk/Velopack.Packaging.Unix/AppImageTool.cs b/src/vpk/Velopack.Packaging.Unix/AppImageTool.cs
index f0efdf24..e4a97f69 100644
--- a/src/vpk/Velopack.Packaging.Unix/AppImageTool.cs
+++ b/src/vpk/Velopack.Packaging.Unix/AppImageTool.cs
@@ -1,6 +1,5 @@
using ICSharpCode.SharpZipLib.Tar;
using Microsoft.Extensions.Logging;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Util;
diff --git a/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs b/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs
index d0cb3bba..934ded32 100644
--- a/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs
+++ b/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging;
using Velopack.Core;
using Velopack.Core.Abstractions;
+using Velopack.Packaging.Compression;
using Velopack.Util;
namespace Velopack.Packaging.Unix.Commands;
diff --git a/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackOptions.cs b/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackOptions.cs
index 19c0fa45..ec0779c4 100644
--- a/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackOptions.cs
+++ b/src/vpk/Velopack.Packaging.Unix/Commands/LinuxPackOptions.cs
@@ -1,4 +1,5 @@
using Velopack.Packaging.Abstractions;
+using Velopack.Packaging.Compression;
namespace Velopack.Packaging.Unix.Commands;
diff --git a/src/vpk/Velopack.Packaging.Unix/Commands/OsxPackOptions.cs b/src/vpk/Velopack.Packaging.Unix/Commands/OsxPackOptions.cs
index 9e9c41db..51010184 100644
--- a/src/vpk/Velopack.Packaging.Unix/Commands/OsxPackOptions.cs
+++ b/src/vpk/Velopack.Packaging.Unix/Commands/OsxPackOptions.cs
@@ -1,4 +1,5 @@
using Velopack.Packaging.Abstractions;
+using Velopack.Packaging.Compression;
namespace Velopack.Packaging.Unix.Commands;
diff --git a/src/vpk/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs b/src/vpk/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs
index 1893370c..997e441e 100644
--- a/src/vpk/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs
+++ b/src/vpk/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs
@@ -5,7 +5,6 @@ using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NuGet.Versioning;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Core.Abstractions;
using Velopack.NuGet;
diff --git a/src/vpk/Velopack.Packaging.Windows/Commands/WindowsReleasifyOptions.cs b/src/vpk/Velopack.Packaging.Windows/Commands/WindowsReleasifyOptions.cs
index 747953a1..97f537b8 100644
--- a/src/vpk/Velopack.Packaging.Windows/Commands/WindowsReleasifyOptions.cs
+++ b/src/vpk/Velopack.Packaging.Windows/Commands/WindowsReleasifyOptions.cs
@@ -1,4 +1,6 @@
-namespace Velopack.Packaging.Windows.Commands;
+using Velopack.Packaging.Compression;
+
+namespace Velopack.Packaging.Windows.Commands;
public class WindowsReleasifyOptions : WindowsSigningOptions
{
diff --git a/src/vpk/Velopack.Packaging/Abstractions/IPackOptions.cs b/src/vpk/Velopack.Packaging/Abstractions/IPackOptions.cs
index 9b2fb687..9656b261 100644
--- a/src/vpk/Velopack.Packaging/Abstractions/IPackOptions.cs
+++ b/src/vpk/Velopack.Packaging/Abstractions/IPackOptions.cs
@@ -1,4 +1,6 @@
-namespace Velopack.Packaging.Abstractions;
+using Velopack.Packaging.Compression;
+
+namespace Velopack.Packaging.Abstractions;
public interface IPackOptions : INugetPackCommand, IPlatformOptions
{
diff --git a/src/vpk/Velopack.Packaging/Commands/DeltaGenCommandRunner.cs b/src/vpk/Velopack.Packaging/Commands/DeltaGenCommandRunner.cs
index cf7b93b6..1f45eff4 100644
--- a/src/vpk/Velopack.Packaging/Commands/DeltaGenCommandRunner.cs
+++ b/src/vpk/Velopack.Packaging/Commands/DeltaGenCommandRunner.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Logging;
using Velopack.Core.Abstractions;
+using Velopack.Packaging.Compression;
namespace Velopack.Packaging.Commands;
diff --git a/src/vpk/Velopack.Packaging/Commands/DeltaGenOptions.cs b/src/vpk/Velopack.Packaging/Commands/DeltaGenOptions.cs
index 92f00a2d..869aebf1 100644
--- a/src/vpk/Velopack.Packaging/Commands/DeltaGenOptions.cs
+++ b/src/vpk/Velopack.Packaging/Commands/DeltaGenOptions.cs
@@ -1,4 +1,5 @@
using Velopack.Core;
+using Velopack.Packaging.Compression;
namespace Velopack.Packaging.Commands;
diff --git a/src/vpk/Velopack.Packaging/Commands/DeltaPatchCommandRunner.cs b/src/vpk/Velopack.Packaging/Commands/DeltaPatchCommandRunner.cs
index 11bc3fad..02c1b835 100644
--- a/src/vpk/Velopack.Packaging/Commands/DeltaPatchCommandRunner.cs
+++ b/src/vpk/Velopack.Packaging/Commands/DeltaPatchCommandRunner.cs
@@ -1,7 +1,7 @@
using Microsoft.Extensions.Logging;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Core.Abstractions;
+using Velopack.Packaging.Compression;
using Velopack.Util;
namespace Velopack.Packaging.Commands;
diff --git a/src/vpk/Velopack.Packaging/Compression/BZip2Stream.cs b/src/vpk/Velopack.Packaging/Compression/BZip2Stream.cs
index e00bdebc..b0489be7 100644
--- a/src/vpk/Velopack.Packaging/Compression/BZip2Stream.cs
+++ b/src/vpk/Velopack.Packaging/Compression/BZip2Stream.cs
@@ -1,10 +1,8 @@
#nullable disable
-using System;
using System.Diagnostics.CodeAnalysis;
-using System.IO;
using System.IO.Compression;
-namespace Velopack.Compression
+namespace Velopack.Packaging.Compression
{
[ExcludeFromCodeCoverage]
internal sealed class BZip2Stream : Stream
diff --git a/src/vpk/Velopack.Packaging/Compression/BinaryPatchUtility.cs b/src/vpk/Velopack.Packaging/Compression/BinaryPatchUtility.cs
index 0df5d978..84999bef 100644
--- a/src/vpk/Velopack.Packaging/Compression/BinaryPatchUtility.cs
+++ b/src/vpk/Velopack.Packaging/Compression/BinaryPatchUtility.cs
@@ -1,13 +1,10 @@
#nullable disable
-using System;
using System.Diagnostics.CodeAnalysis;
-using System.IO;
using System.IO.Compression;
-using System.Threading;
// Adapted from https://github.com/LogosBible/bsdiff.net/blob/master/src/bsdiff/BinaryPatchUtility.cs
-namespace Velopack.Compression
+namespace Velopack.Packaging.Compression
{
/*
The original bsdiff.c source code (http://www.daemonology.net/bsdiff/) is
diff --git a/src/vpk/Velopack.Packaging/Compression/DeltaEmbedded.cs b/src/vpk/Velopack.Packaging/Compression/DeltaEmbedded.cs
index 86d871b0..83821e4b 100644
--- a/src/vpk/Velopack.Packaging/Compression/DeltaEmbedded.cs
+++ b/src/vpk/Velopack.Packaging/Compression/DeltaEmbedded.cs
@@ -1,8 +1,7 @@
using Microsoft.Extensions.Logging;
-using Velopack.Compression;
using Velopack.Core;
-namespace Velopack.Packaging;
+namespace Velopack.Packaging.Compression;
public class DeltaEmbedded
{
diff --git a/src/vpk/Velopack.Packaging/Compression/DeltaMode.cs b/src/vpk/Velopack.Packaging/Compression/DeltaMode.cs
index 78d4877b..7d0e0bb9 100644
--- a/src/vpk/Velopack.Packaging/Compression/DeltaMode.cs
+++ b/src/vpk/Velopack.Packaging/Compression/DeltaMode.cs
@@ -1,4 +1,4 @@
-namespace Velopack.Packaging;
+namespace Velopack.Packaging.Compression;
public enum DeltaMode
{
diff --git a/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs b/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
index 8083127c..733e0b5a 100644
--- a/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
+++ b/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
@@ -1,14 +1,11 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
+#nullable enable
using System.Text;
using System.Text.RegularExpressions;
using Velopack.Exceptions;
using Velopack.Logging;
using Velopack.Util;
-namespace Velopack.Compression
+namespace Velopack.Packaging.Compression
{
internal abstract class DeltaPackage
{
diff --git a/src/vpk/Velopack.Packaging/Compression/DeltaPackageBuilder.cs b/src/vpk/Velopack.Packaging/Compression/DeltaPackageBuilder.cs
index 8a8fb877..28ab8f80 100644
--- a/src/vpk/Velopack.Packaging/Compression/DeltaPackageBuilder.cs
+++ b/src/vpk/Velopack.Packaging/Compression/DeltaPackageBuilder.cs
@@ -1,12 +1,11 @@
using System.IO.MemoryMappedFiles;
using System.Text;
using Microsoft.Extensions.Logging;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Packaging.Exceptions;
using Velopack.Util;
-namespace Velopack.Packaging;
+namespace Velopack.Packaging.Compression;
public class DeltaPackageBuilder
{
diff --git a/src/vpk/Velopack.Packaging/Compression/DeltaUpdateExe.cs b/src/vpk/Velopack.Packaging/Compression/DeltaUpdateExe.cs
index 1d198367..d8597afd 100644
--- a/src/vpk/Velopack.Packaging/Compression/DeltaUpdateExe.cs
+++ b/src/vpk/Velopack.Packaging/Compression/DeltaUpdateExe.cs
@@ -1,9 +1,8 @@
-using System;
-using System.Diagnostics;
+using System.Diagnostics;
using Velopack.Logging;
using Velopack.Util;
-namespace Velopack.Compression
+namespace Velopack.Packaging.Compression
{
internal class DeltaUpdateExe : DeltaPackage
{
diff --git a/src/vpk/Velopack.Packaging/Compression/MsDeltaCompression.cs b/src/vpk/Velopack.Packaging/Compression/MsDeltaCompression.cs
index 29a3fdc0..4aee72ae 100644
--- a/src/vpk/Velopack.Packaging/Compression/MsDeltaCompression.cs
+++ b/src/vpk/Velopack.Packaging/Compression/MsDeltaCompression.cs
@@ -1,10 +1,10 @@
-using System;
+#nullable enable
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
-namespace Velopack.Compression
+namespace Velopack.Packaging.Compression
{
[ExcludeFromCodeCoverage]
[SupportedOSPlatform("windows")]
diff --git a/src/vpk/Velopack.Packaging/PackageBuilder.cs b/src/vpk/Velopack.Packaging/PackageBuilder.cs
index c5120f64..42607ef2 100644
--- a/src/vpk/Velopack.Packaging/PackageBuilder.cs
+++ b/src/vpk/Velopack.Packaging/PackageBuilder.cs
@@ -3,11 +3,11 @@ using System.Text.RegularExpressions;
using Markdig;
using Microsoft.Extensions.Logging;
using NuGet.Versioning;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Core.Abstractions;
using Velopack.NuGet;
using Velopack.Packaging.Abstractions;
+using Velopack.Packaging.Compression;
using Velopack.Util;
namespace Velopack.Packaging;
diff --git a/src/vpk/Velopack.Packaging/Zstd.cs b/src/vpk/Velopack.Packaging/Zstd.cs
index aadc82fe..7222193e 100644
--- a/src/vpk/Velopack.Packaging/Zstd.cs
+++ b/src/vpk/Velopack.Packaging/Zstd.cs
@@ -1,4 +1,5 @@
using Velopack.Core;
+using Velopack.Packaging.Compression;
using Velopack.Packaging.Exceptions;
namespace Velopack.Packaging;
diff --git a/src/vpk/Velopack.Vpk/Commands/Packaging/DeltaGenCommand.cs b/src/vpk/Velopack.Vpk/Commands/Packaging/DeltaGenCommand.cs
index 50e590df..4d3a71ff 100644
--- a/src/vpk/Velopack.Vpk/Commands/Packaging/DeltaGenCommand.cs
+++ b/src/vpk/Velopack.Vpk/Commands/Packaging/DeltaGenCommand.cs
@@ -1,5 +1,6 @@
using Velopack.Core;
using Velopack.Packaging;
+using Velopack.Packaging.Compression;
namespace Velopack.Vpk.Commands.Packaging;
diff --git a/src/vpk/Velopack.Vpk/Commands/Packaging/PackCommand.cs b/src/vpk/Velopack.Vpk/Commands/Packaging/PackCommand.cs
index 93f17dd5..a942abab 100644
--- a/src/vpk/Velopack.Vpk/Commands/Packaging/PackCommand.cs
+++ b/src/vpk/Velopack.Vpk/Commands/Packaging/PackCommand.cs
@@ -1,5 +1,6 @@
using Velopack.Packaging;
+using Velopack.Packaging.Compression;
namespace Velopack.Vpk.Commands.Packaging;
diff --git a/test/Velopack.CommandLine.Tests/Commands/WindowsCommandTests.cs b/test/Velopack.CommandLine.Tests/Commands/WindowsCommandTests.cs
index 7792a126..c9bdbb70 100644
--- a/test/Velopack.CommandLine.Tests/Commands/WindowsCommandTests.cs
+++ b/test/Velopack.CommandLine.Tests/Commands/WindowsCommandTests.cs
@@ -41,7 +41,7 @@ public abstract class ReleaseCommandTests : BaseCommandTests
string cli = GetRequiredDefaultOptions() + "--delta none";
ParseResult parseResult = command.ParseAndApply(cli);
- Assert.True(command.DeltaMode == Packaging.DeltaMode.None);
+ Assert.True(command.DeltaMode == Packaging.Compression.DeltaMode.None);
}
[Fact]
diff --git a/test/Velopack.Packaging.Tests/OsxPackTests.cs b/test/Velopack.Packaging.Tests/OsxPackTests.cs
index e84818d8..e69b8fbf 100644
--- a/test/Velopack.Packaging.Tests/OsxPackTests.cs
+++ b/test/Velopack.Packaging.Tests/OsxPackTests.cs
@@ -1,5 +1,4 @@
using System.Runtime.Versioning;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Util;
diff --git a/test/Velopack.Packaging.Tests/WindowsPackTests.cs b/test/Velopack.Packaging.Tests/WindowsPackTests.cs
index b7cb2818..af1e39f3 100644
--- a/test/Velopack.Packaging.Tests/WindowsPackTests.cs
+++ b/test/Velopack.Packaging.Tests/WindowsPackTests.cs
@@ -5,9 +5,9 @@ using System.Xml.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Win32;
using NuGet.Packaging;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Packaging.Commands;
+using Velopack.Packaging.Compression;
using Velopack.Packaging.Windows.Commands;
using Velopack.Util;
using Velopack.Vpk;
diff --git a/test/Velopack.Tests/SymbolicLinkTests.cs b/test/Velopack.Tests/SymbolicLinkTests.cs
index cc2fc866..75288892 100644
--- a/test/Velopack.Tests/SymbolicLinkTests.cs
+++ b/test/Velopack.Tests/SymbolicLinkTests.cs
@@ -1,7 +1,6 @@
using System.ComponentModel;
using System.IO.Compression;
using NCode.ReparsePoints;
-using Velopack.Compression;
using Velopack.Logging;
using Velopack.Util;
diff --git a/test/Velopack.Tests/UpdateManagerTests.cs b/test/Velopack.Tests/UpdateManagerTests.cs
index 75ca34ef..8816c322 100644
--- a/test/Velopack.Tests/UpdateManagerTests.cs
+++ b/test/Velopack.Tests/UpdateManagerTests.cs
@@ -1,6 +1,5 @@
using System.Text;
using NuGet.Versioning;
-using Velopack.Compression;
using Velopack.Core;
using Velopack.Exceptions;
using Velopack.Locators;
diff --git a/test/Velopack.Tests/ZipPackageTests.cs b/test/Velopack.Tests/ZipPackageTests.cs
index a16bc3da..9950b386 100644
--- a/test/Velopack.Tests/ZipPackageTests.cs
+++ b/test/Velopack.Tests/ZipPackageTests.cs
@@ -39,8 +39,8 @@ public class ZipPackageTests
SymbolicLink.Create(symlink, actual);
SymbolicLink.Create(symfile, actualFile);
- Compression.EasyZip.CreateZipFromDirectoryAsync(logger.ToVelopackLogger(), zipFile, tempDir).GetAwaiterResult();
- Compression.EasyZip.ExtractZipToDirectory(logger.ToVelopackLogger(), zipFile, extractedDir, expandSymlinks: true);
+ EasyZip.CreateZipFromDirectoryAsync(logger.ToVelopackLogger(), zipFile, tempDir).GetAwaiterResult();
+ EasyZip.ExtractZipToDirectory(logger.ToVelopackLogger(), zipFile, extractedDir, expandSymlinks: true);
Assert.True(File.Exists(Path.Combine(extractedDir, "actual", "file.txt")));
Assert.Equal("hello", File.ReadAllText(Path.Combine(extractedDir, "actual", "file.txt")));
From 5d99b7213bbfdb7b58429db7265da3303f5bb281 Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 20:22:32 +0100
Subject: [PATCH 35/64] Performance enhancements to delta process
---
Cargo.lock | 762 +++++++++++++++++++++++++++++++--
Cargo.toml | 4 +-
src/bins/Cargo.toml | 4 +-
src/bins/src/commands/patch.rs | 65 +--
4 files changed, 781 insertions(+), 54 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 6ce860fd..e0a50f91 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "addr2line"
+version = "0.24.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
+dependencies = [
+ "gimli",
+]
+
[[package]]
name = "adler2"
version = "2.0.0"
@@ -251,6 +260,27 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+[[package]]
+name = "backtrace"
+version = "0.3.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
+dependencies = [
+ "addr2line",
+ "cfg-if 1.0.0",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
[[package]]
name = "base64"
version = "0.22.1"
@@ -416,6 +446,16 @@ dependencies = [
"clap_derive",
]
+[[package]]
+name = "clap-verbosity-flag"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34c77f67047557f62582784fd7482884697731b2932c7d37ced54bce2312e1e2"
+dependencies = [
+ "clap",
+ "log",
+]
+
[[package]]
name = "clap_builder"
version = "4.5.38"
@@ -467,12 +507,35 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "console"
+version = "0.15.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
+dependencies = [
+ "encode_unicode",
+ "libc",
+ "once_cell",
+ "unicode-width",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "constant_time_eq"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+[[package]]
+name = "core-foundation"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "core-foundation"
version = "0.10.0"
@@ -522,6 +585,25 @@ dependencies = [
"cfg-if 1.0.0",
]
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
@@ -619,6 +701,27 @@ dependencies = [
"syn 2.0.98",
]
+[[package]]
+name = "derive_more"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
+dependencies = [
+ "derive_more-impl",
+]
+
+[[package]]
+name = "derive_more-impl"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+ "unicode-xid",
+]
+
[[package]]
name = "dialog"
version = "0.3.0"
@@ -678,6 +781,27 @@ dependencies = [
"syn 2.0.98",
]
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "encode_unicode"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
[[package]]
name = "enum-flags"
version = "0.4.0"
@@ -689,6 +813,19 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "env_logger"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
+dependencies = [
+ "humantime",
+ "is-terminal",
+ "log",
+ "regex",
+ "termcolor",
+]
+
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -773,6 +910,21 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
[[package]]
name = "form_urlencoded"
version = "1.2.1"
@@ -836,6 +988,33 @@ dependencies = [
"pin-project-lite",
]
+[[package]]
+name = "futures-sink"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+
+[[package]]
+name = "futures-task"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+
+[[package]]
+name = "futures-util"
+version = "0.3.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+dependencies = [
+ "futures-core",
+ "futures-io",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -881,6 +1060,12 @@ dependencies = [
"weezl",
]
+[[package]]
+name = "gimli"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
+
[[package]]
name = "glob"
version = "0.3.2"
@@ -899,6 +1084,25 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "h2"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http 0.2.12",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
[[package]]
name = "hashbrown"
version = "0.15.2"
@@ -923,6 +1127,12 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+[[package]]
+name = "hermit-abi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
+
[[package]]
name = "hmac"
version = "0.12.1"
@@ -932,6 +1142,17 @@ dependencies = [
"digest",
]
+[[package]]
+name = "http"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
[[package]]
name = "http"
version = "1.2.0"
@@ -943,12 +1164,72 @@ dependencies = [
"itoa",
]
+[[package]]
+name = "http-body"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
+dependencies = [
+ "bytes",
+ "http 0.2.12",
+ "pin-project-lite",
+]
+
[[package]]
name = "httparse"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a"
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "humantime"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
+
+[[package]]
+name = "hyper"
+version = "0.14.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http 0.2.12",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+dependencies = [
+ "bytes",
+ "hyper",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+]
+
[[package]]
name = "iana-time-zone"
version = "0.1.61"
@@ -1143,6 +1424,19 @@ dependencies = [
"hashbrown",
]
+[[package]]
+name = "indicatif"
+version = "0.17.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235"
+dependencies = [
+ "console",
+ "number_prefix",
+ "portable-atomic",
+ "unicode-width",
+ "web-time",
+]
+
[[package]]
name = "inout"
version = "0.1.4"
@@ -1152,12 +1446,38 @@ dependencies = [
"generic-array",
]
+[[package]]
+name = "ipnet"
+version = "2.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
+
+[[package]]
+name = "is-terminal"
+version = "0.4.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
+dependencies = [
+ "hermit-abi 0.5.1",
+ "libc",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
version = "1.0.14"
@@ -1324,6 +1644,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
[[package]]
name = "miniz_oxide"
version = "0.8.5"
@@ -1334,6 +1660,45 @@ dependencies = [
"simd-adler32",
]
+[[package]]
+name = "mio"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
+dependencies = [
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "mtzip"
+version = "4.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6c6cb282455a4f5495359ca3f6b6c3c95b3f5bbb598fce39fbd7ed7877eb9aa"
+dependencies = [
+ "cfg-if 1.0.0",
+ "derive_more",
+ "flate2",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
+dependencies = [
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
[[package]]
name = "neon"
version = "1.0.0"
@@ -1437,12 +1802,71 @@ dependencies = [
"libc",
]
+[[package]]
+name = "number_prefix"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
+
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "once_cell"
version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
+[[package]]
+name = "openssl"
+version = "0.10.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
+dependencies = [
+ "bitflags 2.9.0",
+ "cfg-if 1.0.0",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.108"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
[[package]]
name = "os_info"
version = "3.11.0"
@@ -1526,13 +1950,19 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
dependencies = [
"cfg-if 1.0.0",
"concurrent-queue",
- "hermit-abi",
+ "hermit-abi 0.4.0",
"pin-project-lite",
"rustix 0.38.44",
"tracing",
"windows-sys 0.59.0",
]
+[[package]]
+name = "portable-atomic"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+
[[package]]
name = "powerfmt"
version = "0.2.0"
@@ -1585,6 +2015,12 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "progress-streams"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e965d96c8162c607b0cd8d66047ad3c9fd35273c134d994327882c6e47f986a7"
+
[[package]]
name = "quote"
version = "1.0.38"
@@ -1624,6 +2060,32 @@ dependencies = [
"zerocopy 0.8.20",
]
+[[package]]
+name = "ranges"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350932f7e8b2d0333d2537f42671a837473576c00e128fbee84c819ea08783b5"
+
+[[package]]
+name = "rayon"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
[[package]]
name = "redox_users"
version = "0.4.6"
@@ -1679,6 +2141,46 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "reqwest"
+version = "0.11.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
+dependencies = [
+ "base64 0.21.7",
+ "bytes",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http 0.2.12",
+ "http-body",
+ "hyper",
+ "hyper-tls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "native-tls",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustls-pemfile 1.0.4",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "system-configuration",
+ "tokio",
+ "tokio-native-tls",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg",
+]
+
[[package]]
name = "ring"
version = "0.17.11"
@@ -1693,6 +2195,30 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "ripunzip"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b740f0bf490e13df680ff72bde3a5c4a2d9262edb651cbe650a2532af20b9baf"
+dependencies = [
+ "anyhow",
+ "clap",
+ "clap-verbosity-flag",
+ "env_logger",
+ "indicatif",
+ "itertools",
+ "log",
+ "progress-streams",
+ "ranges",
+ "rayon",
+ "regex",
+ "reqwest",
+ "tempfile",
+ "thiserror 1.0.69",
+ "wildmatch",
+ "zip",
+]
+
[[package]]
name = "rpassword"
version = "2.1.0"
@@ -1704,6 +2230,12 @@ dependencies = [
"winapi 0.2.8",
]
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
[[package]]
name = "rustix"
version = "0.38.44"
@@ -1745,6 +2277,15 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "rustls-pemfile"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
+dependencies = [
+ "base64 0.21.7",
+]
+
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
@@ -1792,6 +2333,38 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "schannel"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "security-framework"
+version = "2.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
+dependencies = [
+ "bitflags 2.9.0",
+ "core-foundation 0.9.4",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "semver"
version = "1.0.26"
@@ -1845,6 +2418,18 @@ dependencies = [
"serde",
]
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
[[package]]
name = "sha1"
version = "0.10.6"
@@ -1920,6 +2505,16 @@ version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
+[[package]]
+name = "socket2"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
@@ -1960,15 +2555,6 @@ dependencies = [
"syn 2.0.98",
]
-[[package]]
-name = "substring"
-version = "1.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86"
-dependencies = [
- "autocfg",
-]
-
[[package]]
name = "subtle"
version = "2.6.1"
@@ -2008,6 +2594,12 @@ dependencies = [
"syn 2.0.98",
]
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
[[package]]
name = "synstructure"
version = "0.13.1"
@@ -2019,6 +2611,27 @@ dependencies = [
"syn 2.0.98",
]
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation 0.9.4",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "tempfile"
version = "3.20.0"
@@ -2135,6 +2748,44 @@ dependencies = [
"zerovec",
]
+[[package]]
+name = "tokio"
+version = "1.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
+dependencies = [
+ "backtrace",
+ "bytes",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "toml"
version = "0.5.11"
@@ -2178,6 +2829,12 @@ dependencies = [
"winnow",
]
+[[package]]
+name = "tower-service"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
+
[[package]]
name = "tracing"
version = "0.1.41"
@@ -2193,6 +2850,15 @@ name = "tracing-core"
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ts-rs"
@@ -2229,6 +2895,18 @@ version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
+[[package]]
+name = "unicode-width"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
+
[[package]]
name = "untrusted"
version = "0.9.0"
@@ -2241,12 +2919,12 @@ version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7a3e9af6113ecd57b8c63d3cd76a385b2e3881365f1f489e54f49801d0c83ea"
dependencies = [
- "base64",
+ "base64 0.22.1",
"flate2",
"log",
"percent-encoding",
"rustls",
- "rustls-pemfile",
+ "rustls-pemfile 2.2.0",
"rustls-pki-types",
"ureq-proto",
"utf-8",
@@ -2259,8 +2937,8 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fadf18427d33828c311234884b7ba2afb57143e6e7e69fda7ee883b624661e36"
dependencies = [
- "base64",
- "http",
+ "base64 0.22.1",
+ "http 1.2.0",
"httparse",
"log",
]
@@ -2328,6 +3006,12 @@ version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
[[package]]
name = "velopack"
version = "0.0.0-local"
@@ -2370,7 +3054,7 @@ dependencies = [
"bitflags 2.9.1",
"chrono",
"clap",
- "core-foundation",
+ "core-foundation 0.10.0",
"core-foundation-sys",
"derivative",
"dialog",
@@ -2385,6 +3069,7 @@ dependencies = [
"log",
"log-panics",
"memmap2",
+ "mtzip",
"normpath",
"ntest",
"os_info",
@@ -2393,6 +3078,7 @@ dependencies = [
"rand",
"regex",
"remove_dir_all",
+ "ripunzip",
"same-file",
"semver",
"sha1_smol",
@@ -2400,7 +3086,6 @@ dependencies = [
"simplelog",
"strsim 0.11.1",
"strum",
- "substring",
"tempfile",
"time 0.3.41",
"velopack",
@@ -2412,7 +3097,6 @@ dependencies = [
"winres",
"winsafe",
"zip",
- "zip-extensions",
"zstd",
]
@@ -2480,6 +3164,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "want"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
+dependencies = [
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
@@ -2582,6 +3275,16 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "web-time"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
[[package]]
name = "webpki-roots"
version = "0.26.8"
@@ -2608,6 +3311,12 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
+[[package]]
+name = "wildmatch"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd"
+
[[package]]
name = "winapi"
version = "0.2.8"
@@ -2918,6 +3627,16 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "winreg"
+version = "0.50.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
+dependencies = [
+ "cfg-if 1.0.0",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "winres"
version = "0.1.12"
@@ -3140,15 +3859,6 @@ dependencies = [
"zstd",
]
-[[package]]
-name = "zip-extensions"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79cdbf826e5a6eec81fc5a0d33cd7c09c31fd8f9918f15434f74c42d39ef337a"
-dependencies = [
- "zip",
-]
-
[[package]]
name = "zopfli"
version = "0.8.1"
diff --git a/Cargo.toml b/Cargo.toml
index 69113a48..db2b7135 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -35,7 +35,6 @@ glob = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0" }
zip = { version = "2.6", default-features = false, features = ["deflate"] }
-zip-extensions = "0.8.2"
thiserror = "2.0"
lazy_static = "1.5"
regex = "1.10"
@@ -85,7 +84,8 @@ core-foundation = "0.10"
core-foundation-sys = "0.8"
uuid = { version = "1.13.1", features = ["v4", "fast-rng", "macro-diagnostics"] }
walkdir = "2.5"
-substring = " 1.4"
+mtzip = "=4.0.2"
+ripunzip = "2.0.2"
# default to small, optimized workspace release binaries
[profile.release]
diff --git a/src/bins/Cargo.toml b/src/bins/Cargo.toml
index 76427c28..e5ef1894 100644
--- a/src/bins/Cargo.toml
+++ b/src/bins/Cargo.toml
@@ -65,10 +65,10 @@ enum-flags.workspace = true
log-panics.workspace = true
zstd.workspace = true
zip.workspace = true
-zip-extensions.workspace = true
walkdir.workspace = true
sha1_smol.workspace = true
-substring.workspace = true
+mtzip.workspace = true
+ripunzip.workspace = true
[target.'cfg(target_os="linux")'.dependencies]
waitpid-any.workspace = true
diff --git a/src/bins/src/commands/patch.rs b/src/bins/src/commands/patch.rs
index c5d1acbe..8be29c3f 100644
--- a/src/bins/src/commands/patch.rs
+++ b/src/bins/src/commands/patch.rs
@@ -1,4 +1,6 @@
use anyhow::{anyhow, bail, Result};
+use mtzip::level::CompressionLevel;
+use ripunzip::{NullProgressReporter, UnzipEngine, UnzipOptions};
use std::os::windows::fs::MetadataExt;
use std::{
collections::HashSet,
@@ -6,8 +8,6 @@ use std::{
path::{Path, PathBuf},
};
use walkdir::WalkDir;
-use zip::{write::SimpleFileOptions, CompressionMethod};
-use zip_extensions::{zip_create_from_directory_with_options, zip_extract};
pub fn zstd_patch_single, P2: AsRef, P3: AsRef>(old_file: P1, patch_file: P2, output_file: P3) -> Result<()> {
let old_file = old_file.as_ref();
@@ -54,6 +54,22 @@ fn fio_highbit64(v: u64) -> u32 {
return count;
}
+fn zip_extract, P2: AsRef>(archive_file: P1, target_dir: P2) -> Result<()> {
+ let target_dir = target_dir.as_ref().to_path_buf();
+ let file = fs::File::open(archive_file)?;
+ let engine = UnzipEngine::for_file(file)?;
+ let null_progress = Box::new(NullProgressReporter {});
+ let options = UnzipOptions {
+ filename_filter: None,
+ progress_reporter: null_progress,
+ output_directory: Some(target_dir),
+ password: None,
+ single_threaded: false,
+ };
+ engine.unzip(options)?;
+ Ok(())
+}
+
pub fn delta, P2: AsRef, P3: AsRef>(
old_file: P1,
delta_files: Vec<&PathBuf>,
@@ -93,15 +109,7 @@ pub fn delta, P2: AsRef, P3: AsRef>(
fs::create_dir_all(&delta_dir)?;
zip_extract(delta_file, &delta_dir)?;
- let delta_relative_paths: Vec = WalkDir::new(&delta_dir)
- .follow_links(false)
- .into_iter()
- .filter_map(|entry| entry.ok())
- .filter(|entry| entry.file_type().is_file())
- .map(|entry| entry.path().strip_prefix(&delta_dir).map(|p| p.to_path_buf()))
- .filter_map(|entry| entry.ok())
- .collect();
-
+ let delta_relative_paths = enumerate_files_relative(&delta_dir);
let mut visited_paths = HashSet::new();
// apply all the zsdiff patches for files which exist in both the delta and the base package
@@ -153,15 +161,7 @@ pub fn delta, P2: AsRef, P3: AsRef>(
}
// anything in the work dir which was not visited is an old / deleted file and should be removed
- let workdir_relative_paths: Vec = WalkDir::new(&work_dir)
- .follow_links(false)
- .into_iter()
- .filter_map(|entry| entry.ok())
- .filter(|entry| entry.file_type().is_file())
- .map(|entry| entry.path().strip_prefix(&work_dir).map(|p| p.to_path_buf()))
- .filter_map(|entry| entry.ok())
- .collect();
-
+ let workdir_relative_paths = enumerate_files_relative(&work_dir);
for relative_path in &workdir_relative_paths {
if !visited_paths.contains(relative_path) {
let file_to_delete = work_dir.join(relative_path);
@@ -173,15 +173,32 @@ pub fn delta, P2: AsRef, P3: AsRef>(
info!("All delta patches applied. Asembling output package at: {}", output_file.to_string_lossy());
- // NOTE: zstd is not supported by older versions of Squirrel/Velopack, but
- // it's assumed if someone is using this code, they are using a recent enough version
- let options = SimpleFileOptions::default().compression_method(CompressionMethod::Zstd);
- zip_create_from_directory_with_options(&output_file, &work_dir, |_| options)?;
+ let mut zipper = mtzip::ZipArchive::new();
+ let workdir_relative_paths = enumerate_files_relative(&work_dir);
+ for relative_path in &workdir_relative_paths {
+ zipper
+ .add_file_from_fs(work_dir.join(&relative_path), relative_path.to_string_lossy().to_string())
+ .compression_level(CompressionLevel::fast())
+ .done();
+ }
+ let mut file = fs::File::create(&output_file)?;
+ zipper.write(&mut file)?;
info!("Successfully applied {} delta patches in {}s.", delta_files.len(), time.s());
Ok(())
}
+fn enumerate_files_relative>(dir: P) -> Vec {
+ WalkDir::new(&dir)
+ .follow_links(false)
+ .into_iter()
+ .filter_map(|entry| entry.ok())
+ .filter(|entry| entry.file_type().is_file())
+ .map(|entry| entry.path().strip_prefix(&dir).map(|p| p.to_path_buf()))
+ .filter_map(|entry| entry.ok())
+ .collect()
+}
+
// NOTE: this is some code to do checksum verification, but it is not being used
// by the current implementation because zstd patching already has checksum verification
//
From 6b08ff0a21767b353aaaf349859d4940e479dd6e Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Tue, 13 May 2025 20:25:11 +0100
Subject: [PATCH 36/64] Refactor code and add tests
---
src/lib-csharp/Sources/GitBase.cs | 2 +-
src/lib-csharp/Sources/IUpdateSource.cs | 2 +-
src/lib-csharp/UpdateManager.cs | 10 +-
src/vpk/Velopack.Build/MSBuildLogger.cs | 53 +-
src/vpk/Velopack.Build/PackTask.cs | 8 +-
src/vpk/Velopack.Build/PublishTask.cs | 4 +-
src/vpk/Velopack.Core/LoggerConsole.cs | 55 ++
.../Velopack.Core}/ReleaseEntry.cs | 4 +-
.../Compression/DeltaPackage.cs | 1 +
.../DeltaPackageTests.cs | 674 +++++++++---------
test/Velopack.Tests/ReleaseEntryTests.cs | 1 +
11 files changed, 404 insertions(+), 410 deletions(-)
create mode 100644 src/vpk/Velopack.Core/LoggerConsole.cs
rename src/{lib-csharp => vpk/Velopack.Core}/ReleaseEntry.cs (98%)
diff --git a/src/lib-csharp/Sources/GitBase.cs b/src/lib-csharp/Sources/GitBase.cs
index b13015e2..5641dc61 100644
--- a/src/lib-csharp/Sources/GitBase.cs
+++ b/src/lib-csharp/Sources/GitBase.cs
@@ -111,7 +111,7 @@ namespace Velopack.Sources
protected abstract string GetAssetUrlFromName(T release, string assetName);
///
- /// Provides a wrapper around which also contains a Git Release.
+ /// Provides a wrapper around which also contains a Git Release.
///
protected internal record GitBaseAsset : VelopackAsset
{
diff --git a/src/lib-csharp/Sources/IUpdateSource.cs b/src/lib-csharp/Sources/IUpdateSource.cs
index c25c5bdd..ad43e963 100644
--- a/src/lib-csharp/Sources/IUpdateSource.cs
+++ b/src/lib-csharp/Sources/IUpdateSource.cs
@@ -27,7 +27,7 @@ namespace Velopack.Sources
/// metadata from this package may be provided to the remote server (such as package id,
/// or cpu architecture) to ensure that the correct package is downloaded for this user.
///
- /// An array of objects that are available for download
+ /// An array of objects that are available for download
/// and are applicable to this user.
Task GetReleaseFeed(IVelopackLogger logger, string? appId, string channel, Guid? stagingId = null, VelopackAsset? latestLocalRelease = null);
diff --git a/src/lib-csharp/UpdateManager.cs b/src/lib-csharp/UpdateManager.cs
index 7e1e7f76..1f2733f9 100644
--- a/src/lib-csharp/UpdateManager.cs
+++ b/src/lib-csharp/UpdateManager.cs
@@ -169,7 +169,6 @@ namespace Velopack
}
EnsureInstalled();
- var installedVer = CurrentVersion!;
var matchingRemoteDelta = feed.Where(r => r.Type == VelopackAssetType.Delta && r.Version == latestRemoteFull.Version).FirstOrDefault();
if (matchingRemoteDelta == null) {
@@ -328,7 +327,7 @@ namespace Velopack
async x => {
var targetFile = Locator.GetLocalPackagePath(x);
double component = 0;
- Log.Debug($"Downloading delta version {x.Version}");
+ Log.Info($"Downloading delta {x.Version}");
await Source.DownloadReleaseEntry(
Log,
x,
@@ -347,7 +346,8 @@ namespace Velopack
Log.Debug($"Download complete for delta version {x.Version}");
}).ConfigureAwait(false);
- Log.Info("All delta packages downloaded and verified, applying them to the base now.");
+ Log.Info("All delta packages downloaded and verified.");
+ Log.Info($"Applying {releasesToDownload.Length} patches to {updates.BaseRelease?.FileName}.");
// applying deltas accounts for 70%-100% of progress
var baseFile = Locator.GetLocalPackagePath(updates.BaseRelease!);
@@ -365,10 +365,10 @@ namespace Velopack
}
var psi = new ProcessStartInfo(updateExe);
- psi.AppendArgumentListSafe(args, out var _);
+ psi.AppendArgumentListSafe(args, out _);
psi.CreateNoWindow = true;
var p = psi.StartRedirectOutputToILogger(Log, VelopackLogLevel.Debug);
- if (!p.WaitForExit((int)TimeSpan.FromMinutes(5).TotalMilliseconds)) {
+ if (!p.WaitForExit((int) TimeSpan.FromMinutes(5).TotalMilliseconds)) {
p.Kill();
throw new TimeoutException("patch process timed out (5min).");
}
diff --git a/src/vpk/Velopack.Build/MSBuildLogger.cs b/src/vpk/Velopack.Build/MSBuildLogger.cs
index 8bc63207..1c40d2c0 100644
--- a/src/vpk/Velopack.Build/MSBuildLogger.cs
+++ b/src/vpk/Velopack.Build/MSBuildLogger.cs
@@ -10,7 +10,7 @@ using Task = System.Threading.Tasks.Task;
namespace Velopack.Build;
-public class MSBuildLogger(TaskLoggingHelper loggingHelper) : ILogger, IFancyConsole, IFancyConsoleProgress
+public class MSBuildLogger(TaskLoggingHelper loggingHelper) : ILogger
{
private TaskLoggingHelper LoggingHelper { get; } = loggingHelper;
@@ -19,31 +19,6 @@ public class MSBuildLogger(TaskLoggingHelper loggingHelper) : ILogger, IFancyCon
throw new NotImplementedException();
}
- public async Task ExecuteProgressAsync(Func action)
- {
- await action(this).ConfigureAwait(false);
- }
-
- public async Task RunTask(string name, Func, Task> fn)
- {
- try {
- await fn(x => { }).ConfigureAwait(false);
- } catch (Exception ex) {
- this.LogError(ex, "Error running task {taskName}", name);
- throw;
- }
- }
-
- public async Task RunTask(string name, Func, Task> fn)
- {
- try {
- return await fn(x => { }).ConfigureAwait(false);
- } catch (Exception ex) {
- this.LogError(ex, "Error running task {taskName}", name);
- throw;
- }
- }
-
public bool IsEnabled(LogLevel logLevel)
{
return logLevel switch {
@@ -60,6 +35,7 @@ public class MSBuildLogger(TaskLoggingHelper loggingHelper) : ILogger, IFancyCon
if (exception != null) {
message += " " + exception.Message;
}
+
switch (logLevel) {
case LogLevel.Trace:
LoggingHelper.LogMessage(MessageImportance.Low, message);
@@ -79,27 +55,4 @@ public class MSBuildLogger(TaskLoggingHelper loggingHelper) : ILogger, IFancyCon
break;
}
}
-
- public void WriteTable(string tableName, IEnumerable> rows, bool hasHeaderRow = true)
- {
- LoggingHelper.LogMessage(tableName);
- foreach (var row in rows) {
- LoggingHelper.LogMessage(" " + String.Join(" ", row));
- }
- }
-
- public System.Threading.Tasks.Task PromptYesNo(string prompt, bool? defaultValue = null, TimeSpan? timeout = null)
- {
- return Task.FromResult(true);
- }
-
- public void WriteLine(string text = "")
- {
- Log(LogLevel.Information, 0, null, null, (object? state, Exception? exception) => text);
- }
-
- public string EscapeMarkup(string text)
- {
- return text;
- }
-}
+}
\ No newline at end of file
diff --git a/src/vpk/Velopack.Build/PackTask.cs b/src/vpk/Velopack.Build/PackTask.cs
index 62989c8d..02644dd7 100644
--- a/src/vpk/Velopack.Build/PackTask.cs
+++ b/src/vpk/Velopack.Build/PackTask.cs
@@ -4,6 +4,7 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
+using Velopack.Core;
using Velopack.Packaging;
using Velopack.Packaging.Unix.Commands;
using Velopack.Packaging.Windows.Commands;
@@ -105,6 +106,7 @@ public class PackTask : MSBuildAsyncTask
{
//System.Diagnostics.Debugger.Launch();
try {
+ var console = new LoggerConsole(Logger);
HelperFile.ClearSearchPaths();
var searchPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "..", "..", "vendor"));
HelperFile.AddSearchPath(searchPath);
@@ -132,15 +134,15 @@ public class PackTask : MSBuildAsyncTask
#pragma warning restore CS0618 // Type or member is obsolete
}
- var runner = new WindowsPackCommandRunner(Logger, Logger);
+ var runner = new WindowsPackCommandRunner(Logger, console);
await runner.Run(options).ConfigureAwait(false);
} else if (VelopackRuntimeInfo.IsOSX) {
var options = this.ToOsxPackOptions();
- var runner = new OsxPackCommandRunner(Logger, Logger);
+ var runner = new OsxPackCommandRunner(Logger, console);
await runner.Run(options).ConfigureAwait(false);
} else if (VelopackRuntimeInfo.IsLinux) {
var options = this.ToLinuxPackOptions();
- var runner = new LinuxPackCommandRunner(Logger, Logger);
+ var runner = new LinuxPackCommandRunner(Logger, console);
await runner.Run(options).ConfigureAwait(false);
} else {
throw new NotSupportedException("Unsupported OS platform: " + VelopackRuntimeInfo.SystemOs.GetOsLongName());
diff --git a/src/vpk/Velopack.Build/PublishTask.cs b/src/vpk/Velopack.Build/PublishTask.cs
index 19cb32d2..634730d7 100644
--- a/src/vpk/Velopack.Build/PublishTask.cs
+++ b/src/vpk/Velopack.Build/PublishTask.cs
@@ -3,6 +3,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Extensions.Logging;
+using Velopack.Core;
using Velopack.Flow;
namespace Velopack.Build;
@@ -44,7 +45,8 @@ public class PublishTask : MSBuildAsyncTask
AllowInteractiveLogin = false,
};
- var client = new VelopackFlowServiceClient(options, Logger, Logger);
+ var console = new LoggerConsole(Logger);
+ var client = new VelopackFlowServiceClient(options, Logger, console);
if (!await client.LoginAsync(loginOptions, false, cancellationToken).ConfigureAwait(false)) {
Logger.LogWarning("Not logged into Velopack Flow service, skipping publish. Please run vpk login.");
return true;
diff --git a/src/vpk/Velopack.Core/LoggerConsole.cs b/src/vpk/Velopack.Core/LoggerConsole.cs
new file mode 100644
index 00000000..4e566739
--- /dev/null
+++ b/src/vpk/Velopack.Core/LoggerConsole.cs
@@ -0,0 +1,55 @@
+using Microsoft.Extensions.Logging;
+using Velopack.Core.Abstractions;
+
+namespace Velopack.Core;
+
+public class LoggerConsole(ILogger log) : IFancyConsole, IFancyConsoleProgress
+{
+ public async Task ExecuteProgressAsync(Func action)
+ {
+ await action(this).ConfigureAwait(false);
+ }
+
+ public async Task RunTask(string name, Func, Task> fn)
+ {
+ try {
+ await fn(x => { }).ConfigureAwait(false);
+ } catch (Exception ex) {
+ log.LogError(ex, "Error running task {taskName}", name);
+ throw;
+ }
+ }
+
+ public async Task RunTask(string name, Func, Task> fn)
+ {
+ try {
+ return await fn(x => { }).ConfigureAwait(false);
+ } catch (Exception ex) {
+ log.LogError(ex, "Error running task {taskName}", name);
+ throw;
+ }
+ }
+
+ public void WriteTable(string tableName, IEnumerable> rows, bool hasHeaderRow = true)
+ {
+ log.LogInformation(tableName);
+ foreach (var row in rows) {
+ log.LogInformation(" " + String.Join(" ", row));
+ }
+ }
+
+ public Task PromptYesNo(string prompt, bool? defaultValue = null, TimeSpan? timeout = null)
+ {
+ return Task.FromResult(true);
+ }
+
+ public void WriteLine(string text = "")
+ {
+ log.LogInformation(text);
+ }
+
+ public string EscapeMarkup(string text)
+ {
+ return text;
+ }
+}
\ No newline at end of file
diff --git a/src/lib-csharp/ReleaseEntry.cs b/src/vpk/Velopack.Core/ReleaseEntry.cs
similarity index 98%
rename from src/lib-csharp/ReleaseEntry.cs
rename to src/vpk/Velopack.Core/ReleaseEntry.cs
index 1a525b9f..04388ec3 100644
--- a/src/lib-csharp/ReleaseEntry.cs
+++ b/src/vpk/Velopack.Core/ReleaseEntry.cs
@@ -13,7 +13,7 @@ using System.Threading.Tasks;
using NuGet.Versioning;
using Velopack.Util;
-namespace Velopack
+namespace Velopack.Core
{
///
/// Describes the requested release notes text format.
@@ -146,7 +146,7 @@ namespace Velopack
///
/// Create a new instance of .
///
- protected internal ReleaseEntry(string sha1, string filename, long filesize, string baseUrl = null, string query = null, float? stagingPercentage = null)
+ public ReleaseEntry(string sha1, string filename, long filesize, string baseUrl = null, string query = null, float? stagingPercentage = null)
{
Contract.Requires(sha1 != null && sha1.Length == 40);
Contract.Requires(filename != null);
diff --git a/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs b/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
index 733e0b5a..11d9a8ae 100644
--- a/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
+++ b/src/vpk/Velopack.Packaging/Compression/DeltaPackage.cs
@@ -1,6 +1,7 @@
#nullable enable
using System.Text;
using System.Text.RegularExpressions;
+using Velopack.Core;
using Velopack.Exceptions;
using Velopack.Logging;
using Velopack.Util;
diff --git a/test/Velopack.Packaging.Tests/DeltaPackageTests.cs b/test/Velopack.Packaging.Tests/DeltaPackageTests.cs
index b982952c..d09d4010 100644
--- a/test/Velopack.Packaging.Tests/DeltaPackageTests.cs
+++ b/test/Velopack.Packaging.Tests/DeltaPackageTests.cs
@@ -1,347 +1,327 @@
-//using System;
-//using System.Collections.Generic;
-//using System.IO;
-//using System.Linq;
-//using System.Threading.Tasks;
-//using Squirrel.NuGet;
-//using Squirrel;
-//using Squirrel.SimpleSplat;
-//using Squirrel.Tests.TestHelpers;
-//using Xunit;
-//using Xunit.Abstractions;
-//using NuGet.Versioning;
-//using Squirrel.CommandLine;
-
-//namespace Squirrel.Tests
-//{
-// public class ApplyDeltaPackageTests : TestLoggingBase
-// {
-// public ApplyDeltaPackageTests(ITestOutputHelper log) : base(log)
-// {
-// }
-
-// [Fact]
-// public void ApplyDeltaPackageSmokeTest()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.0.0.0-full.nupkg");
-// var deltaPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.1.0.0-delta.nupkg");
-// var expectedPackageFile = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.1.0.0-full.nupkg");
-// var outFile = Path.GetTempFileName() + ".nupkg";
-
-// try {
-// var deltaBuilder = new DeltaPackage();
-// deltaBuilder.ApplyDeltaPackage(basePackage, deltaPackage, outFile);
-
-// var result = new ZipPackage(outFile);
-// var expected = new ZipPackage(expectedPackageFile);
-
-// result.Id.ShouldEqual(expected.Id);
-// result.Version.ShouldEqual(expected.Version);
-
-// this.Log().Info("Expected file list:");
-// var expectedList = expected.Files.Select(x => x.Path).OrderBy(x => x).ToList();
-// expectedList.ForEach(x => this.Log().Info(x));
-
-// this.Log().Info("Actual file list:");
-// var actualList = result.Files.Select(x => x.Path).OrderBy(x => x).ToList();
-// actualList.ForEach(x => this.Log().Info(x));
-
-// Enumerable.Zip(expectedList, actualList, (e, a) => e == a)
-// .All(x => x != false)
-// .ShouldBeTrue();
-// } finally {
-// if (File.Exists(outFile)) {
-// File.Delete(outFile);
-// }
-// }
-// }
-
-// [Fact]
-// public void ApplyDeltaWithBothBsdiffAndNormalDiffDoesntFail()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "slack-1.1.8-full.nupkg");
-// var deltaPackage = IntegrationTestHelper.GetPath("fixtures", "slack-1.2.0-delta.nupkg");
-// var outFile = Path.GetTempFileName() + ".nupkg";
-
-// try {
-// var deltaBuilder = new DeltaPackage();
-// deltaBuilder.ApplyDeltaPackage(basePackage, deltaPackage, outFile);
-
-// var result = new ZipPackage(outFile);
-
-// result.Id.ShouldEqual("slack");
-// result.Version.ShouldEqual(SemanticVersion.Parse("1.2.0"));
-// } finally {
-// if (File.Exists(outFile)) {
-// File.Delete(outFile);
-// }
-// }
-// }
-
-// [Fact]
-// public void ApplyMultipleDeltasFast()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Clowd-3.4.287-full.nupkg");
-// var deltaPackage1 = IntegrationTestHelper.GetPath("fixtures", "Clowd-3.4.288-delta.nupkg");
-// var deltaPackage2 = IntegrationTestHelper.GetPath("fixtures", "Clowd-3.4.291-delta.nupkg");
-// var deltaPackage3 = IntegrationTestHelper.GetPath("fixtures", "Clowd-3.4.292-delta.nupkg");
-
-// using var t1 = Utility.GetTempDirectory(out var appDir);
-// using var t2 = Utility.GetTempDirectory(out var updateDir);
-
-// using var um = UpdateManagerTestImpl.FromLocalPackageTempDir(updateDir, "theApp", appDir);
-// var pkgDir = um.Config.PackagesDir;
-
-// File.Copy(basePackage, Path.Combine(pkgDir, Path.GetFileName(basePackage)));
-// File.Copy(deltaPackage1, Path.Combine(pkgDir, Path.GetFileName(deltaPackage1)));
-// File.Copy(deltaPackage2, Path.Combine(pkgDir, Path.GetFileName(deltaPackage2)));
-// File.Copy(deltaPackage3, Path.Combine(pkgDir, Path.GetFileName(deltaPackage3)));
-
-// var baseEntry = ReleaseEntry.GenerateFromFile(basePackage);
-
-// var toApply = new [] {
-// ReleaseEntry.GenerateFromFile(deltaPackage1),
-// ReleaseEntry.GenerateFromFile(deltaPackage2),
-// ReleaseEntry.GenerateFromFile(deltaPackage3),
-// };
-
-// List progress = new List();
-
-// var newEntry = um.createFullPackagesFromDeltas(toApply, baseEntry, progress.Add);
-
-// var outFile = Path.Combine(pkgDir, newEntry.Filename);
-// var result = new ZipPackage(outFile);
-// result.Id.ShouldEqual("Clowd");
-// result.Version.ShouldEqual(SemanticVersion.Parse("3.4.292"));
-// }
-
-// [Fact(Skip = "Rewrite this test, the original uses too many heavyweight fixtures")]
-// public void ApplyMultipleDeltaPackagesGeneratesCorrectHash()
-// {
-// Assert.Fail("Rewrite this test, the original uses too many heavyweight fixtures");
-// }
-// }
-
-// public class CreateDeltaPackageTests : IEnableLogger
-// {
-// [Fact]
-// public void CreateDeltaPackageIntegrationTest()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
-// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
-
-// var baseFixture = new ReleasePackageBuilder(basePackage);
-// var fixture = new ReleasePackageBuilder(newPackage);
-
-// var tempFiles = Enumerable.Range(0, 3)
-// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
-// .ToArray();
-
-// try {
-// baseFixture.CreateReleasePackage(tempFiles[0]);
-// fixture.CreateReleasePackage(tempFiles[1]);
-
-// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-
-// var deltaBuilder = new DeltaPackageBuilder();
-// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
-
-// var fullPkg = new ZipPackage(tempFiles[1]);
-// var deltaPkg = new ZipPackage(tempFiles[2]);
-
-// //
-// // Package Checks
-// //
-
-// fullPkg.Id.ShouldEqual(deltaPkg.Id);
-// fullPkg.Version.CompareTo(deltaPkg.Version).ShouldEqual(0);
-
-// // Delta packages should be smaller than the original!
-// var fileInfos = tempFiles.Select(x => new FileInfo(x)).ToArray();
-// this.Log().Info("Base Size: {0}, Current Size: {1}, Delta Size: {2}",
-// fileInfos[0].Length, fileInfos[1].Length, fileInfos[2].Length);
-
-// (fileInfos[2].Length - fileInfos[1].Length).ShouldBeLessThan(0);
-
-// //
-// // File Checks
-// ///
-
-// var deltaPkgFiles = deltaPkg.Files.ToList();
-// deltaPkgFiles.Count.ShouldBeGreaterThan(0);
-
-// this.Log().Info("Files in delta package:");
-// deltaPkgFiles.ForEach(x => this.Log().Info(x.Path));
-
-// var newFilesAdded = new[] {
-// "Newtonsoft.Json.dll",
-// //"Refit.dll",
-// //"Refit-Portable.dll",
-// //"Castle.Core.dll",
-// }.Select(x => x.ToLowerInvariant());
-
-// // vNext adds a dependency on Refit
-// newFilesAdded
-// .All(x => deltaPkgFiles.Any(y => y.Path.ToLowerInvariant().Contains(x)))
-// .ShouldBeTrue();
-
-// // All the other files should be diffs and shasums
-// deltaPkgFiles
-// .Where(x => !newFilesAdded.Any(y => x.Path.ToLowerInvariant().Contains(y)))
-// .All(x => x.Path.ToLowerInvariant().EndsWith("bsdiff") || x.Path.ToLowerInvariant().EndsWith("shasum"))
-// .ShouldBeTrue();
-
-// // Every .diff file should have a shasum file
-// deltaPkg.Files.Any(x => x.Path.ToLowerInvariant().EndsWith(".bsdiff")).ShouldBeTrue();
-// deltaPkg.Files
-// .Where(x => x.Path.ToLowerInvariant().EndsWith(".bsdiff"))
-// .ForEach(x => {
-// var lookingFor = x.Path.Replace(".bsdiff", ".shasum");
-// this.Log().Info("Looking for corresponding shasum file: {0}", lookingFor);
-// deltaPkg.Files.Any(y => y.Path == lookingFor).ShouldBeTrue();
-// });
-// } finally {
-// tempFiles.ForEach(File.Delete);
-// }
-// }
-
-// [Fact]
-// public void WhenBasePackageIsNewerThanNewPackageThrowException()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
-// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
-
-// var baseFixture = new ReleasePackageBuilder(basePackage);
-// var fixture = new ReleasePackageBuilder(newPackage);
-
-// var tempFiles = Enumerable.Range(0, 3)
-// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
-// .ToArray();
-
-// try {
-// baseFixture.CreateReleasePackage(tempFiles[0]);
-// fixture.CreateReleasePackage(tempFiles[1]);
-
-// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-
-// Assert.Throws(() => {
-// var deltaBuilder = new DeltaPackageBuilder();
-// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
-// });
-// } finally {
-// tempFiles.ForEach(File.Delete);
-// }
-// }
-
-// [Fact]
-// public void WhenBasePackageReleaseIsNullThrowsException()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.0.0.0.nupkg");
-// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.1.0.0.nupkg");
-
-// var sourceDir = IntegrationTestHelper.GetPath("fixtures", "packages");
-// (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();
-
-// var baseFixture = new ReleasePackageBuilder(basePackage);
-// var fixture = new ReleasePackageBuilder(newPackage);
-
-// var tempFile = Path.GetTempPath() + Guid.NewGuid() + ".nupkg";
-
-// try {
-// Assert.Throws(() => {
-// var deltaBuilder = new DeltaPackageBuilder();
-// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFile);
-// });
-// } finally {
-// File.Delete(tempFile);
-// }
-// }
-
-// [Fact]
-// public void WhenBasePackageDoesNotExistThrowException()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
-// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
-
-// var baseFixture = new ReleasePackageBuilder(basePackage);
-// var fixture = new ReleasePackageBuilder(newPackage);
-
-// var tempFiles = Enumerable.Range(0, 3)
-// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
-// .ToArray();
-
-// try {
-// baseFixture.CreateReleasePackage(tempFiles[0]);
-// fixture.CreateReleasePackage(tempFiles[1]);
-
-// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-
-// // NOW WATCH AS THE FILE DISAPPEARS
-// File.Delete(baseFixture.ReleasePackageFile);
-
-// Assert.Throws(() => {
-// var deltaBuilder = new DeltaPackageBuilder();
-// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
-// });
-// } finally {
-// tempFiles.ForEach(File.Delete);
-// }
-// }
-
-// [Fact]
-// public void WhenNewPackageDoesNotExistThrowException()
-// {
-// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
-// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
-
-// var baseFixture = new ReleasePackageBuilder(basePackage);
-// var fixture = new ReleasePackageBuilder(newPackage);
-
-// var tempFiles = Enumerable.Range(0, 3)
-// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
-// .ToArray();
-
-// try {
-// baseFixture.CreateReleasePackage(tempFiles[0]);
-// fixture.CreateReleasePackage(tempFiles[1]);
-
-// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
-
-// // NOW WATCH AS THE FILE DISAPPEARS
-// File.Delete(fixture.ReleasePackageFile);
-
-// Assert.Throws(() => {
-// var deltaBuilder = new DeltaPackageBuilder();
-// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
-// });
-// } finally {
-// tempFiles.ForEach(File.Delete);
-// }
-// }
-
-// [Fact]
-// public void HandleBsDiffWithoutExtraData()
-// {
-// var baseFileData = new byte[] { 1, 1, 1, 1 };
-// var newFileData = new byte[] { 2, 1, 1, 1 };
-
-// byte[] patchData;
-
-// using (var patchOut = new MemoryStream()) {
-// Bsdiff.BinaryPatchUtility.Create(baseFileData, newFileData, patchOut);
-// patchData = patchOut.ToArray();
-// }
-
-// using (var toPatch = new MemoryStream(baseFileData))
-// using (var patched = new MemoryStream()) {
-// Bsdiff.BinaryPatchUtility.Apply(toPatch, () => new MemoryStream(patchData), patched);
-
-// Assert.Equal(newFileData, patched.ToArray());
-// }
-// }
-// }
-//}
+using Velopack.Core;
+using Velopack.Packaging.Commands;
+using Velopack.Util;
+
+namespace Velopack.Packaging.Tests;
+
+public class ApplyDeltaPackageTests(ITestOutputHelper output)
+{
+ // [Fact]
+ // public void ApplyDeltaPackageSmokeTest()
+ // {
+ // var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.0.0.0-full.nupkg");
+ // var deltaPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.1.0.0-delta.nupkg");
+ // var expectedPackageFile = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.1.0.0-full.nupkg");
+ // var outFile = Path.GetTempFileName() + ".nupkg";
+ //
+ // try {
+ // var deltaBuilder = new DeltaPackage();
+ // deltaBuilder.ApplyDeltaPackage(basePackage, deltaPackage, outFile);
+ //
+ // var result = new ZipPackage(outFile);
+ // var expected = new ZipPackage(expectedPackageFile);
+ //
+ // result.Id.ShouldEqual(expected.Id);
+ // result.Version.ShouldEqual(expected.Version);
+ //
+ // this.Log().Info("Expected file list:");
+ // var expectedList = expected.Files.Select(x => x.Path).OrderBy(x => x).ToList();
+ // expectedList.ForEach(x => this.Log().Info(x));
+ //
+ // this.Log().Info("Actual file list:");
+ // var actualList = result.Files.Select(x => x.Path).OrderBy(x => x).ToList();
+ // actualList.ForEach(x => this.Log().Info(x));
+ //
+ // Enumerable.Zip(expectedList, actualList, (e, a) => e == a)
+ // .All(x => x != false)
+ // .ShouldBeTrue();
+ // } finally {
+ // if (File.Exists(outFile)) {
+ // File.Delete(outFile);
+ // }
+ // }
+ // }
+ //
+ // [Fact]
+ // public void ApplyDeltaWithBothBsdiffAndNormalDiffDoesntFail()
+ // {
+ // var basePackage = IntegrationTestHelper.GetPath("fixtures", "slack-1.1.8-full.nupkg");
+ // var deltaPackage = IntegrationTestHelper.GetPath("fixtures", "slack-1.2.0-delta.nupkg");
+ // var outFile = Path.GetTempFileName() + ".nupkg";
+ //
+ // try {
+ // var deltaBuilder = new DeltaPackage();
+ // deltaBuilder.ApplyDeltaPackage(basePackage, deltaPackage, outFile);
+ //
+ // var result = new ZipPackage(outFile);
+ //
+ // result.Id.ShouldEqual("slack");
+ // result.Version.ShouldEqual(SemanticVersion.Parse("1.2.0"));
+ // } finally {
+ // if (File.Exists(outFile)) {
+ // File.Delete(outFile);
+ // }
+ // }
+ // }
+
+ [Fact]
+ public async Task ApplyMultipleDeltasFast()
+ {
+ var basePackage = PathHelper.GetFixture("Clowd-3.4.287-full.nupkg");
+ var deltaPackage1 = PathHelper.GetFixture("Clowd-3.4.288-delta.nupkg");
+ var deltaPackage2 = PathHelper.GetFixture("Clowd-3.4.291-delta.nupkg");
+ var deltaPackage3 = PathHelper.GetFixture("Clowd-3.4.292-delta.nupkg");
+
+ using var t2 = TempUtil.GetTempDirectory(out var temp);
+ using var logger = output.BuildLoggerFor();
+ var console = new LoggerConsole(logger);
+
+ var runner = new DeltaPatchCommandRunner(logger, console);
+ await runner.Run(
+ new DeltaPatchOptions() {
+ BasePackage = basePackage,
+ OutputFile = Path.Combine(temp, "Clowd-3.4.292-full.nupkg"),
+ PatchFiles = [
+ new FileInfo(deltaPackage1),
+ new FileInfo(deltaPackage2),
+ new FileInfo(deltaPackage3),
+ ]
+ });
+
+ // var newEntry = um.createFullPackagesFromDeltas(toApply, baseEntry, progress.Add);
+ //
+ // var outFile = Path.Combine(pkgDir, newEntry.Filename);
+ // var result = new ZipPackage(outFile);
+ // result.Id.ShouldEqual("Clowd");
+ // result.Version.ShouldEqual(SemanticVersion.Parse("3.4.292"));
+ }
+
+ // [Fact(Skip = "Rewrite this test, the original uses too many heavyweight fixtures")]
+ // public void ApplyMultipleDeltaPackagesGeneratesCorrectHash()
+ // {
+ // Assert.Fail("Rewrite this test, the original uses too many heavyweight fixtures");
+ // }
+}
+
+// public class CreateDeltaPackageTests : IEnableLogger
+// {
+// [Fact]
+// public void CreateDeltaPackageIntegrationTest()
+// {
+// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
+// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
+//
+// var baseFixture = new ReleasePackageBuilder(basePackage);
+// var fixture = new ReleasePackageBuilder(newPackage);
+//
+// var tempFiles = Enumerable.Range(0, 3)
+// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
+// .ToArray();
+//
+// try {
+// baseFixture.CreateReleasePackage(tempFiles[0]);
+// fixture.CreateReleasePackage(tempFiles[1]);
+//
+// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+//
+// var deltaBuilder = new DeltaPackageBuilder();
+// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
+//
+// var fullPkg = new ZipPackage(tempFiles[1]);
+// var deltaPkg = new ZipPackage(tempFiles[2]);
+//
+// //
+// // Package Checks
+// //
+//
+// fullPkg.Id.ShouldEqual(deltaPkg.Id);
+// fullPkg.Version.CompareTo(deltaPkg.Version).ShouldEqual(0);
+//
+// // Delta packages should be smaller than the original!
+// var fileInfos = tempFiles.Select(x => new FileInfo(x)).ToArray();
+// this.Log().Info("Base Size: {0}, Current Size: {1}, Delta Size: {2}",
+// fileInfos[0].Length, fileInfos[1].Length, fileInfos[2].Length);
+//
+// (fileInfos[2].Length - fileInfos[1].Length).ShouldBeLessThan(0);
+//
+// //
+// // File Checks
+// ///
+//
+// var deltaPkgFiles = deltaPkg.Files.ToList();
+// deltaPkgFiles.Count.ShouldBeGreaterThan(0);
+//
+// this.Log().Info("Files in delta package:");
+// deltaPkgFiles.ForEach(x => this.Log().Info(x.Path));
+//
+// var newFilesAdded = new[] {
+// "Newtonsoft.Json.dll",
+// //"Refit.dll",
+// //"Refit-Portable.dll",
+// //"Castle.Core.dll",
+// }.Select(x => x.ToLowerInvariant());
+//
+// // vNext adds a dependency on Refit
+// newFilesAdded
+// .All(x => deltaPkgFiles.Any(y => y.Path.ToLowerInvariant().Contains(x)))
+// .ShouldBeTrue();
+//
+// // All the other files should be diffs and shasums
+// deltaPkgFiles
+// .Where(x => !newFilesAdded.Any(y => x.Path.ToLowerInvariant().Contains(y)))
+// .All(x => x.Path.ToLowerInvariant().EndsWith("bsdiff") || x.Path.ToLowerInvariant().EndsWith("shasum"))
+// .ShouldBeTrue();
+//
+// // Every .diff file should have a shasum file
+// deltaPkg.Files.Any(x => x.Path.ToLowerInvariant().EndsWith(".bsdiff")).ShouldBeTrue();
+// deltaPkg.Files
+// .Where(x => x.Path.ToLowerInvariant().EndsWith(".bsdiff"))
+// .ForEach(x => {
+// var lookingFor = x.Path.Replace(".bsdiff", ".shasum");
+// this.Log().Info("Looking for corresponding shasum file: {0}", lookingFor);
+// deltaPkg.Files.Any(y => y.Path == lookingFor).ShouldBeTrue();
+// });
+// } finally {
+// tempFiles.ForEach(File.Delete);
+// }
+// }
+//
+// [Fact]
+// public void WhenBasePackageIsNewerThanNewPackageThrowException()
+// {
+// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
+// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
+//
+// var baseFixture = new ReleasePackageBuilder(basePackage);
+// var fixture = new ReleasePackageBuilder(newPackage);
+//
+// var tempFiles = Enumerable.Range(0, 3)
+// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
+// .ToArray();
+//
+// try {
+// baseFixture.CreateReleasePackage(tempFiles[0]);
+// fixture.CreateReleasePackage(tempFiles[1]);
+//
+// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+//
+// Assert.Throws(() => {
+// var deltaBuilder = new DeltaPackageBuilder();
+// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
+// });
+// } finally {
+// tempFiles.ForEach(File.Delete);
+// }
+// }
+//
+// [Fact]
+// public void WhenBasePackageReleaseIsNullThrowsException()
+// {
+// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.0.0.0.nupkg");
+// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Core.1.1.0.0.nupkg");
+//
+// var sourceDir = IntegrationTestHelper.GetPath("fixtures", "packages");
+// (new DirectoryInfo(sourceDir)).Exists.ShouldBeTrue();
+//
+// var baseFixture = new ReleasePackageBuilder(basePackage);
+// var fixture = new ReleasePackageBuilder(newPackage);
+//
+// var tempFile = Path.GetTempPath() + Guid.NewGuid() + ".nupkg";
+//
+// try {
+// Assert.Throws(() => {
+// var deltaBuilder = new DeltaPackageBuilder();
+// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFile);
+// });
+// } finally {
+// File.Delete(tempFile);
+// }
+// }
+//
+// [Fact]
+// public void WhenBasePackageDoesNotExistThrowException()
+// {
+// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
+// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
+//
+// var baseFixture = new ReleasePackageBuilder(basePackage);
+// var fixture = new ReleasePackageBuilder(newPackage);
+//
+// var tempFiles = Enumerable.Range(0, 3)
+// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
+// .ToArray();
+//
+// try {
+// baseFixture.CreateReleasePackage(tempFiles[0]);
+// fixture.CreateReleasePackage(tempFiles[1]);
+//
+// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+//
+// // NOW WATCH AS THE FILE DISAPPEARS
+// File.Delete(baseFixture.ReleasePackageFile);
+//
+// Assert.Throws(() => {
+// var deltaBuilder = new DeltaPackageBuilder();
+// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
+// });
+// } finally {
+// tempFiles.ForEach(File.Delete);
+// }
+// }
+//
+// [Fact]
+// public void WhenNewPackageDoesNotExistThrowException()
+// {
+// var basePackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.1.0-pre.nupkg");
+// var newPackage = IntegrationTestHelper.GetPath("fixtures", "Squirrel.Tests.0.2.0-pre.nupkg");
+//
+// var baseFixture = new ReleasePackageBuilder(basePackage);
+// var fixture = new ReleasePackageBuilder(newPackage);
+//
+// var tempFiles = Enumerable.Range(0, 3)
+// .Select(_ => Path.GetTempPath() + Guid.NewGuid().ToString() + ".nupkg")
+// .ToArray();
+//
+// try {
+// baseFixture.CreateReleasePackage(tempFiles[0]);
+// fixture.CreateReleasePackage(tempFiles[1]);
+//
+// (new FileInfo(baseFixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+// (new FileInfo(fixture.ReleasePackageFile)).Exists.ShouldBeTrue();
+//
+// // NOW WATCH AS THE FILE DISAPPEARS
+// File.Delete(fixture.ReleasePackageFile);
+//
+// Assert.Throws(() => {
+// var deltaBuilder = new DeltaPackageBuilder();
+// deltaBuilder.CreateDeltaPackage(baseFixture, fixture, tempFiles[2]);
+// });
+// } finally {
+// tempFiles.ForEach(File.Delete);
+// }
+// }
+//
+// [Fact]
+// public void HandleBsDiffWithoutExtraData()
+// {
+// var baseFileData = new byte[] { 1, 1, 1, 1 };
+// var newFileData = new byte[] { 2, 1, 1, 1 };
+//
+// byte[] patchData;
+//
+// using (var patchOut = new MemoryStream()) {
+// Bsdiff.BinaryPatchUtility.Create(baseFileData, newFileData, patchOut);
+// patchData = patchOut.ToArray();
+// }
+//
+// using (var toPatch = new MemoryStream(baseFileData))
+// using (var patched = new MemoryStream()) {
+// Bsdiff.BinaryPatchUtility.Apply(toPatch, () => new MemoryStream(patchData), patched);
+//
+// Assert.Equal(newFileData, patched.ToArray());
+// }
+// }
+// }
\ No newline at end of file
diff --git a/test/Velopack.Tests/ReleaseEntryTests.cs b/test/Velopack.Tests/ReleaseEntryTests.cs
index 73c2623c..2be0aca3 100644
--- a/test/Velopack.Tests/ReleaseEntryTests.cs
+++ b/test/Velopack.Tests/ReleaseEntryTests.cs
@@ -1,6 +1,7 @@
#pragma warning disable CS0618 // Type or member is obsolete
using System.Text;
using NuGet.Versioning;
+using Velopack.Core;
using OldReleaseEntry = Velopack.Tests.OldSquirrel.ReleaseEntry;
using OldSemanticVersion = Velopack.Tests.OldSquirrel.SemanticVersion;
From 96a191ed1b2e09cbd8921b2c4ef8d5dd5285fe04 Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Wed, 14 May 2025 08:32:16 +0100
Subject: [PATCH 37/64] Add delta to rust updatemanager
---
src/lib-csharp/UpdateManager.cs | 31 +++---
src/lib-csharp/UpdateOptions.cs | 8 +-
src/lib-rust/src/lib.rs | 2 +
src/lib-rust/src/locator.rs | 2 +-
src/lib-rust/src/manager.rs | 191 ++++++++++++++++++++++++++++----
5 files changed, 192 insertions(+), 42 deletions(-)
diff --git a/src/lib-csharp/UpdateManager.cs b/src/lib-csharp/UpdateManager.cs
index 1f2733f9..672a6766 100644
--- a/src/lib-csharp/UpdateManager.cs
+++ b/src/lib-csharp/UpdateManager.cs
@@ -69,6 +69,9 @@ namespace Velopack
/// If true, UpdateManager should return the latest asset in the feed, even if that version is lower than the current version.
protected bool ShouldAllowVersionDowngrade { get; }
+ /// Sets the maximum number of deltas to consider before falling back to a full update.
+ protected int MaximumDeltasBeforeFallback { get; }
+
///
/// Creates a new UpdateManager instance using the specified URL or file path to the releases feed, and the specified channel name.
///
@@ -96,6 +99,7 @@ namespace Velopack
Log = Locator.Log;
Channel = options?.ExplicitChannel ?? DefaultChannel;
ShouldAllowVersionDowngrade = options?.AllowVersionDowngrade ?? false;
+ MaximumDeltasBeforeFallback = options?.MaximumDeltasBeforeFallback ?? 10;
}
///
@@ -185,9 +189,9 @@ namespace Velopack
}
///
- public void DownloadUpdates(UpdateInfo updates, Action? progress = null, bool ignoreDeltas = false)
+ public void DownloadUpdates(UpdateInfo updates, Action? progress = null)
{
- DownloadUpdatesAsync(updates, progress, ignoreDeltas)
+ DownloadUpdatesAsync(updates, progress)
.ConfigureAwait(false).GetAwaiter().GetResult();
}
@@ -201,8 +205,7 @@ namespace Velopack
/// The progress callback. Will be called with values from 0-100.
/// Whether to attempt downloading delta's or skip to full package download.
/// An optional cancellation token if you wish to stop this operation.
- public virtual async Task DownloadUpdatesAsync(
- UpdateInfo updates, Action? progress = null, bool ignoreDeltas = false, CancellationToken cancelToken = default)
+ public virtual async Task DownloadUpdatesAsync(UpdateInfo updates, Action? progress = null, CancellationToken cancelToken = default)
{
progress ??= (_ => { });
@@ -252,19 +255,15 @@ namespace Velopack
try {
if (updates.BaseRelease?.FileName != null && deltasCount > 0) {
- if (ignoreDeltas) {
- Log.Info("Ignoring delta updates (ignoreDeltas parameter)");
+ if (deltasCount > MaximumDeltasBeforeFallback || deltasSize > targetRelease.Size) {
+ Log.Info(
+ $"There are too many delta's ({deltasCount} > {MaximumDeltasBeforeFallback}) or the sum of their size ({deltasSize} > {targetRelease.Size}) is too large. " +
+ $"Only full update will be available.");
} else {
- if (deltasCount > 10 || deltasSize > targetRelease.Size) {
- Log.Info(
- $"There are too many delta's ({deltasCount} > 10) or the sum of their size ({deltasSize} > {targetRelease.Size}) is too large. " +
- $"Only full update will be available.");
- } else {
- await DownloadAndApplyDeltaUpdates(updates, incompleteFile, progress, cancelToken).ConfigureAwait(false);
- IoUtil.MoveFile(incompleteFile, completeFile, true);
- Log.Info("Delta update download complete. Package moved to: " + completeFile);
- return; // success!
- }
+ await DownloadAndApplyDeltaUpdates(updates, incompleteFile, progress, cancelToken).ConfigureAwait(false);
+ IoUtil.MoveFile(incompleteFile, completeFile, true);
+ Log.Info("Delta update download complete. Package moved to: " + completeFile);
+ return; // success!
}
}
} catch (Exception ex) when (!VelopackRuntimeInfo.InUnitTestRunner) {
diff --git a/src/lib-csharp/UpdateOptions.cs b/src/lib-csharp/UpdateOptions.cs
index 95aab7d9..ba4b57d6 100644
--- a/src/lib-csharp/UpdateOptions.cs
+++ b/src/lib-csharp/UpdateOptions.cs
@@ -22,5 +22,11 @@
/// without having to reinstall the application.
///
public string? ExplicitChannel { get; set; }
+
+ ///
+ /// Sets the maximum number of deltas to consider before falling back to a full update.
+ /// The default is 10. Set to a negative number to disable deltas.
+ ///
+ public int? MaximumDeltasBeforeFallback { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/src/lib-rust/src/lib.rs b/src/lib-rust/src/lib.rs
index dfe36739..fe9cce17 100644
--- a/src/lib-rust/src/lib.rs
+++ b/src/lib-rust/src/lib.rs
@@ -127,6 +127,8 @@ pub enum Error
FileNotFound(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
+ #[error("Checusum did not match for {0} (expected {1}, actual {2})")]
+ Checksum(String, String, String),
#[error("Zip error: {0}")]
Zip(#[from] zip::result::ZipError),
#[error("Network error: {0}")]
diff --git a/src/lib-rust/src/locator.rs b/src/lib-rust/src/locator.rs
index 58a9a8d5..b8ebb679 100644
--- a/src/lib-rust/src/locator.rs
+++ b/src/lib-rust/src/locator.rs
@@ -531,7 +531,7 @@ pub fn find_latest_full_package(packages_dir: &PathBuf) -> Option<(PathBuf, Mani
info!("Attempting to auto-detect package in: {}", packages_dir);
let mut package: Option<(PathBuf, Manifest)> = None;
- let search_glob = format!("{}/*.nupkg", packages_dir);
+ let search_glob = format!("{}/*-full.nupkg", packages_dir);
if let Ok(paths) = glob::glob(search_glob.as_str()) {
for path in paths.into_iter().flatten() {
trace!("Checking package: '{}'", path.to_string_lossy());
diff --git a/src/lib-rust/src/manager.rs b/src/lib-rust/src/manager.rs
index 30b007ed..66d6240c 100644
--- a/src/lib-rust/src/manager.rs
+++ b/src/lib-rust/src/manager.rs
@@ -1,19 +1,20 @@
+use semver::Version;
+use serde::{Deserialize, Serialize};
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
+use std::path::PathBuf;
use std::{
fs,
process::{exit, Command as Process},
sync::mpsc::Sender,
};
-use semver::Version;
-use serde::{Deserialize, Serialize};
-
#[cfg(feature = "async")]
use async_std::channel::Sender as AsyncSender;
#[cfg(feature = "async")]
use async_std::task::JoinHandle;
+use crate::bundle::Manifest;
use crate::{
locator::{self, LocationContext, VelopackLocator, VelopackLocatorConfig},
sources::UpdateSource,
@@ -82,12 +83,26 @@ pub struct VelopackAsset {
pub struct UpdateInfo {
/// The available version that we are updating to.
pub TargetFullRelease: VelopackAsset,
+ /// The base release that this update is based on. This is only available if the update is a delta update.
+ pub BaseRelease: Option,
+ /// The list of delta updates that can be applied to the base version to get to the target version.
+ pub DeltasToTarget: Vec,
/// True if the update is a version downgrade or lateral move (such as when switching channels to the same version number).
/// In this case, only full updates are allowed, and any local packages on disk newer than the downloaded version will be
/// deleted.
pub IsDowngrade: bool,
}
+impl UpdateInfo {
+ pub(crate) fn new_full(target: VelopackAsset, is_downgrade: bool) -> UpdateInfo {
+ UpdateInfo { TargetFullRelease: target, BaseRelease: None, DeltasToTarget: Vec::new(), IsDowngrade: is_downgrade }
+ }
+
+ pub(crate) fn new_delta(target: VelopackAsset, base: VelopackAsset, deltas: Vec) -> UpdateInfo {
+ UpdateInfo { TargetFullRelease: target, BaseRelease: Some(base), DeltasToTarget: deltas, IsDowngrade: false }
+ }
+}
+
impl AsRef for UpdateInfo {
fn as_ref(&self) -> &VelopackAsset {
&self.TargetFullRelease
@@ -119,6 +134,9 @@ pub struct UpdateOptions {
/// allows you to explicitly switch channels, for example if the user wished to switch back to the 'stable' channel
/// without having to reinstall the application.
pub ExplicitChannel: Option,
+ /// Sets the maximum number of deltas to consider before falling back to a full update.
+ /// The default is 10. Set to a negative number (eg. -1) to disable deltas.
+ pub MaximumDeltasBeforeFallback: i32,
}
/// Provides functionality for checking for updates, downloading updates, and applying updates to the current application.
@@ -177,7 +195,11 @@ impl UpdateManager {
} else {
locator::auto_locate_app_manifest(LocationContext::FromCurrentExe)?
};
- Ok(UpdateManager { options: options.unwrap_or_default(), source, locator })
+ let mut options = options.unwrap_or_default();
+ if options.MaximumDeltasBeforeFallback == 0 {
+ options.MaximumDeltasBeforeFallback = 10;
+ }
+ Ok(UpdateManager { options, source, locator })
}
fn get_practical_channel(&self) -> String {
@@ -220,22 +242,26 @@ impl UpdateManager {
let packages_dir = self.locator.get_packages_dir();
if let Some((path, manifest)) = locator::find_latest_full_package(&packages_dir) {
if manifest.version > self.locator.get_manifest_version() {
- return Some(VelopackAsset {
- PackageId: manifest.id,
- Version: manifest.version.to_string(),
- Type: "Full".to_string(),
- FileName: path.file_name().unwrap().to_string_lossy().to_string(),
- SHA1: util::calculate_file_sha1(&path).unwrap_or_default(),
- SHA256: util::calculate_file_sha256(&path).unwrap_or_default(),
- Size: path.metadata().map(|m| m.len()).unwrap_or(0),
- NotesMarkdown: manifest.release_notes,
- NotesHtml: manifest.release_notes_html,
- });
+ return Some(self.local_manifest_to_asset(&manifest, &path));
}
}
None
}
+ fn local_manifest_to_asset(&self, manifest: &Manifest, path: &PathBuf) -> VelopackAsset {
+ VelopackAsset {
+ PackageId: manifest.id.clone(),
+ Version: manifest.version.to_string(),
+ Type: "Full".to_string(),
+ FileName: path.file_name().unwrap().to_string_lossy().to_string(),
+ SHA1: util::calculate_file_sha1(&path).unwrap_or_default(),
+ SHA256: util::calculate_file_sha256(&path).unwrap_or_default(),
+ Size: path.metadata().map(|m| m.len()).unwrap_or(0),
+ NotesMarkdown: manifest.release_notes.clone(),
+ NotesHtml: manifest.release_notes_html.clone(),
+ }
+ }
+
/// Get a list of available remote releases from the package source.
pub fn get_release_feed(&self) -> Result {
let channel = self.get_practical_channel();
@@ -266,9 +292,9 @@ impl UpdateManager {
return Ok(UpdateCheck::RemoteIsEmpty);
}
- let mut latest: Option = None;
+ let mut latest: Option<&VelopackAsset> = None;
let mut latest_version: Version = Version::parse("0.0.0")?;
- for asset in assets {
+ for asset in &assets {
if let Ok(sv) = Version::parse(&asset.Version) {
if asset.Type.eq_ignore_ascii_case("Full") {
debug!("Found full release: {} ({}).", asset.FileName, sv.to_string());
@@ -291,21 +317,66 @@ impl UpdateManager {
if remote_version > app_version {
info!("Found newer remote release available ({} -> {}).", app_version, remote_version);
- Ok(UpdateCheck::UpdateAvailable(UpdateInfo { TargetFullRelease: remote_asset, IsDowngrade: false }))
+ Ok(UpdateCheck::UpdateAvailable(self.create_delta_update_strategy(&assets, (remote_asset, remote_version))))
} else if remote_version < app_version && allow_downgrade {
info!("Found older remote release available and downgrade is enabled ({} -> {}).", app_version, remote_version);
- Ok(UpdateCheck::UpdateAvailable(UpdateInfo { TargetFullRelease: remote_asset, IsDowngrade: true }))
+ Ok(UpdateCheck::UpdateAvailable(UpdateInfo::new_full(remote_asset.clone(), true)))
} else if remote_version == app_version && allow_downgrade && is_non_default_channel {
info!(
"Latest remote release is the same version of a different channel, and downgrade is enabled ({} -> {}, {} -> {}).",
app_version, remote_version, app_channel, practical_channel
);
- Ok(UpdateCheck::UpdateAvailable(UpdateInfo { TargetFullRelease: remote_asset, IsDowngrade: true }))
+ Ok(UpdateCheck::UpdateAvailable(UpdateInfo::new_full(remote_asset.clone(), true)))
} else {
Ok(UpdateCheck::NoUpdateAvailable)
}
}
+ fn create_delta_update_strategy(
+ &self,
+ velopack_asset_feed: &Vec,
+ latest_remote: (&VelopackAsset, Version),
+ ) -> UpdateInfo {
+ let packages_dir = self.locator.get_packages_dir();
+ let latest_local = locator::find_latest_full_package(&packages_dir);
+
+ if latest_local.is_none() {
+ info!("There is no local/base package available for this update, so delta updates will be disabled.");
+ return UpdateInfo::new_full(latest_remote.0.clone(), false);
+ }
+
+ let (latest_local_path, latest_local_manifest) = latest_local.unwrap();
+ let local_asset = self.local_manifest_to_asset(&latest_local_manifest, &latest_local_path);
+
+ let assets_and_versions: Vec<(&VelopackAsset, Version)> =
+ velopack_asset_feed.iter().filter_map(|asset| Version::parse(&asset.Version).ok().map(|ver| (asset, ver))).collect();
+
+ let matching_latest_delta =
+ assets_and_versions.iter().find(|(asset, version)| asset.Type.eq_ignore_ascii_case("Delta") && version == &latest_remote.1);
+
+ if matching_latest_delta.is_none() {
+ info!("No matching delta update found for release {}, so deltas will be disabled.", latest_remote.1);
+ return UpdateInfo::new_full(latest_remote.0.clone(), false);
+ }
+
+ let mut remotes_greater_than_local = assets_and_versions
+ .iter()
+ .filter(|(asset, _version)| asset.Type.eq_ignore_ascii_case("Delta"))
+ .filter(|(_asset, version)| version > &latest_local_manifest.version && version <= &latest_remote.1)
+ .collect::>();
+
+ remotes_greater_than_local.sort_by(|a, b| a.1.cmp(&b.1));
+ let remotes_greater_than_local = remotes_greater_than_local.iter().map(|obj| obj.0.clone()).collect::>();
+
+ info!(
+ "Found {} delta updates between {} and {}.",
+ remotes_greater_than_local.len(),
+ latest_local_manifest.version,
+ latest_remote.1
+ );
+ UpdateInfo::new_delta(latest_remote.0.clone(), local_asset, remotes_greater_than_local)
+ }
+
/// Checks for updates, returning None if there are none available. If there are updates available, this method will return an
/// UpdateInfo object containing the latest available release, and any delta updates that can be applied if they are available.
#[cfg(feature = "async")]
@@ -327,7 +398,7 @@ impl UpdateManager {
fs::create_dir_all(packages_dir)?;
let final_target_file = packages_dir.join(name);
- let partial_file = packages_dir.join(format!("{}.partial", name));
+ let partial_file = final_target_file.with_extension(".partial");
if final_target_file.exists() {
info!("Package already exists on disk, skipping download: '{}'", final_target_file.to_string_lossy());
@@ -336,6 +407,7 @@ impl UpdateManager {
let old_nupkg_pattern = format!("{}/*.nupkg", packages_dir.to_string_lossy());
let old_partial_pattern = format!("{}/*.partial", packages_dir.to_string_lossy());
+ let delta_pattern = format!("{}/-delta.nupkg", packages_dir.to_string_lossy());
let mut to_delete = Vec::new();
fn find_files_to_delete(pattern: &str, to_delete: &mut Vec) {
@@ -355,12 +427,26 @@ impl UpdateManager {
find_files_to_delete(&old_nupkg_pattern, &mut to_delete);
find_files_to_delete(&old_partial_pattern, &mut to_delete);
- self.source.download_release_entry(&update.TargetFullRelease, &partial_file.to_string_lossy(), progress)?;
- info!("Successfully placed file: '{}'", partial_file.to_string_lossy());
+ if update.BaseRelease.is_some() && !update.DeltasToTarget.is_empty() {
+ info!("Beginning delta update process.");
+ if let Err(e) = self.download_and_apply_delta_updates(update, &partial_file, progress.clone()) {
+ error!("Error downloading delta updates: {}", e);
+ info!("Falling back to full update...");
+ self.source.download_release_entry(&update.TargetFullRelease, &partial_file.to_string_lossy(), progress)?;
+ self.verify_package_checksum(&partial_file, &update.TargetFullRelease)?;
+ }
+ } else {
+ self.source.download_release_entry(&update.TargetFullRelease, &partial_file.to_string_lossy(), progress)?;
+ self.verify_package_checksum(&partial_file, &update.TargetFullRelease)?;
+ }
+
+ info!("Successfully downloaded file: '{}'", partial_file.to_string_lossy());
info!("Renaming partial file to final target: '{}'", final_target_file.to_string_lossy());
fs::rename(&partial_file, &final_target_file)?;
+ find_files_to_delete(&delta_pattern, &mut to_delete);
+
// extract new Update.exe on Windows only
#[cfg(target_os = "windows")]
match crate::bundle::load_bundle_from_file(&final_target_file) {
@@ -384,6 +470,63 @@ impl UpdateManager {
Ok(())
}
+ fn download_and_apply_delta_updates(
+ &self,
+ update: &UpdateInfo,
+ target_file: &PathBuf,
+ progress: Option>,
+ ) -> Result<(), Error> {
+ let packages_dir = self.locator.get_packages_dir();
+ for (i, delta) in update.DeltasToTarget.iter().enumerate() {
+ let delta_file = packages_dir.join(&delta.FileName);
+ let partial_file = delta_file.with_extension("partial");
+
+ info!("Downloading delta package: '{}'", &delta.FileName);
+ self.source.download_release_entry(&delta, &partial_file.to_string_lossy(), None)?;
+ self.verify_package_checksum(&partial_file, delta)?;
+
+ fs::rename(&partial_file, &delta_file)?;
+ debug!("Successfully downloaded file: '{}'", &delta.FileName);
+ if let Some(progress) = &progress {
+ let _ = progress.send(((i as f64 / update.DeltasToTarget.len() as f64) * 70.0) as i16);
+ }
+ }
+
+ let mut args: Vec =
+ ["patch", "--old", &update.BaseRelease.as_ref().unwrap().FileName, "--output"].iter().map(|s| s.to_string()).collect();
+ args.push(target_file.to_string_lossy().to_string());
+ for delta in update.DeltasToTarget.iter() {
+ args.push("--delta".to_string());
+ let path = packages_dir.join(&delta.FileName);
+ args.push(path.to_string_lossy().to_string());
+ }
+
+ info!("Applying {} patches to {}.", update.DeltasToTarget.len(), target_file.to_string_lossy());
+
+ let output = std::process::Command::new(self.locator.get_update_path()).args(args).output()?;
+ if output.status.success() {
+ info!("Successfully applied delta updates.");
+ } else {
+ let error_message = String::from_utf8_lossy(&output.stderr);
+ error!("Error applying delta updates: {}", error_message);
+ return Err(Error::Generic(error_message.to_string()));
+ }
+
+ if let Some(progress) = &progress {
+ let _ = progress.send(100);
+ }
+ Ok(())
+ }
+
+ fn verify_package_checksum(&self, file: &PathBuf, asset: &VelopackAsset) -> Result<(), Error> {
+ let sha1 = util::calculate_file_sha1(file)?;
+ if !sha1.eq_ignore_ascii_case(&asset.SHA1) {
+ error!("SHA1 checksum mismatch for file '{}': expected '{}', got '{}'", file.to_string_lossy(), asset.SHA1, sha1);
+ return Err(Error::Checksum(file.to_string_lossy().to_string(), asset.SHA1.clone(), sha1));
+ }
+ Ok(())
+ }
+
/// Downloads the specified updates to the local app packages directory. Progress is reported back to the caller via an optional Sender.
/// This function will acquire a global update lock so may fail if there is already another update operation in progress.
/// - If the update contains delta packages and the delta feature is enabled
@@ -462,7 +605,7 @@ impl UpdateManager {
}
/// This will launch the Velopack updater and optionally wait for a program to exit gracefully.
- /// This method is unsafe because it does not necessarily wait for any / the correct process to exit
+ /// This method is unsafe because it does not necessarily wait for any / the correct process to exit
/// before applying updates. The `wait_exit_then_apply_updates` method is recommended for most use cases.
pub fn unsafe_apply_updates(
&self,
From 0dace008453cfcf06b84baf45341131ea9768461 Mon Sep 17 00:00:00 2001
From: Caelan Sayler
Date: Wed, 14 May 2025 08:33:39 +0100
Subject: [PATCH 38/64] First version of handlebars is working
---
src/lib-cpp/include/Velopack.h | 27 +-
src/lib-cpp/include/Velopack.hpp | 15 +-
src/lib-cpp/src/csource.rs | 13 +-
src/lib-cpp/src/lib.rs | 59 +--
src/lib-cpp/src/types.rs | 486 ++++++++++++------
src/lib-cpp/type-generator/Program.cs | 79 ++-
src/lib-cpp/type-generator/StructParser.cs | 38 +-
src/lib-cpp/type-generator/Templates.cs | 65 ++-
.../type-generator/Templates/rust_struct.hbs | 98 ++++
src/lib-cpp/type-generator/Util.cs | 9 +-
.../type-generator/type-generator.csproj | 5 +
src/lib-nodejs/src/bindings/UpdateInfo.ts | 8 +
src/lib-nodejs/src/bindings/UpdateOptions.ts | 9 +-
src/lib-rust/src/manager.rs | 2 +-
14 files changed, 676 insertions(+), 237 deletions(-)
create mode 100644 src/lib-cpp/type-generator/Templates/rust_struct.hbs
diff --git a/src/lib-cpp/include/Velopack.h b/src/lib-cpp/include/Velopack.h
index 94910a05..badef7c2 100644
--- a/src/lib-cpp/include/Velopack.h
+++ b/src/lib-cpp/include/Velopack.h
@@ -55,7 +55,7 @@ typedef struct vpkc_asset_t {
*/
char *Version;
/**
- * The type of asset (eg. "Full" or "Delta").
+ * The type of asset (eg. "Full" or "Delta").
*/
char *Type;
/**
@@ -107,7 +107,7 @@ typedef struct vpkc_update_options_t {
*/
bool AllowVersionDowngrade;
/**
- * **This option should usually be left None**.
+ * **This option should usually be left None**.
* Overrides the default channel used to fetch updates.
* The default channel will be whatever channel was specified on the command line when building this release.
* For example, if the current release was packaged with '--channel beta', then the default channel will be 'beta'.
@@ -116,6 +116,11 @@ typedef struct vpkc_update_options_t {
* without having to reinstall the application.
*/
char *ExplicitChannel;
+ /**
+ * Sets the maximum number of deltas to consider before falling back to a full update.
+ * The default is 10. Set to a negative number (eg. -1) to disable deltas.
+ */
+ int32_t MaximumDeltasBeforeFallback;
} vpkc_update_options_t;
/**
@@ -160,7 +165,19 @@ typedef struct vpkc_update_info_t {
/**
* The available version that we are updating to.
*/
- struct vpkc_asset_t TargetFullRelease;
+ struct vpkc_asset_t *TargetFullRelease;
+ /**
+ * The base release that this update is based on. This is only available if the update is a delta update.
+ */
+ struct vpkc_asset_t *BaseRelease;
+ /**
+ * The list of delta updates that can be applied to the base version to get to the target version.
+ */
+ struct vpkc_asset_t **DeltasToTarget;
+ /**
+ * The number of elements in the DeltasToTarget array.
+ */
+ size_t DeltasToTargetCount;
/**
* True if the update is a version downgrade or lateral move (such as when switching channels to the same version number).
* In this case, only full updates are allowed, and any local packages on disk newer than the downloaded version will be
@@ -267,14 +284,14 @@ bool vpkc_is_portable(vpkc_update_manager_t *p_manager);
* Returns an UpdateInfo object if there is an update downloaded which still needs to be applied.
* You can pass the UpdateInfo object to waitExitThenApplyUpdate to apply the update.
*/
-bool vpkc_update_pending_restart(vpkc_update_manager_t *p_manager, struct vpkc_asset_t *p_asset);
+bool vpkc_update_pending_restart(vpkc_update_manager_t *p_manager, struct vpkc_asset_t **p_asset);
/**
* Checks for updates, returning None if there are none available. If there are updates available, this method will return an
* UpdateInfo object containing the latest available release, and any delta updates that can be applied if they are available.
*/
vpkc_update_check_t vpkc_check_for_updates(vpkc_update_manager_t *p_manager,
- struct vpkc_update_info_t *p_update);
+ struct vpkc_update_info_t **p_update);
/**
* Downloads the specified updates to the local app packages directory. Progress is reported back to the caller via an optional callback.
diff --git a/src/lib-cpp/include/Velopack.hpp b/src/lib-cpp/include/Velopack.hpp
index 7aa5ff8b..43f08390 100644
--- a/src/lib-cpp/include/Velopack.hpp
+++ b/src/lib-cpp/include/Velopack.hpp
@@ -91,6 +91,10 @@ struct VelopackAsset {
struct UpdateInfo {
/// The available version that we are updating to.
VelopackAsset TargetFullRelease;
+ /// The base release that this update is based on. This is only available if the update is a delta update.
+ std::optional BaseRelease;
+ /// The list of delta updates that can be applied to the base version to get to the target version.
+ std::vector DeltasToTarget;
/// True if the update is a version downgrade or lateral move (such as when switching channels to the same version number).
/// In this case, only full updates are allowed, and any local packages on disk newer than the downloaded version will be
/// deleted.
@@ -104,7 +108,7 @@ struct UpdateOptions {
/// ExplicitChannel to switch channels to another channel where the latest version on that
/// channel is lower than the current version.
bool AllowVersionDowngrade;
- /// **This option should usually be left None**.
+ /// **This option should usually be left None**.
/// Overrides the default channel used to fetch updates.
/// The default channel will be whatever channel was specified on the command line when building this release.
/// For example, if the current release was packaged with '--channel beta', then the default channel will be 'beta'.
@@ -112,6 +116,9 @@ struct UpdateOptions {
/// allows you to explicitly switch channels, for example if the user wished to switch back to the 'stable' channel
/// without having to reinstall the application.
std::optional ExplicitChannel;
+ /// Sets the maximum number of deltas to consider before falling back to a full update.
+ /// The default is 10. Set to a negative number (eg. -1) to disable deltas.
+ int64_t MaximumDeltasBeforeFallback;
};
static inline vpkc_locator_config_t to_c(const VelopackLocatorConfig& dto) {
@@ -167,6 +174,8 @@ static inline VelopackAsset to_cpp(const vpkc_asset_t& dto) {
static inline vpkc_update_info_t to_c(const UpdateInfo& dto) {
return {
to_c(dto.TargetFullRelease),
+ to_c_opt(dto.BaseRelease),
+ to_c(dto.DeltasToTarget),
to_cbool(dto.IsDowngrade),
};
}
@@ -174,6 +183,8 @@ static inline vpkc_update_info_t to_c(const UpdateInfo& dto) {
static inline UpdateInfo to_cpp(const vpkc_update_info_t& dto) {
return {
to_cpp(dto.TargetFullRelease),
+ to_cpp_opt(dto.BaseRelease),
+ to_cpp(dto.DeltasToTarget),
to_cppbool(dto.IsDowngrade),
};
}
@@ -182,6 +193,7 @@ static inline vpkc_update_options_t to_c(const UpdateOptions& dto) {
return {
to_cbool(dto.AllowVersionDowngrade),
to_cstring_opt(dto.ExplicitChannel),
+ to_ci32(dto.MaximumDeltasBeforeFallback),
};
}
@@ -189,6 +201,7 @@ static inline UpdateOptions to_cpp(const vpkc_update_options_t& dto) {
return {
to_cppbool(dto.AllowVersionDowngrade),
to_cppstring_opt(dto.ExplicitChannel),
+ to_cppi32(dto.MaximumDeltasBeforeFallback),
};
}
// !! AUTO-GENERATED-END CPP_TYPES
diff --git a/src/lib-cpp/src/csource.rs b/src/lib-cpp/src/csource.rs
index 40b21340..9a2d051d 100644
--- a/src/lib-cpp/src/csource.rs
+++ b/src/lib-cpp/src/csource.rs
@@ -42,9 +42,9 @@ impl UpdateSource for CCallbackUpdateSource {
if let Some(cb_get_release_feed) = self.cb_get_release_feed {
let json_cstr_ptr = (cb_get_release_feed)(self.p_user_data, releases_name_cstr.as_ptr());
- let json = c_to_string_opt(json_cstr_ptr)
- .ok_or(Error::Generic("User vpkc_release_feed_delegate_t returned a null pointer instead of an asset feed".to_string()))?;
-
+ let json = c_to_String(json_cstr_ptr).map_err(|_| {
+ Error::Generic("User vpkc_release_feed_delegate_t returned a null pointer instead of an asset feed".to_string())
+ })?;
if let Some(cb_free_release_feed) = self.cb_free_release_feed {
(cb_free_release_feed)(self.p_user_data, json_cstr_ptr); // Free the C string returned by the callback
} else {
@@ -60,9 +60,7 @@ impl UpdateSource for CCallbackUpdateSource {
fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, progress_sender: Option>) -> Result<(), Error> {
if let Some(cb_download_release_entry) = self.cb_download_release_entry {
let local_file_cstr = CString::new(local_file).unwrap();
- let mut asset_c: vpkc_asset_t = unsafe { std::mem::zeroed() };
- let asset_ptr: *mut vpkc_asset_t = &mut asset_c as *mut vpkc_asset_t;
- unsafe { allocate_velopackasset(asset.clone(), asset_ptr) };
+ let asset_ptr = unsafe { allocate_VelopackAsset(asset) };
let progress_callback_id = PROGRESS_ID.fetch_add(1, Ordering::SeqCst);
if let Some(progress_sender) = &progress_sender {
@@ -71,8 +69,7 @@ impl UpdateSource for CCallbackUpdateSource {
}
let success = (cb_download_release_entry)(self.p_user_data, asset_ptr, local_file_cstr.as_ptr(), progress_callback_id);
-
- unsafe { free_velopackasset(asset_ptr) };
+ unsafe { free_VelopackAsset(asset_ptr) };
if let Some(sender) = PROGRESS_CALLBACKS.write().unwrap().remove(&progress_callback_id) {
let _ = sender.send(100);
diff --git a/src/lib-cpp/src/lib.rs b/src/lib-cpp/src/lib.rs
index 4c4b9fc6..ffe16e16 100644
--- a/src/lib-cpp/src/lib.rs
+++ b/src/lib-cpp/src/lib.rs
@@ -15,16 +15,16 @@ use anyhow::{anyhow, bail};
use libc::{c_char, c_void, size_t};
use log_derive::{logfn, logfn_inputs};
use std::{ffi::CString, ptr};
-use velopack::{sources, ApplyWaitMode, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp};
use velopack::locator::LocationContext;
use velopack::logging::{default_logfile_path, init_logging};
+use velopack::{sources, ApplyWaitMode, Error as VelopackError, UpdateCheck, UpdateManager, VelopackApp};
/// Create a new FileSource update source for a given file path.
#[no_mangle]
#[logfn(Trace)]
#[logfn_inputs(Trace)]
pub extern "C" fn vpkc_new_source_file(psz_file_path: *const c_char) -> *mut vpkc_update_source_t {
- if let Some(update_path) = c_to_string_opt(psz_file_path) {
+ if let Some(update_path) = c_to_String(psz_file_path).ok() {
UpdateSourceRawPtr::new(Box::new(sources::FileSource::new(update_path)))
} else {
log::error!("psz_file_path is null");
@@ -37,7 +37,7 @@ pub extern "C" fn vpkc_new_source_file(psz_file_path: *const c_char) -> *mut vpk
#[logfn(Trace)]
#[logfn_inputs(Trace)]
pub extern "C" fn vpkc_new_source_http_url(psz_http_url: *const c_char) -> *mut vpkc_update_source_t {
- if let Some(update_url) = c_to_string_opt(psz_http_url) {
+ if let Some(update_url) = c_to_String(psz_http_url).ok() {
UpdateSourceRawPtr::new(Box::new(sources::HttpSource::new(update_url)))
} else {
log::error!("psz_http_url is null");
@@ -103,10 +103,10 @@ pub extern "C" fn vpkc_new_update_manager(
p_manager: *mut *mut vpkc_update_manager_t,
) -> bool {
wrap_error(|| {
- let update_url = c_to_string_opt(psz_url_or_path).ok_or(anyhow!("URL or path is null"))?;
+ let update_url = c_to_String(psz_url_or_path)?;
let source = sources::AutoSource::new(&update_url);
- let options = c_to_updateoptions_opt(p_options);
- let locator = c_to_velopacklocatorconfig_opt(p_locator);
+ let options = c_to_UpdateOptions(p_options).ok();
+ let locator = c_to_VelopackLocatorConfig(p_locator).ok();
let manager = UpdateManager::new(source, options, locator)?;
unsafe { *p_manager = UpdateManagerRawPtr::new(manager) };
Ok(())
@@ -128,8 +128,8 @@ pub extern "C" fn vpkc_new_update_manager_with_source(
) -> bool {
wrap_error(|| {
let source = UpdateSourceRawPtr::get_source_clone(p_source).ok_or(anyhow!("pSource must not be null"))?;
- let options = c_to_updateoptions_opt(p_options);
- let locator = c_to_velopacklocatorconfig_opt(p_locator);
+ let options = c_to_UpdateOptions(p_options).ok();
+ let locator = c_to_VelopackLocatorConfig(p_locator).ok();
let manager = UpdateManager::new_boxed(source, options, locator)?;
unsafe { *p_manager = UpdateManagerRawPtr::new(manager) };
Ok(())
@@ -181,11 +181,11 @@ pub extern "C" fn vpkc_is_portable(p_manager: *mut vpkc_update_manager_t) -> boo
#[no_mangle]
#[logfn(Trace)]
#[logfn_inputs(Trace)]
-pub extern "C" fn vpkc_update_pending_restart(p_manager: *mut vpkc_update_manager_t, p_asset: *mut vpkc_asset_t) -> bool {
+pub extern "C" fn vpkc_update_pending_restart(p_manager: *mut vpkc_update_manager_t, p_asset: *mut *mut vpkc_asset_t) -> bool {
match p_manager.to_opaque_ref() {
Some(manager) => match manager.get_update_pending_restart() {
Some(asset) => {
- unsafe { allocate_velopackasset(asset, p_asset) };
+ unsafe { *p_asset = allocate_VelopackAsset(&asset) };
true
}
None => false,
@@ -199,13 +199,14 @@ pub extern "C" fn vpkc_update_pending_restart(p_manager: *mut vpkc_update_manage
#[no_mangle]
#[logfn(Trace)]
#[logfn_inputs(Trace)]
-pub extern "C" fn vpkc_check_for_updates(p_manager: *mut vpkc_update_manager_t, p_update: *mut vpkc_update_info_t) -> vpkc_update_check_t {
+pub extern "C" fn vpkc_check_for_updates(
+ p_manager: *mut vpkc_update_manager_t,
+ p_update: *mut *mut vpkc_update_info_t,
+) -> vpkc_update_check_t {
match p_manager.to_opaque_ref() {
Some(manager) => match manager.check_for_updates() {
Ok(UpdateCheck::UpdateAvailable(info)) => {
- unsafe {
- allocate_updateinfo(info, p_update);
- }
+ unsafe { *p_update = allocate_UpdateInfo(&info) };
vpkc_update_check_t::UPDATE_AVAILABLE
}
Ok(UpdateCheck::RemoteIsEmpty) => vpkc_update_check_t::REMOTE_IS_EMPTY,
@@ -243,7 +244,7 @@ pub extern "C" fn vpkc_download_updates(
None => bail!("pManager must not be null"),
};
- let update = c_to_updateinfo_opt(p_update).ok_or(anyhow!("pUpdate must not be null"))?;
+ let update = c_to_UpdateInfo(p_update)?;
if let Some(cb_progress) = cb_progress {
let (progress_sender, progress_receiver) = std::sync::mpsc::channel::();
@@ -311,15 +312,15 @@ pub extern "C" fn vpkc_wait_exit_then_apply_updates(
None => bail!("pManager must not be null"),
};
- let asset = c_to_velopackasset_opt(p_asset).ok_or(anyhow!("pAsset must not be null"))?;
- let restart_args = c_to_string_array_opt(p_restart_args, c_restart_args).unwrap_or_default();
+ let asset = c_to_VelopackAsset(p_asset)?;
+ let restart_args = c_to_String_vec(p_restart_args, c_restart_args)?;
manager.wait_exit_then_apply_updates(&asset, b_silent, b_restart, &restart_args)?;
Ok(())
})
}
/// This will launch the Velopack updater and optionally wait for a program to exit gracefully.
-/// This method is unsafe because it does not necessarily wait for any / the correct process to exit
+/// This method is unsafe because it does not necessarily wait for any / the correct process to exit
/// before applying updates. The `vpkc_wait_exit_then_apply_updates` method is recommended for most use cases.
/// If dw_wait_pid is 0, the updater will not wait for any process to exit before applying updates (Not Recommended).
#[no_mangle]
@@ -335,13 +336,9 @@ pub extern "C" fn vpkc_unsafe_apply_updates(
c_restart_args: size_t,
) -> bool {
wrap_error(|| {
- let manager = match p_manager.to_opaque_ref() {
- Some(manager) => manager,
- None => bail!("pManager must not be null"),
- };
-
- let asset = c_to_velopackasset_opt(p_asset).ok_or(anyhow!("pAsset must not be null"))?;
- let restart_args = c_to_string_array_opt(p_restart_args, c_restart_args).unwrap_or_default();
+ let manager = p_manager.to_opaque_ref().ok_or(anyhow!("pManager must not be null"))?;
+ let asset = c_to_VelopackAsset(p_asset)?;
+ let restart_args = c_to_String_vec(p_restart_args, c_restart_args)?;
let wait_mode = if dw_wait_pid > 0 { ApplyWaitMode::WaitPid(dw_wait_pid) } else { ApplyWaitMode::NoWait };
manager.unsafe_apply_updates(&asset, b_silent, wait_mode, b_restart, &restart_args)?;
Ok(())
@@ -361,7 +358,7 @@ pub extern "C" fn vpkc_free_update_manager(p_manager: *mut vpkc_update_manager_t
#[logfn(Trace)]
#[logfn_inputs(Trace)]
pub extern "C" fn vpkc_free_update_info(p_update_info: *mut vpkc_update_info_t) {
- unsafe { free_updateinfo(p_update_info) };
+ unsafe { free_UpdateInfo(p_update_info) };
}
/// Frees a vpkc_asset_t instance.
@@ -369,7 +366,7 @@ pub extern "C" fn vpkc_free_update_info(p_update_info: *mut vpkc_update_info_t)
#[logfn(Trace)]
#[logfn_inputs(Trace)]
pub extern "C" fn vpkc_free_asset(p_asset: *mut vpkc_asset_t) {
- unsafe { free_velopackasset(p_asset) };
+ unsafe { free_VelopackAsset(p_asset) };
}
/// VelopackApp helps you to handle app activation events correctly.
@@ -439,14 +436,14 @@ pub extern "C" fn vpkc_app_run(p_user_data: *mut c_void) {
hook(p_user_data, c_string.as_ptr());
});
}
-
+
// init logging
let log_file = if let Some(locator) = &app_options.locator {
default_logfile_path(locator)
} else {
default_logfile_path(LocationContext::FromCurrentExe)
};
-
+
init_logging("lib-cpp", Some(&log_file), false, false, Some(create_shared_logger()));
app.run();
}
@@ -463,7 +460,7 @@ pub extern "C" fn vpkc_app_set_auto_apply_on_startup(b_auto_apply: bool) {
#[no_mangle]
pub extern "C" fn vpkc_app_set_args(p_args: *mut *mut c_char, c_args: size_t) {
update_app_options(|opt| {
- opt.args = c_to_string_array_opt(p_args, c_args);
+ opt.args = c_to_String_vec(p_args, c_args).ok();
});
}
@@ -471,7 +468,7 @@ pub extern "C" fn vpkc_app_set_args(p_args: *mut *mut c_char, c_args: size_t) {
#[no_mangle]
pub extern "C" fn vpkc_app_set_locator(p_locator: *mut vpkc_locator_config_t) {
update_app_options(|opt| {
- opt.locator = c_to_velopacklocatorconfig_opt(p_locator);
+ opt.locator = c_to_VelopackLocatorConfig(p_locator).ok();
});
}
diff --git a/src/lib-cpp/src/types.rs b/src/lib-cpp/src/types.rs
index 7a0f7584..82072dbc 100644
--- a/src/lib-cpp/src/types.rs
+++ b/src/lib-cpp/src/types.rs
@@ -1,3 +1,4 @@
+use anyhow::{bail, Result};
use libc::{c_char, c_void, size_t};
use std::ffi::{CStr, CString};
use std::path::PathBuf;
@@ -47,73 +48,52 @@ pub type vpkc_download_asset_delegate_t = Option<
) -> bool,
>;
-pub fn c_to_string_opt(psz: *const c_char) -> Option {
+pub fn c_to_String(psz: *const c_char) -> Result {
if psz.is_null() {
- return None;
+ bail!("Null pointer: String must be set.");
}
let cstr = unsafe { CStr::from_ptr(psz) };
- Some(String::from_utf8_lossy(cstr.to_bytes()).to_string())
+ Ok(String::from_utf8_lossy(cstr.to_bytes()).to_string())
}
-pub fn c_to_string(psz: *const c_char) -> String {
- c_to_string_opt(psz).unwrap_or_default()
+pub fn c_to_String_vec(p_args: *mut *mut c_char, c_args: size_t) -> Result> {
+ if p_args.is_null() || c_args == 0 {
+ return Ok(Vec::new());
+ }
+ let mut args = Vec::with_capacity(c_args);
+ for i in 0..c_args {
+ let arg = c_to_String(unsafe { *p_args.add(i) })?;
+ args.push(arg);
+ }
+ Ok(args)
}
-pub fn c_to_pathbuf(psz: *const c_char) -> PathBuf {
- PathBuf::from(c_to_string(psz))
+pub fn c_to_PathBuf(psz: *const c_char) -> Result {
+ c_to_String(psz).map(PathBuf::from)
}
-pub fn string_to_cstr(s: &str) -> *mut c_char {
- let cstr = CString::new(s).unwrap();
+pub fn allocate_String<'a, T: Into