mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Compare commits
38 Commits
0.0.1331-g
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d5c984c14 | ||
|
|
095567789a | ||
|
|
09f9df1d11 | ||
|
|
3df255b8a6 | ||
|
|
ea50914cea | ||
|
|
935a36c6ea | ||
|
|
84f5fb9d44 | ||
|
|
fa48e3c56c | ||
|
|
5d569607fc | ||
|
|
78e6b6f683 | ||
|
|
031bd9b63a | ||
|
|
efa9d296b0 | ||
|
|
c9c31029ff | ||
|
|
65df343dea | ||
|
|
37aa43d6cb | ||
|
|
1f5df34aff | ||
|
|
bb7dd08b99 | ||
|
|
5f2cf75f74 | ||
|
|
50c44adbc7 | ||
|
|
3ba32af42b | ||
|
|
a2c559072b | ||
|
|
023fdc5150 | ||
|
|
ef7f55691a | ||
|
|
4ba75beea8 | ||
|
|
72af62649f | ||
|
|
fee5cb2148 | ||
|
|
35d6875b42 | ||
|
|
42e3959c43 | ||
|
|
ceebea0fdf | ||
|
|
c69f0cca6f | ||
|
|
756bdc66f7 | ||
|
|
b378a6b9b9 | ||
|
|
1ae63dc1e0 | ||
|
|
2fc2597c29 | ||
|
|
2ad2c3706a | ||
|
|
989bdb4ea0 | ||
|
|
8bed8a185c | ||
|
|
9c76a8d6b3 |
1
.github/renovate.json5
vendored
1
.github/renovate.json5
vendored
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"enabled": false,
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
":semanticCommitsDisabled"
|
||||
|
||||
62
.github/workflows/build-python.yml
vendored
62
.github/workflows/build-python.yml
vendored
@@ -38,14 +38,14 @@ jobs:
|
||||
args: --release --out dist
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
manylinux: auto
|
||||
- name: Build free-threaded wheels
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
working-directory: src/lib-python
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: --release --out dist -i python3.13t
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
manylinux: auto
|
||||
# - name: Build free-threaded wheels
|
||||
# uses: PyO3/maturin-action@v1
|
||||
# with:
|
||||
# working-directory: src/lib-python
|
||||
# target: ${{ matrix.platform.target }}
|
||||
# args: --release --out dist -i python3.13t
|
||||
# sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
# manylinux: auto
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -84,14 +84,14 @@ jobs:
|
||||
args: --release --out dist
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
manylinux: musllinux_1_2
|
||||
- name: Build free-threaded wheels
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
working-directory: src/lib-python
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: --release --out dist -i python3.13t
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
manylinux: musllinux_1_2
|
||||
# - name: Build free-threaded wheels
|
||||
# uses: PyO3/maturin-action@v1
|
||||
# with:
|
||||
# working-directory: src/lib-python
|
||||
# target: ${{ matrix.platform.target }}
|
||||
# args: --release --out dist -i python3.13t
|
||||
# sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
# manylinux: musllinux_1_2
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
uses: ./.github/actions/job-setup
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.13t
|
||||
python-version: 3.x
|
||||
architecture: ${{ matrix.platform.target }}
|
||||
- name: Build wheels
|
||||
uses: PyO3/maturin-action@v1
|
||||
@@ -133,13 +133,13 @@ jobs:
|
||||
target: ${{ matrix.platform.rust_target }}
|
||||
args: --release --out dist
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
- name: Build free-threaded wheels
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
working-directory: src/lib-python
|
||||
target: ${{ matrix.platform.rust_target }}
|
||||
args: --release --out dist -i python3.13t
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
# - name: Build free-threaded wheels
|
||||
# uses: PyO3/maturin-action@v1
|
||||
# with:
|
||||
# working-directory: src/lib-python
|
||||
# target: ${{ matrix.platform.rust_target }}
|
||||
# args: --release --out dist -i python3.13t
|
||||
# sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -173,13 +173,13 @@ jobs:
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: --release --out dist
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
- name: Build free-threaded wheels
|
||||
uses: PyO3/maturin-action@v1
|
||||
with:
|
||||
working-directory: src/lib-python
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: --release --out dist -i python3.13t
|
||||
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
# - name: Build free-threaded wheels
|
||||
# uses: PyO3/maturin-action@v1
|
||||
# with:
|
||||
# working-directory: src/lib-python
|
||||
# target: ${{ matrix.platform.target }}
|
||||
# args: --release --out dist -i python3.13t
|
||||
# sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
||||
21
.github/workflows/build-samples.yml
vendored
21
.github/workflows/build-samples.yml
vendored
@@ -7,7 +7,15 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
sample: [CPlusPlusWidgets, CPlusPlusWin32, CSharpAvalonia, CSharpUno, CSharpWpf, NodeJSElectron, RustIced]
|
||||
sample:
|
||||
- CPlusPlusWidgets
|
||||
- CPlusPlusWin32
|
||||
- CSharpAvalonia
|
||||
- CSharpUno
|
||||
- CSharpWpf
|
||||
- NodeJSElectron
|
||||
- PythonWXPython
|
||||
- RustIced
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
exclude:
|
||||
- os: ubuntu-latest
|
||||
@@ -44,6 +52,16 @@ jobs:
|
||||
sudo apt-cache search libgtk*
|
||||
sudo apt install -y libwxgtk3.2-dev libgtk-3-dev
|
||||
if: ${{ matrix.sample == 'CPlusPlusWidgets' && matrix.os == 'ubuntu-latest' }}
|
||||
- name: Install uv
|
||||
run: |
|
||||
pip install uv
|
||||
if: ${{ matrix.sample == 'PythonWXPython' }}
|
||||
- name: Refresh uv.lock for wxPython
|
||||
working-directory: samples/${{ matrix.sample }}
|
||||
run: |
|
||||
rm uv.lock
|
||||
uv sync --find-links https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-24.04
|
||||
if: ${{ matrix.sample == 'PythonWXPython' && matrix.os == 'ubuntu-latest' }}
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
@@ -51,6 +69,7 @@ jobs:
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
if: ${{ startsWith(matrix.sample, 'CSharp') }}
|
||||
- name: Install VPK
|
||||
run: dotnet tool install -g vpk
|
||||
- name: Pack Sample (Windows)
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -83,13 +83,6 @@ jobs:
|
||||
mkdir -p ../lib-python
|
||||
zip -r ../lib-python/velopack_libpython_$PKG_VERSION.zip .
|
||||
|
||||
- name: test-artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-artifact
|
||||
path: lib-python/*
|
||||
retention-days: 1
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: ./repo
|
||||
@@ -223,6 +216,7 @@ jobs:
|
||||
gh release upload $currentTag (get-item ../lib-nodejs/*.tgz)
|
||||
gh release upload $currentTag (get-item ../lib-rust/*.crate)
|
||||
gh release upload $currentTag (get-item ../lib-c/*.zip)
|
||||
gh release upload $currentTag (get-item ../lib-python/*.zip)
|
||||
|
||||
- name: Publish NuGet Packages
|
||||
run: |
|
||||
|
||||
36
Cargo.lock
generated
36
Cargo.lock
generated
@@ -1948,12 +1948,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@@ -2228,29 +2225,6 @@ version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs"
|
||||
version = "10.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e640d9b0964e9d39df633548591090ab92f7a4567bc31d3891af23471a3365c6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"thiserror 2.0.12",
|
||||
"ts-rs-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ts-rs-macros"
|
||||
version = "10.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e9d8656589772eeec2cf7a8264d9cda40fb28b9bc53118ceb9e8c07f8f38730"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.103",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.18.0"
|
||||
@@ -2295,9 +2269,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fadf18427d33828c311234884b7ba2afb57143e6e7e69fda7ee883b624661e36"
|
||||
checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"http",
|
||||
@@ -2388,7 +2362,6 @@ dependencies = [
|
||||
"tempfile",
|
||||
"thiserror 2.0.12",
|
||||
"time 0.3.41",
|
||||
"ts-rs",
|
||||
"ureq",
|
||||
"url",
|
||||
"uuid",
|
||||
@@ -2476,7 +2449,6 @@ dependencies = [
|
||||
"semver",
|
||||
"serde_json",
|
||||
"simplelog",
|
||||
"ts-rs",
|
||||
"velopack",
|
||||
]
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ regex = "1.10"
|
||||
normpath = "1.3"
|
||||
bitflags = "2.9"
|
||||
rand = "0.9"
|
||||
ts-rs = "10.0"
|
||||
zstd = "0.13"
|
||||
async-std = "1.13"
|
||||
anyhow = "1.0"
|
||||
|
||||
18
README.md
18
README.md
@@ -50,3 +50,21 @@ I've used a lot of installer frameworks and Velopack is by far the best. Everyth
|
||||
|
||||
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)
|
||||
|
||||
## Sponsors
|
||||
Huge thanks to everyone who provides the project with free tools, services, or donations!
|
||||
|
||||
<div align="center">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://velopack.github.io/velopack.sponsorkit/sponsors-white.svg">
|
||||
<img alt="Sponsors Cloud" src="https://velopack.github.io/velopack.sponsorkit/sponsors-black.svg">
|
||||
</picture>
|
||||
|
||||
<span>Free tools provided by<br/></span>
|
||||
<a href="https://jb.gg/OpenSource">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://www.jetbrains.com/company/brand/img/logo_jb_dos_3.svg">
|
||||
<img alt="Jetbrains Logo" src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg" width="160">
|
||||
</picture>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -12,12 +12,17 @@ set "version=%~1"
|
||||
echo.
|
||||
echo Compiling velopack_libc...
|
||||
cargo build -p velopack_libc
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Compiling VelopackCppWidgets with cmake...
|
||||
cmake -S . -B build-rel
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
cmake --build build-rel -j --config Release
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%version%
|
||||
vpk pack -u VelopackCppWidgets -o %~dp0releases -p %~dp0build-rel\Release -e main.exe -v %*
|
||||
vpk pack -u VelopackCppWidgets -o %~dp0releases -p %~dp0build-rel\Release -e main.exe -v %*
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Find the absolute path of the script
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
@@ -15,6 +15,7 @@ if "%~1"=="" (
|
||||
echo.
|
||||
echo Building Velopack C Lib with Cargo
|
||||
cargo build -p velopack_libc
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
cd %~dp0
|
||||
|
||||
@@ -39,9 +40,11 @@ echo.
|
||||
echo Building CppWin32Sample
|
||||
cd %~dp0
|
||||
"%MSBUILD_PATH%" CppWin32Sample.sln
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo #define UPDATE_URL "REPLACE_ME" > constants.h
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%~1
|
||||
vpk pack -u VelopackCppWin32Sample -o releases -p x64\Debug -v %* -e CppWin32Sample.exe
|
||||
vpk pack -u VelopackCppWin32Sample -o releases -p x64\Debug -v %* -e CppWin32Sample.exe
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -12,7 +12,9 @@ set "version=%~1"
|
||||
echo.
|
||||
echo Compiling VelopackCSharpAvalonia with dotnet...
|
||||
dotnet publish -c Release --no-self-contained -r win-x64 -o %~dp0publish
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%version%
|
||||
vpk pack -u VelopackCSharpAvalonia -o %~dp0releases -p %~dp0publish -f net8-x64-desktop -v %*
|
||||
vpk pack -u VelopackCSharpAvalonia -o %~dp0releases -p %~dp0publish -f net8-x64-desktop -v %*
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Find the absolute path of the script
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
@@ -17,10 +17,12 @@ cd %~dp0..\..\..\
|
||||
echo.
|
||||
echo Building Velopack Rust
|
||||
cargo build --features windows
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Vpk
|
||||
dotnet build src/vpk/Velopack.Vpk/Velopack.Vpk.csproj
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
cd %~dp0..
|
||||
set "version=%~1"
|
||||
@@ -28,7 +30,9 @@ set "version=%~1"
|
||||
echo.
|
||||
echo Compiling VelopackCSharpAvalonia with dotnet...
|
||||
dotnet publish -c Release --self-contained -r win-x64 -o publish -p:UseLocalVelopack=true
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%version%
|
||||
%~dp0..\..\..\build\Debug\net8.0\vpk pack -u VelopackCSharpAvalonia -o releases -p publish -v %*
|
||||
%~dp0..\..\..\build\Debug\net8.0\vpk pack -u VelopackCSharpAvalonia -o releases -p publish -v %*
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Find the absolute path of the script
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
@@ -12,7 +12,9 @@ set "version=%~1"
|
||||
echo.
|
||||
echo Compiling CSharpUno with dotnet...
|
||||
dotnet publish -c Release --framework net9.0-desktop -o %~dp0UnoSample\publish UnoSample\UnoSample.csproj
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%version%
|
||||
vpk pack -u CSharpUno -v %version% -o %~dp0UnoSample\releases -p %~dp0UnoSample\publish --mainExe UnoSample.exe
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Check if version parameter is provided
|
||||
if [ "$#" -ne 1 ]; then
|
||||
|
||||
@@ -12,7 +12,9 @@ set "version=%~1"
|
||||
echo.
|
||||
echo Compiling VelopackCSharpWinForms with dotnet...
|
||||
dotnet publish -c Release -o %~dp0publish
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%version%
|
||||
vpk pack -u VelopackCSharpWinForms -v %version% -o %~dp0releases -p %~dp0publish -f net8-x64-desktop
|
||||
vpk pack -u VelopackCSharpWinForms -v %version% -o %~dp0releases -p %~dp0publish -f net8-x64-desktop
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -12,7 +12,9 @@ set "version=%~1"
|
||||
echo.
|
||||
echo Compiling VelopackCSharpWpf with dotnet...
|
||||
dotnet publish -c Release -o %~dp0publish
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%version%
|
||||
vpk pack -u VelopackCSharpWpf -v %version% -o %~dp0releases -p %~dp0publish -f net8-x64-desktop
|
||||
vpk pack -u VelopackCSharpWpf -v %version% -o %~dp0releases -p %~dp0publish -f net8-x64-desktop
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -14,33 +14,41 @@ cd %~dp0..\..\src\lib-nodejs
|
||||
echo.
|
||||
echo Running npm install
|
||||
call npm install
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Cleaning lib-nodejs
|
||||
call npm run clean
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Compiling lib-nodejs
|
||||
call npm run dev
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Packing lib-nodejs
|
||||
call npm pack
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
cd %~dp0
|
||||
|
||||
echo.
|
||||
echo Running npm install
|
||||
call npm install
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Installing lib-nodejs package
|
||||
call npm install ..\..\src\lib-nodejs\velopack-0.0.0.tgz
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Packing with electron-forge
|
||||
call npm run package
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Creating Velopack Release
|
||||
call vpk pack -u VelopackElectronSample -v %version% -o %~dp0releases -p %~dp0out\VelopackElectronSample-win32-x64
|
||||
call vpk pack -u VelopackElectronSample -v %version% -o %~dp0releases -p %~dp0out\VelopackElectronSample-win32-x64
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Find the absolute path of the script
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
85
samples/NodeJSElectron/package-lock.json
generated
85
samples/NodeJSElectron/package-lock.json
generated
@@ -616,9 +616,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/node-gyp/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -813,9 +813,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@electron/universal/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1317,13 +1317,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz",
|
||||
"integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==",
|
||||
"version": "24.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz",
|
||||
"integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
"undici-types": "~7.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-forge": {
|
||||
@@ -2042,9 +2042,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2181,9 +2181,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2306,9 +2306,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001721",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
|
||||
"integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
|
||||
"version": "1.0.30001723",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz",
|
||||
"integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -3760,9 +3760,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.165",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz",
|
||||
"integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==",
|
||||
"version": "1.5.167",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz",
|
||||
"integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
@@ -3788,6 +3788,16 @@
|
||||
"global-agent": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/@types/node": {
|
||||
"version": "22.15.31",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.31.tgz",
|
||||
"integrity": "sha512-jnVe5ULKl6tijxUhvQeNbQG/84fHfg+yMak02cT8QVhBx/F05rAVxCGBYYTh2EKz22D6JF5ktXuNwdx7b9iEGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
@@ -3823,6 +3833,13 @@
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/electron/node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron/node_modules/universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
@@ -7115,9 +7132,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
|
||||
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
|
||||
"version": "8.5.5",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz",
|
||||
"integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -8318,9 +8335,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socks": {
|
||||
"version": "2.8.4",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz",
|
||||
"integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==",
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz",
|
||||
"integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -8676,9 +8693,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.41.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.41.0.tgz",
|
||||
"integrity": "sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==",
|
||||
"version": "5.42.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.42.0.tgz",
|
||||
"integrity": "sha512-UYCvU9YQW2f/Vwl+P0GfhxJxbUGLwd+5QrrGgLajzWAtC/23AX0vcise32kkP7Eu0Wu9VlzzHAXkLObgjQfFlQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
@@ -9007,9 +9024,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
|
||||
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
205
samples/PythonQt/.gitignore
vendored
Normal file
205
samples/PythonQt/.gitignore
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
build/*
|
||||
dist/*
|
||||
Releases/*
|
||||
*.zip
|
||||
*.tar.gz
|
||||
VelopackPythonSampleApp-win-Portable/*
|
||||
.python-version
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Velopack
|
||||
_build_config.py
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Abstra
|
||||
# Abstra is an AI-powered process automation framework.
|
||||
# Ignore directories containing user credentials, local state, and settings.
|
||||
# Learn more at https://abstra.io/docs
|
||||
.abstra/
|
||||
|
||||
# Visual Studio Code
|
||||
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||
# you could uncomment the following to ignore the entire vscode folder
|
||||
# .vscode/
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# Cursor
|
||||
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
||||
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
||||
# refer to https://docs.cursor.com/context/ignore-files
|
||||
.cursorignore
|
||||
.cursorindexingignore
|
||||
1
samples/PythonQt/_build_config.py
Normal file
1
samples/PythonQt/_build_config.py
Normal file
@@ -0,0 +1 @@
|
||||
update_url = R"D:\WinDev\Projects\velopack\samples\PythonPySide6\releases"
|
||||
36
samples/PythonQt/build.bat
Normal file
36
samples/PythonQt/build.bat
Normal file
@@ -0,0 +1,36 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
if "%~1"=="" (
|
||||
echo Version number is required.
|
||||
echo Usage: build.bat [version] [extra_args...]
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
cd %~dp0
|
||||
|
||||
echo.
|
||||
echo Installing dependencies
|
||||
uv sync --reinstall-package velopack
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo update_url = R"%~dp0releases" > _build_config.py
|
||||
|
||||
echo.
|
||||
echo Building Python application
|
||||
uv run pyinstaller --onedir --windowed --noconfirm main.py
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%~1
|
||||
mkdir publish 2>nul
|
||||
xcopy /E /I /Y dist\main\* publish\ >nul
|
||||
vpk pack --packId VelopackPythonPySide6App --mainExe main.exe -o releases --packDir publish --packVersion %*
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Cleaning up
|
||||
rmdir /S /Q build 2>nul
|
||||
rmdir /S /Q dist 2>nul
|
||||
rmdir /S /Q publish 2>nul
|
||||
del /Q main.spec 2>nul
|
||||
30
samples/PythonQt/build.sh
Normal file
30
samples/PythonQt/build.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Version number is required."
|
||||
echo "Usage: ./build.sh [version] [extra_args...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo
|
||||
echo "Installing dependencies"
|
||||
uv sync --reinstall-package velopack || exit 1
|
||||
|
||||
echo "update_url = R\"$SCRIPT_DIR/releases\"" > _build_config.py
|
||||
|
||||
echo
|
||||
echo "Building Python application"
|
||||
uv run pyinstaller --onedir --windowed --noconfirm main.py || exit 1
|
||||
|
||||
echo
|
||||
echo "Building Velopack Release v$1"
|
||||
mkdir -p publish
|
||||
cp -r dist/main/* publish/
|
||||
vpk pack --packId VelopackPythonPySide6App --mainExe main -o releases --packDir publish --packVersion "$@" || exit 1
|
||||
|
||||
echo
|
||||
echo "Cleaning up"
|
||||
rm -rf build dist publish main.spec
|
||||
151
samples/PythonQt/main.py
Normal file
151
samples/PythonQt/main.py
Normal file
@@ -0,0 +1,151 @@
|
||||
import logging
|
||||
import sys
|
||||
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QTextEdit, QVBoxLayout, QHBoxLayout
|
||||
from PySide6.QtCore import QTimer
|
||||
|
||||
import velopack
|
||||
from _build_config import update_url
|
||||
|
||||
class BufferedLogHandler(logging.Handler):
|
||||
"""Buffers log messages and provides access to them"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.buffer = []
|
||||
|
||||
def emit(self, record):
|
||||
msg = self.format(record)
|
||||
self.buffer.append(msg)
|
||||
|
||||
def get_messages(self):
|
||||
"""Get all buffered messages and clear the buffer"""
|
||||
messages = self.buffer[:]
|
||||
self.buffer.clear()
|
||||
return messages
|
||||
|
||||
# Global buffered handler
|
||||
log_handler = BufferedLogHandler()
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setWindowTitle("Velopack Sample")
|
||||
self.resize(600, 400)
|
||||
|
||||
# create velopacks update manager
|
||||
self.update_manager = None
|
||||
self.update_info = None
|
||||
|
||||
# Create central widget and main layout
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
# Create buttons
|
||||
self.check_btn = QPushButton("Check")
|
||||
self.download_btn = QPushButton("Download")
|
||||
self.apply_btn = QPushButton("Apply")
|
||||
|
||||
# Create log text control (multiline and read-only)
|
||||
self.log_text = QTextEdit()
|
||||
self.log_text.setReadOnly(True)
|
||||
|
||||
# Connect button events
|
||||
self.check_btn.clicked.connect(self.on_check)
|
||||
self.download_btn.clicked.connect(self.on_download)
|
||||
self.apply_btn.clicked.connect(self.on_apply)
|
||||
|
||||
# Layout
|
||||
self.setup_layout(central_widget)
|
||||
|
||||
# Start timer to check for log messages
|
||||
self.timer = QTimer(self)
|
||||
self.timer.timeout.connect(self.on_timer)
|
||||
self.timer.start(5) # 5ms interval
|
||||
|
||||
logging.info("GUI initialized and ready")
|
||||
|
||||
def on_timer(self):
|
||||
"""Check for new log messages and add them to text control"""
|
||||
messages = log_handler.get_messages()
|
||||
for msg in messages:
|
||||
self.log_text.append(f"{msg}")
|
||||
|
||||
def setup_layout(self, widget):
|
||||
# Create layouts
|
||||
main_layout = QVBoxLayout()
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
# Add buttons to horizontal layout
|
||||
button_layout.addWidget(self.check_btn)
|
||||
button_layout.addWidget(self.download_btn)
|
||||
button_layout.addWidget(self.apply_btn)
|
||||
button_layout.addStretch() # Add stretch to align buttons to left
|
||||
|
||||
# Add to main layout
|
||||
main_layout.addLayout(button_layout)
|
||||
main_layout.addWidget(self.log_text)
|
||||
|
||||
widget.setLayout(main_layout)
|
||||
|
||||
def on_check(self):
|
||||
try:
|
||||
self.update_manager = velopack.UpdateManager(update_url)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to initialize update manager: {e}")
|
||||
return
|
||||
self.update_info = self.update_manager.check_for_updates()
|
||||
if self.update_info:
|
||||
logging.info(f"Update available: {self.update_info}")
|
||||
else:
|
||||
logging.info("No updates available")
|
||||
|
||||
|
||||
def on_download(self):
|
||||
if not self.update_info:
|
||||
logging.warning("No update information available. Please check first.")
|
||||
return
|
||||
|
||||
try:
|
||||
self.update_manager.download_updates(self.update_info)
|
||||
logging.info("Update downloaded successfully")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to download update: {e}")
|
||||
|
||||
def on_apply(self):
|
||||
if not self.update_info:
|
||||
logging.warning("No update information available. Please check first.")
|
||||
return
|
||||
|
||||
try:
|
||||
self.update_manager.apply_updates_and_restart(self.update_info)
|
||||
logging.info("Update applied successfully")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to apply update: {e}")
|
||||
|
||||
def setup_logging():
|
||||
"""Setup logging to use buffered handler"""
|
||||
logger = logging.getLogger()
|
||||
|
||||
# Remove existing handlers
|
||||
for handler in logger.handlers[:]:
|
||||
logger.removeHandler(handler)
|
||||
|
||||
# Setup our buffered handler
|
||||
formatter = logging.Formatter('- %(levelname)s - %(message)s')
|
||||
log_handler.setFormatter(formatter)
|
||||
log_handler.setLevel(logging.INFO)
|
||||
|
||||
logger.addHandler(log_handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Setup logging before velopack runs
|
||||
setup_logging()
|
||||
|
||||
# Run velopack early
|
||||
velopack.App().run()
|
||||
|
||||
# Create and run the Qt app
|
||||
app = QApplication(sys.argv)
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
18
samples/PythonQt/pyproject.toml
Normal file
18
samples/PythonQt/pyproject.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[project]
|
||||
name = "pythonqt"
|
||||
version = "0.1.0"
|
||||
description = "Velopack sample app using PySide6 (Qt6)"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"velopack",
|
||||
"PySide6>=6.9",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
velopack = { path = "../../src/lib-python" }
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pyinstaller>=6.14.1",
|
||||
]
|
||||
221
samples/PythonQt/uv.lock
generated
Normal file
221
samples/PythonQt/uv.lock
generated
Normal file
@@ -0,0 +1,221 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.9"
|
||||
|
||||
[[package]]
|
||||
name = "altgraph"
|
||||
version = "0.17.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/de/a8/7145824cf0b9e3c28046520480f207df47e927df83aa9555fb47f8505922/altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406", size = 48418, upload-time = "2023-09-25T09:04:52.164Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/3f/3bc3f1d83f6e4a7fcb834d3720544ca597590425be5ba9db032b2bf322a2/altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff", size = 21212, upload-time = "2023-09-25T09:04:50.691Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "8.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "zipp" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macholib"
|
||||
version = "1.16.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "altgraph" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/95/ee/af1a3842bdd5902ce133bd246eb7ffd4375c38642aeb5dc0ae3a0329dfa2/macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30", size = 59309, upload-time = "2023-09-25T09:10:16.155Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/5d/c059c180c84f7962db0aeae7c3b9303ed1d73d76f2bfbc32bc231c8be314/macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c", size = 38094, upload-time = "2023-09-25T09:10:14.188Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "25.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pefile"
|
||||
version = "2023.2.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/c5/3b3c62223f72e2360737fd2a57c30e5b2adecd85e70276879609a7403334/pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc", size = 74854, upload-time = "2023-02-07T12:23:55.958Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/55/26/d0ad8b448476d0a1e8d3ea5622dc77b916db84c6aa3cb1e1c0965af948fc/pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6", size = 71791, upload-time = "2023-02-07T12:28:36.678Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller"
|
||||
version = "6.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "altgraph" },
|
||||
{ name = "importlib-metadata", marker = "python_full_version < '3.10'" },
|
||||
{ name = "macholib", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pefile", marker = "sys_platform == 'win32'" },
|
||||
{ name = "pyinstaller-hooks-contrib" },
|
||||
{ name = "pywin32-ctypes", marker = "sys_platform == 'win32'" },
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/64/17/b2bb4de22650adbeef401fa82a1b43028976547a8728602e4d29735b455e/pyinstaller-6.15.0.tar.gz", hash = "sha256:a48fc4644ee4aa2aa2a35e7b51f496f8fbd7eecf6a2150646bbf1613ad07bc2d", size = 4331521, upload-time = "2025-08-03T18:33:35.709Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/24/dd/d5c8a127446adda954f68ea7fac22772f7ab8656ad4b06df396d82574ca9/pyinstaller-6.15.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:9f00c71c40148cd1e61695b2c6f1e086693d3bcf9bfa22ab513aa4254c3b966f", size = 1016981, upload-time = "2025-08-03T18:31:52.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/2a/7b50593b419db43e48d9bdeebaac0ff92a5fe035f3c30f87ca3e1650d7e2/pyinstaller-6.15.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:cbcc8eb77320c60722030ac875883b564e00768fe3ff1721c7ba3ad0e0a277e9", size = 726337, upload-time = "2025-08-03T18:31:57.592Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/83/7f498fba0154c57eb5fc93eb9680a2dbadb9f780a3389fb85b8d79683378/pyinstaller-6.15.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c33e6302bc53db2df1104ed5566bd980b3e0ee7f18416a6e3caa908c12a54542", size = 737539, upload-time = "2025-08-03T18:32:02.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/d6/e4477feab7c8379fb49e7ec95c82d0a69ad88f6ccc247f76bef3cb0e3432/pyinstaller-6.15.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:eb902d0fed3bb1f8b7190dc4df5c11f3b59505767e0d56d1ed782b853938bbf3", size = 735426, upload-time = "2025-08-03T18:32:06.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/7e/ff25648276f15e2e77fc563d36d8cfcd917e077bf2a172420df3588601b4/pyinstaller-6.15.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:b4df862adae7cf1f08eff53c43ace283822447f7f528f72e4f94749062712f15", size = 732210, upload-time = "2025-08-03T18:32:21.667Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/3d/267a7dddd0647de95d260780050ccd8228ab29d2b9edea54ed1f56800967/pyinstaller-6.15.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:b9ebf16ed0f99016ae8ae5746dee4cb244848a12941539e62ce2eea1df5a3f95", size = 732194, upload-time = "2025-08-03T18:32:29.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/61/962b2eb79ef225233e2d6e04600e998935328011dfb2fa775b1dd16b943a/pyinstaller-6.15.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:22193489e6a22435417103f61e7950363bba600ef36ec3ab1487303668c81092", size = 731256, upload-time = "2025-08-03T18:32:36.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/5e/4e20e1c0e5791b09b69bef3ac921fd0cd25551b56879324ad999b92fa045/pyinstaller-6.15.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:18f743069849dbaee3e10900385f35795a5743eabab55e99dcc42f204e40a0db", size = 731148, upload-time = "2025-08-03T18:32:41.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/31/28956c534991f289e2f981c715730b6241e75dc6295737a8cbd050a0cc8c/pyinstaller-6.15.0-py3-none-win32.whl", hash = "sha256:60da8f1b5071766b45c0f607d8bc3d7e59ba2c3b262d08f2e4066ba65f3544a2", size = 1312297, upload-time = "2025-08-03T18:32:50.572Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/ab/6a45186c7f8e34c422faecd72580116a67d068158c57faa2d2f6d01faa7f/pyinstaller-6.15.0-py3-none-win_amd64.whl", hash = "sha256:cbea297e16eeda30b41c300d6ec2fd2abea4dbd8d8a32650eeec36431c94fcd9", size = 1373091, upload-time = "2025-08-03T18:32:58.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/86/72159af032b9db36f2470a3b085f79277ec1c38e7e48f8c5dc1ed16dc4e1/pyinstaller-6.15.0-py3-none-win_arm64.whl", hash = "sha256:f43c035621742cf2d19b84308c60e4e44e72c94786d176b8f6adcde351b5bd98", size = 1314305, upload-time = "2025-08-03T18:33:05.557Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller-hooks-contrib"
|
||||
version = "2025.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "importlib-metadata", marker = "python_full_version < '3.10'" },
|
||||
{ name = "packaging" },
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/71/d6/e5b378b7d4add8c879295c531309b0320e9c07a70458665d091760ffdc87/pyinstaller_hooks_contrib-2025.8.tar.gz", hash = "sha256:3402ad41dfe9b5110af134422e37fc5d421ba342c6cb980bd67cb30b7415641c", size = 164214, upload-time = "2025-07-27T16:37:31.943Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/48/34/1d973d0dae849683e53fbcda84443ce016f315e6f4dc7605ede4f56a28c3/pyinstaller_hooks_contrib-2025.8-py3-none-any.whl", hash = "sha256:8d0b8cfa0cb689a619294ae200497374234bd4e3994b3ace2a4442274c899064", size = 442346, upload-time = "2025-07-27T16:37:30.268Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyside6"
|
||||
version = "6.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyside6-addons" },
|
||||
{ name = "pyside6-essentials" },
|
||||
{ name = "shiboken6" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/91/8e9c7f7e90431297de9856e90a156ade9420977e26d87996909c63f30bd2/PySide6-6.9.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:f843ef39970a2f79757810fffd7b8e93ac42a3de9ea62f2a03648cde57648aed", size = 558097, upload-time = "2025-06-03T13:20:03.739Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ff/04d1b6b30edd24d761cc30d964860f997bdf37d06620694bf9aab35eec3a/PySide6-6.9.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:db44ac08b8f7ac1b421bc1c6a44200d03f08d80dc7b3f68dfdb1684f30f41c17", size = 558239, upload-time = "2025-06-03T13:20:06.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b4/ca076c55c11a8e473363e05aa82c5c03dd7ba8f17b77cc9311ce17213193/PySide6-6.9.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:531a6e67c429b045674d57fe9864b711eb59e4cded753c2640982e368fd468d1", size = 558239, upload-time = "2025-06-03T13:20:08.257Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/ff/95c941f53b0faebc27dbe361d8e971b77f504b9cf36f8f5d750fd82cd6fc/PySide6-6.9.1-cp39-abi3-win_amd64.whl", hash = "sha256:c82dbb7d32bbdd465e01059174f71bddc97de152ab71bded3f1907c40f9a5f16", size = 564571, upload-time = "2025-06-03T13:20:10.321Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/ef/0aa5e910fa4e9770db6b45c23e360a52313922e0ca71fc060a57db613de1/PySide6-6.9.1-cp39-abi3-win_arm64.whl", hash = "sha256:1525d63dc6dc425b8c2dc5bc01a8cb1d67530401449f3a3490c09a14c095b9f9", size = 401793, upload-time = "2025-06-03T13:20:12.108Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyside6-addons"
|
||||
version = "6.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyside6-essentials" },
|
||||
{ name = "shiboken6" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/e2/39b9e04335d7ac782b6459bf7abec90c36b8efaac5a88ef818e972c59387/PySide6_Addons-6.9.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:7be0708fa89715c282541fca47e2ba97c0c8d2886e0236ef994b2dd8f52aacdd", size = 316212438, upload-time = "2025-06-03T13:06:15.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/6f/691d7039a6f7943522a770b713ecd85fa169688dfdd65ddd4db1699d01b6/PySide6_Addons-6.9.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:da7869b02e3599d26546fad582db4656060786bc5ec8ece5ec9ee8aa8b42371c", size = 166690468, upload-time = "2025-06-03T13:06:34.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/08/a264db09ad35819643d910cd4c73a86f72f23b7092f8ebc7e51dcca53a86/PySide6_Addons-6.9.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:53fd08c8152b6ba8c435458afd189835ba905793a5077a2bb0b1b11222b375d4", size = 162466096, upload-time = "2025-06-03T13:08:58.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/be/a849402f7e73d137b5ae8b4370a49b0cf0e0c02f028b845782cb743e4995/PySide6_Addons-6.9.1-cp39-abi3-win_amd64.whl", hash = "sha256:cd93a3a5e3886cd958f3a5acc7c061c24f10a394ce9f4ce657ac394544ca7ec2", size = 143150906, upload-time = "2025-06-03T13:09:12.762Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/f1/1bb6b5859aff4e2b3f5ef789b9cee200811a9f469f04d9aa7425e816622b/PySide6_Addons-6.9.1-cp39-abi3-win_arm64.whl", hash = "sha256:4f589631bdceb518080ae9c9fa288e64f092cd5bebe25adc8ad89e8eadd4db29", size = 26938762, upload-time = "2025-06-03T13:09:20.009Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyside6-essentials"
|
||||
version = "6.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "shiboken6" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/59/714874db9ef3bbbbda654fd3223248969bea02ec1a5bfdd1c941c4e97749/PySide6_Essentials-6.9.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:ed43435a70e018e1c22efcaf34a9430b83cfcad716dba661b03de21c13322fab", size = 132957077, upload-time = "2025-06-03T13:11:52.629Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/6a/ea0db68d40a1c487fd255634896f4e37b6560e3ef1f57ca5139bf6509b1f/PySide6_Essentials-6.9.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e5da48883f006c6206ef85874db74ddebcdf69b0281bd4f1642b1c5ac1d54aea", size = 96416183, upload-time = "2025-06-03T13:12:48.945Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/2f/4243630d1733522638c4967d36018c38719d8b84f5246bf3d4c010e0aa9d/PySide6_Essentials-6.9.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:e46a2801c9c6098025515fd0af6c594b9e9c951842f68b8f6f3da9858b9b26c2", size = 94171343, upload-time = "2025-06-03T13:12:59.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/a9/a8e0209ba9116f2c2db990cfb79f2edbd5a3a428013be2df1f1cddd660a9/PySide6_Essentials-6.9.1-cp39-abi3-win_amd64.whl", hash = "sha256:ad1ac94011492dba33051bc33db1c76a7d6f815a81c01422cb6220273b369145", size = 72435676, upload-time = "2025-06-03T13:13:08.805Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/e4/23268c57e775a1a4d2843d288a9583a47f2e4b3977a9ae93cb9ded1a4ea5/PySide6_Essentials-6.9.1-cp39-abi3-win_arm64.whl", hash = "sha256:35c2c2bb4a88db74d11e638cf917524ff35785883f10b439ead07960a5733aa4", size = 49483707, upload-time = "2025-06-03T13:13:16.399Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pythonqt"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "pyside6" },
|
||||
{ name = "velopack" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pyinstaller" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "pyside6", specifier = ">=6.9" },
|
||||
{ name = "velopack", directory = "../../src/lib-python" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "pyinstaller", specifier = ">=6.14.1" }]
|
||||
|
||||
[[package]]
|
||||
name = "pywin32-ctypes"
|
||||
version = "0.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shiboken6"
|
||||
version = "6.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/98/98/34d4d25b79055959b171420d47fcc10121aefcbb261c91d5491252830e31/shiboken6-6.9.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:40e92afc88da06b5100c56b761e59837ff282166e9531268f3d910b6128e621e", size = 406159, upload-time = "2025-06-03T13:16:45.104Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/07/53b2532ecd42ff925feb06b7bb16917f5f99f9c3470f0815c256789d818b/shiboken6-6.9.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efcdfa8655d34aaf8d7a0c7724def3440bd46db02f5ad3b1785db5f6ccb0a8ff", size = 206756, upload-time = "2025-06-03T13:16:46.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/b0/75b86ee3f7b044e6a87fbe7abefd1948ca4ae5fcde8321f4986a1d9eaa5e/shiboken6-6.9.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:efcf75d48a29ae072d0bf54b3cd5a59ae91bb6b3ab7459e17c769355486c2e0b", size = 203233, upload-time = "2025-06-03T13:16:48.264Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/56/00af281275aab4c79e22e0ea65feede0a5c6da3b84e86b21a4a0071e0744/shiboken6-6.9.1-cp39-abi3-win_amd64.whl", hash = "sha256:209ccf02c135bd70321143dcbc5023ae0c056aa4850a845955dd2f9b2ff280a9", size = 1153587, upload-time = "2025-06-03T13:16:50.454Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/ce/6ccd382fbe1a96926c5514afa6f2c42da3a9a8482e61f8dfc6068a9ca64f/shiboken6-6.9.1-cp39-abi3-win_arm64.whl", hash = "sha256:2a39997ce275ced7853defc89d3a1f19a11c90991ac6eef3435a69bb0b7ff1de", size = 1831623, upload-time = "2025-06-03T13:16:52.468Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "velopack"
|
||||
version = "0.0.1"
|
||||
source = { directory = "../../src/lib-python" }
|
||||
|
||||
[package.metadata]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "maturin", specifier = ">=1.8.6" },
|
||||
{ name = "pyinstaller", specifier = ">=6.13.0" },
|
||||
]
|
||||
test = [{ name = "pyinstaller", specifier = ">=6.13.0" }]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.23.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
|
||||
]
|
||||
205
samples/PythonWXPython/.gitignore
vendored
Normal file
205
samples/PythonWXPython/.gitignore
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
build/*
|
||||
dist/*
|
||||
Releases/*
|
||||
*.zip
|
||||
*.tar.gz
|
||||
VelopackPythonSampleApp-win-Portable/*
|
||||
.python-version
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Velopack
|
||||
_build_config.py
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# UV
|
||||
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
#uv.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||
.pdm.toml
|
||||
.pdm-python
|
||||
.pdm-build/
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Abstra
|
||||
# Abstra is an AI-powered process automation framework.
|
||||
# Ignore directories containing user credentials, local state, and settings.
|
||||
# Learn more at https://abstra.io/docs
|
||||
.abstra/
|
||||
|
||||
# Visual Studio Code
|
||||
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||
# you could uncomment the following to ignore the entire vscode folder
|
||||
# .vscode/
|
||||
|
||||
# Ruff stuff:
|
||||
.ruff_cache/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# Cursor
|
||||
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
||||
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
||||
# refer to https://docs.cursor.com/context/ignore-files
|
||||
.cursorignore
|
||||
.cursorindexingignore
|
||||
0
samples/PythonWXPython/README.md
Normal file
0
samples/PythonWXPython/README.md
Normal file
36
samples/PythonWXPython/build.bat
Normal file
36
samples/PythonWXPython/build.bat
Normal file
@@ -0,0 +1,36 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
if "%~1"=="" (
|
||||
echo Version number is required.
|
||||
echo Usage: build.bat [version] [extra_args...]
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
cd %~dp0
|
||||
|
||||
echo.
|
||||
echo Installing dependencies
|
||||
uv sync --reinstall-package velopack
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo update_url = R"%~dp0releases" > _build_config.py
|
||||
|
||||
echo.
|
||||
echo Building Python application
|
||||
uv run pyinstaller --onedir --windowed --noconfirm main.py
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%~1
|
||||
mkdir publish 2>nul
|
||||
xcopy /E /I /Y dist\main\* publish\ >nul
|
||||
vpk pack --packId VelopackPythonSampleApp --mainExe main.exe -o releases --packDir publish --packVersion %*
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Cleaning up
|
||||
rmdir /S /Q build 2>nul
|
||||
rmdir /S /Q dist 2>nul
|
||||
rmdir /S /Q publish 2>nul
|
||||
del /Q main.spec 2>nul
|
||||
45
samples/PythonWXPython/build.sh
Executable file
45
samples/PythonWXPython/build.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Find the absolute path of the script
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Check if version parameter is provided
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "Version number is required."
|
||||
echo "Usage: ./build.sh [version] [extra_args...]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
# Installing dependencies
|
||||
echo ""
|
||||
echo "Installing dependencies..."
|
||||
uv sync
|
||||
|
||||
# Generate build config
|
||||
# Note: In Python, we use r'' for raw strings. The path needs to be absolute.
|
||||
echo "update_url = r'$SCRIPT_DIR/releases'" > _build_config.py
|
||||
|
||||
# Building Python application
|
||||
echo ""
|
||||
echo "Building Python application..."
|
||||
uv run pyinstaller --onedir --windowed --noconfirm main.py
|
||||
|
||||
# Building Velopack Release
|
||||
echo ""
|
||||
echo "Building Velopack Release v$1..."
|
||||
mkdir -p publish
|
||||
cp -r dist/main/* publish/
|
||||
vpk pack --packId VelopackPythonSampleApp --mainExe main -o releases --packDir publish --packVersion "$@"
|
||||
|
||||
# Cleaning up
|
||||
echo ""
|
||||
echo "Cleaning up..."
|
||||
rm -rf build
|
||||
rm -rf dist
|
||||
rm -rf publish
|
||||
rm -f main.spec
|
||||
|
||||
echo "Done."
|
||||
185
samples/PythonWXPython/main.py
Normal file
185
samples/PythonWXPython/main.py
Normal file
@@ -0,0 +1,185 @@
|
||||
import logging
|
||||
import threading
|
||||
import wx
|
||||
|
||||
import velopack
|
||||
from _build_config import update_url
|
||||
|
||||
class BufferedLogHandler(logging.Handler):
|
||||
"""Buffers log messages and provides access to them"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.buffer = []
|
||||
|
||||
def emit(self, record):
|
||||
msg = self.format(record)
|
||||
self.buffer.append(msg)
|
||||
|
||||
def get_messages(self):
|
||||
"""Get all buffered messages and clear the buffer"""
|
||||
messages = self.buffer[:]
|
||||
self.buffer.clear()
|
||||
return messages
|
||||
|
||||
# Global buffered handler
|
||||
log_handler = BufferedLogHandler()
|
||||
|
||||
class MainFrame(wx.Frame):
|
||||
def __init__(self):
|
||||
super().__init__(None, title="Velopack Sample", size=(600, 400))
|
||||
|
||||
# create velopacks update manager
|
||||
self.update_manager = None
|
||||
self.update_info = None
|
||||
|
||||
# Create main panel
|
||||
panel = wx.Panel(self)
|
||||
|
||||
# Create buttons with minimum width to prevent text cutoff
|
||||
self.check_btn = wx.Button(panel, label="Check", size=(150, -1))
|
||||
self.download_btn = wx.Button(panel, label="Download", size=(150, -1))
|
||||
self.apply_btn = wx.Button(panel, label="Apply", size=(150, -1))
|
||||
|
||||
# Start with Download and Apply disabled
|
||||
self.download_btn.Disable()
|
||||
self.apply_btn.Disable()
|
||||
|
||||
# Create log text control (multiline and read-only)
|
||||
self.log_text = wx.TextCtrl(panel,
|
||||
style=wx.TE_MULTILINE | wx.TE_READONLY)
|
||||
|
||||
# Bind button events
|
||||
self.check_btn.Bind(wx.EVT_BUTTON, self.on_check)
|
||||
self.download_btn.Bind(wx.EVT_BUTTON, self.on_download)
|
||||
self.apply_btn.Bind(wx.EVT_BUTTON, self.on_apply)
|
||||
|
||||
# Layout
|
||||
self.setup_layout(panel)
|
||||
|
||||
# Center the frame
|
||||
self.Center()
|
||||
|
||||
# Start timer to check for log messages
|
||||
self.timer = wx.Timer(self)
|
||||
self.Bind(wx.EVT_TIMER, self.on_timer)
|
||||
self.timer.Start(5)
|
||||
|
||||
logging.info("GUI initialized and ready")
|
||||
|
||||
def on_timer(self, event):
|
||||
"""Check for new log messages and add them to text control"""
|
||||
messages = log_handler.get_messages()
|
||||
for msg in messages:
|
||||
self.log_text.AppendText(f"{msg}\n")
|
||||
|
||||
def setup_layout(self, panel):
|
||||
# Create sizers
|
||||
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
|
||||
# Add buttons to horizontal sizer
|
||||
button_sizer.Add(self.check_btn, 0, wx.ALL, 5)
|
||||
button_sizer.Add(self.download_btn, 0, wx.ALL, 5)
|
||||
button_sizer.Add(self.apply_btn, 0, wx.ALL, 5)
|
||||
|
||||
# Add to main sizer
|
||||
main_sizer.Add(button_sizer, 0, wx.ALL | wx.EXPAND, 10)
|
||||
main_sizer.Add(self.log_text, 1, wx.ALL | wx.EXPAND, 10)
|
||||
|
||||
panel.SetSizer(main_sizer)
|
||||
|
||||
def on_check(self, event):
|
||||
try:
|
||||
self.update_manager = velopack.UpdateManager(update_url)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to initialize update manager: {e}")
|
||||
return
|
||||
self.update_info = self.update_manager.check_for_updates()
|
||||
if self.update_info:
|
||||
logging.info(f"Update available: {self.update_info}")
|
||||
# Enable download and apply buttons when update is available
|
||||
self.download_btn.Enable()
|
||||
self.apply_btn.Enable()
|
||||
else:
|
||||
logging.info("No updates available")
|
||||
# Keep buttons disabled if no update
|
||||
self.download_btn.Disable()
|
||||
self.apply_btn.Disable()
|
||||
|
||||
|
||||
def on_download(self, event):
|
||||
if not self.update_info:
|
||||
logging.warning("No update information available. Please check first.")
|
||||
return
|
||||
|
||||
# Disable buttons during download
|
||||
self.download_btn.Disable()
|
||||
self.apply_btn.Disable()
|
||||
|
||||
def progress_callback(progress):
|
||||
# Update button text with progress percentage
|
||||
wx.CallAfter(self.download_btn.SetLabel, f"Downloading... {progress}%")
|
||||
|
||||
def download_thread():
|
||||
try:
|
||||
# Store original button label
|
||||
original_label = self.download_btn.GetLabel()
|
||||
|
||||
# Call download_updates with progress callback
|
||||
self.update_manager.download_updates(self.update_info, progress_callback)
|
||||
|
||||
# Restore original button label when done
|
||||
wx.CallAfter(self.download_btn.SetLabel, original_label)
|
||||
wx.CallAfter(self.download_btn.Enable)
|
||||
wx.CallAfter(self.apply_btn.Enable)
|
||||
wx.CallAfter(logging.info, "Update downloaded successfully")
|
||||
except Exception as e:
|
||||
# Restore button label on error
|
||||
wx.CallAfter(self.download_btn.SetLabel, "Download")
|
||||
wx.CallAfter(self.download_btn.Enable)
|
||||
wx.CallAfter(self.apply_btn.Enable)
|
||||
wx.CallAfter(logging.error, f"Failed to download update: {e}")
|
||||
|
||||
# Start download in a separate thread
|
||||
thread = threading.Thread(target=download_thread, daemon=True)
|
||||
thread.start()
|
||||
|
||||
def on_apply(self, event):
|
||||
if not self.update_info:
|
||||
logging.warning("No update information available. Please check first.")
|
||||
return
|
||||
|
||||
try:
|
||||
self.update_manager.apply_updates_and_restart(self.update_info)
|
||||
logging.info("Update applied successfully")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to apply update: {e}")
|
||||
|
||||
def setup_logging():
|
||||
"""Setup logging to use buffered handler"""
|
||||
logger = logging.getLogger()
|
||||
|
||||
# Remove existing handlers
|
||||
for handler in logger.handlers[:]:
|
||||
logger.removeHandler(handler)
|
||||
|
||||
# Setup our buffered handler
|
||||
formatter = logging.Formatter('- %(levelname)s - %(message)s')
|
||||
log_handler.setFormatter(formatter)
|
||||
log_handler.setLevel(logging.INFO)
|
||||
|
||||
logger.addHandler(log_handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Setup logging before velopack runs
|
||||
setup_logging()
|
||||
|
||||
# Run velopack early
|
||||
velopack.App().run()
|
||||
|
||||
# Create and run the wx app
|
||||
app = wx.App(False)
|
||||
frame = MainFrame()
|
||||
frame.Show()
|
||||
app.MainLoop()
|
||||
18
samples/PythonWXPython/pyproject.toml
Normal file
18
samples/PythonWXPython/pyproject.toml
Normal file
@@ -0,0 +1,18 @@
|
||||
[project]
|
||||
name = "pythonwxpython"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"velopack",
|
||||
"wxpython>=4.2.3",
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
velopack = { path = "../../src/lib-python" }
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pyinstaller>=6.14.1",
|
||||
]
|
||||
390
samples/PythonWXPython/uv.lock
generated
Normal file
390
samples/PythonWXPython/uv.lock
generated
Normal file
@@ -0,0 +1,390 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.9"
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.11'",
|
||||
"python_full_version == '3.10.*'",
|
||||
"python_full_version < '3.10'",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "altgraph"
|
||||
version = "0.17.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/de/a8/7145824cf0b9e3c28046520480f207df47e927df83aa9555fb47f8505922/altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406", size = 48418, upload-time = "2023-09-25T09:04:52.164Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/3f/3bc3f1d83f6e4a7fcb834d3720544ca597590425be5ba9db032b2bf322a2/altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff", size = 21212, upload-time = "2023-09-25T09:04:50.691Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "8.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "zipp" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "macholib"
|
||||
version = "1.16.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "altgraph" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/95/ee/af1a3842bdd5902ce133bd246eb7ffd4375c38642aeb5dc0ae3a0329dfa2/macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30", size = 59309, upload-time = "2023-09-25T09:10:16.155Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/5d/c059c180c84f7962db0aeae7c3b9303ed1d73d76f2bfbc32bc231c8be314/macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c", size = 38094, upload-time = "2023-09-25T09:10:14.188Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version < '3.10'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78", size = 18902015, upload-time = "2024-08-26T20:19:40.945Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/21/91/3495b3237510f79f5d81f2508f9f13fea78ebfdf07538fc7444badda173d/numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece", size = 21165245, upload-time = "2024-08-26T20:04:14.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/33/26178c7d437a87082d11019292dce6d3fe6f0e9026b7b2309cbf3e489b1d/numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04", size = 13738540, upload-time = "2024-08-26T20:04:36.784Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/31/cc46e13bf07644efc7a4bf68df2df5fb2a1a88d0cd0da9ddc84dc0033e51/numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66", size = 5300623, upload-time = "2024-08-26T20:04:46.491Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/16/7bfcebf27bb4f9d7ec67332ffebee4d1bf085c84246552d52dbb548600e7/numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b", size = 6901774, upload-time = "2024-08-26T20:04:58.173Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/a3/561c531c0e8bf082c5bef509d00d56f82e0ea7e1e3e3a7fc8fa78742a6e5/numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd", size = 13907081, upload-time = "2024-08-26T20:05:19.098Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/66/f7177ab331876200ac7563a580140643d1179c8b4b6a6b0fc9838de2a9b8/numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318", size = 19523451, upload-time = "2024-08-26T20:05:47.479Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/7f/0b209498009ad6453e4efc2c65bcdf0ae08a182b2b7877d7ab38a92dc542/numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8", size = 19927572, upload-time = "2024-08-26T20:06:17.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/df/2619393b1e1b565cd2d4c4403bdd979621e2c4dea1f8532754b2598ed63b/numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326", size = 14400722, upload-time = "2024-08-26T20:06:39.16Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/ad/77e921b9f256d5da36424ffb711ae79ca3f451ff8489eeca544d0701d74a/numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97", size = 6472170, upload-time = "2024-08-26T20:06:50.361Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/05/3442317535028bc29cf0c0dd4c191a4481e8376e9f0db6bcf29703cadae6/numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131", size = 15905558, upload-time = "2024-08-26T20:07:13.881Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448", size = 21169137, upload-time = "2024-08-26T20:07:45.345Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/d9/32de45561811a4b87fbdee23b5797394e3d1504b4a7cf40c10199848893e/numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195", size = 13703552, upload-time = "2024-08-26T20:08:06.666Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/ca/2f384720020c7b244d22508cb7ab23d95f179fcfff33c31a6eeba8d6c512/numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57", size = 5298957, upload-time = "2024-08-26T20:08:15.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a", size = 6905573, upload-time = "2024-08-26T20:08:27.185Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/72/cfc3a1beb2caf4efc9d0b38a15fe34025230da27e1c08cc2eb9bfb1c7231/numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669", size = 13914330, upload-time = "2024-08-26T20:08:48.058Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951", size = 19534895, upload-time = "2024-08-26T20:09:16.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9", size = 19937253, upload-time = "2024-08-26T20:09:46.263Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/87/f76450e6e1c14e5bb1eae6836478b1028e096fd02e85c1c37674606ab752/numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15", size = 14414074, upload-time = "2024-08-26T20:10:08.483Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/ca/0f0f328e1e59f73754f06e1adfb909de43726d4f24c6a3f8805f34f2b0fa/numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4", size = 6470640, upload-time = "2024-08-26T20:10:19.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc", size = 15910230, upload-time = "2024-08-26T20:10:43.413Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/40/2e117be60ec50d98fa08c2f8c48e09b3edea93cfcabd5a9ff6925d54b1c2/numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b", size = 20895803, upload-time = "2024-08-26T20:11:13.916Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/92/1b8b8dee833f53cef3e0a3f69b2374467789e0bb7399689582314df02651/numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e", size = 13471835, upload-time = "2024-08-26T20:11:34.779Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/19/e2793bde475f1edaea6945be141aef6c8b4c669b90c90a300a8954d08f0a/numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c", size = 5038499, upload-time = "2024-08-26T20:11:43.902Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/ff/ddf6dac2ff0dd50a7327bcdba45cb0264d0e96bb44d33324853f781a8f3c/numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c", size = 6633497, upload-time = "2024-08-26T20:11:55.09Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/21/67f36eac8e2d2cd652a2e69595a54128297cdcb1ff3931cfc87838874bd4/numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692", size = 13621158, upload-time = "2024-08-26T20:12:14.95Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/68/e9f1126d757653496dbc096cb429014347a36b228f5a991dae2c6b6cfd40/numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a", size = 19236173, upload-time = "2024-08-26T20:12:44.049Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/e9/1f5333281e4ebf483ba1c888b1d61ba7e78d7e910fdd8e6499667041cc35/numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c", size = 19634174, upload-time = "2024-08-26T20:13:13.634Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/af/a469674070c8d8408384e3012e064299f7a2de540738a8e414dcfd639996/numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded", size = 14099701, upload-time = "2024-08-26T20:13:34.851Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/3d/08ea9f239d0e0e939b6ca52ad403c84a2bce1bde301a8eb4888c1c1543f1/numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5", size = 6174313, upload-time = "2024-08-26T20:13:45.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/b5/4ac39baebf1fdb2e72585c8352c56d063b6126be9fc95bd2bb5ef5770c20/numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a", size = 15606179, upload-time = "2024-08-26T20:14:08.786Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/c1/41c8f6df3162b0c6ffd4437d729115704bd43363de0090c7f913cfbc2d89/numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c", size = 21169942, upload-time = "2024-08-26T20:14:40.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/bc/fd298f308dcd232b56a4031fd6ddf11c43f9917fbc937e53762f7b5a3bb1/numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd", size = 13711512, upload-time = "2024-08-26T20:15:00.985Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/ff/06d1aa3eeb1c614eda245c1ba4fb88c483bee6520d361641331872ac4b82/numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b", size = 5306976, upload-time = "2024-08-26T20:15:10.876Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/98/121996dcfb10a6087a05e54453e28e58694a7db62c5a5a29cee14c6e047b/numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729", size = 6906494, upload-time = "2024-08-26T20:15:22.055Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/31/9dffc70da6b9bbf7968f6551967fc21156207366272c2a40b4ed6008dc9b/numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1", size = 13912596, upload-time = "2024-08-26T20:15:42.452Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/14/78635daab4b07c0930c919d451b8bf8c164774e6a3413aed04a6d95758ce/numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd", size = 19526099, upload-time = "2024-08-26T20:16:11.048Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/4c/0eeca4614003077f68bfe7aac8b7496f04221865b3a5e7cb230c9d055afd/numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d", size = 19932823, upload-time = "2024-08-26T20:16:40.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/46/ea25b98b13dccaebddf1a803f8c748680d972e00507cd9bc6dcdb5aa2ac1/numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d", size = 14404424, upload-time = "2024-08-26T20:17:02.604Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/a6/177dd88d95ecf07e722d21008b1b40e681a929eb9e329684d449c36586b2/numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa", size = 6476809, upload-time = "2024-08-26T20:17:13.553Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/2b/7fc9f4e7ae5b507c1a3a21f0f15ed03e794c1242ea8a242ac158beb56034/numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73", size = 15911314, upload-time = "2024-08-26T20:17:36.72Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/3b/df5a870ac6a3be3a86856ce195ef42eec7ae50d2a202be1f5a4b3b340e14/numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8", size = 21025288, upload-time = "2024-08-26T20:18:07.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/97/51af92f18d6f6f2d9ad8b482a99fb74e142d71372da5d834b3a2747a446e/numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4", size = 6762793, upload-time = "2024-08-26T20:18:19.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/46/de1fbd0c1b5ccaa7f9a005b66761533e2f6a3e560096682683a223631fe9/numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c", size = 19334885, upload-time = "2024-08-26T20:18:47.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/dc/d330a6faefd92b446ec0f0dfea4c3207bb1fef3c4771d19cf4543efd2c78/numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385", size = 15828784, upload-time = "2024-08-26T20:19:11.19Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.2.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version == '3.10.*'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.11'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2e/19/d7c972dfe90a353dbd3efbbe1d14a5951de80c99c9dc1b93cd998d51dc0f/numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b", size = 20390372, upload-time = "2025-06-21T12:28:33.469Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/c7/87c64d7ab426156530676000c94784ef55676df2f13b2796f97722464124/numpy-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070", size = 21199346, upload-time = "2025-06-21T11:47:47.57Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/0e/0966c2f44beeac12af8d836e5b5f826a407cf34c45cb73ddcdfce9f5960b/numpy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae", size = 14361143, upload-time = "2025-06-21T11:48:10.766Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/31/6e35a247acb1bfc19226791dfc7d4c30002cd4e620e11e58b0ddf836fe52/numpy-2.3.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a", size = 5378989, upload-time = "2025-06-21T11:48:19.998Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/25/93b621219bb6f5a2d4e713a824522c69ab1f06a57cd571cda70e2e31af44/numpy-2.3.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e", size = 6912890, upload-time = "2025-06-21T11:48:31.376Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/60/6b06ed98d11fb32e27fb59468b42383f3877146d3ee639f733776b6ac596/numpy-2.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db", size = 14569032, upload-time = "2025-06-21T11:48:52.563Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/c9/9bec03675192077467a9c7c2bdd1f2e922bd01d3a69b15c3a0fdcd8548f6/numpy-2.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb", size = 16930354, upload-time = "2025-06-21T11:49:17.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/e2/5756a00cabcf50a3f527a0c968b2b4881c62b1379223931853114fa04cda/numpy-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93", size = 15879605, upload-time = "2025-06-21T11:49:41.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/86/a471f65f0a86f1ca62dcc90b9fa46174dd48f50214e5446bc16a775646c5/numpy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115", size = 18666994, upload-time = "2025-06-21T11:50:08.516Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/a6/482a53e469b32be6500aaf61cfafd1de7a0b0d484babf679209c3298852e/numpy-2.3.1-cp311-cp311-win32.whl", hash = "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369", size = 6603672, upload-time = "2025-06-21T11:50:19.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/fb/bb613f4122c310a13ec67585c70e14b03bfc7ebabd24f4d5138b97371d7c/numpy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff", size = 13024015, upload-time = "2025-06-21T11:50:39.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/58/2d842825af9a0c041aca246dc92eb725e1bc5e1c9ac89712625db0c4e11c/numpy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a", size = 10456989, upload-time = "2025-06-21T11:50:55.616Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/56/71ad5022e2f63cfe0ca93559403d0edef14aea70a841d640bd13cdba578e/numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d", size = 20896664, upload-time = "2025-06-21T12:15:30.845Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/65/2db52ba049813670f7f987cc5db6dac9be7cd95e923cc6832b3d32d87cef/numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29", size = 14131078, upload-time = "2025-06-21T12:15:52.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/dd/28fa3c17b0e751047ac928c1e1b6990238faad76e9b147e585b573d9d1bd/numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc", size = 5112554, upload-time = "2025-06-21T12:16:01.434Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/fc/84ea0cba8e760c4644b708b6819d91784c290288c27aca916115e3311d17/numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943", size = 6646560, upload-time = "2025-06-21T12:16:11.895Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/b2/512b0c2ddec985ad1e496b0bd853eeb572315c0f07cd6997473ced8f15e2/numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25", size = 14260638, upload-time = "2025-06-21T12:16:32.611Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/45/c51cb248e679a6c6ab14b7a8e3ead3f4a3fe7425fc7a6f98b3f147bec532/numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660", size = 16632729, upload-time = "2025-06-21T12:16:57.439Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/ff/feb4be2e5c09a3da161b412019caf47183099cbea1132fd98061808c2df2/numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952", size = 15565330, upload-time = "2025-06-21T12:17:20.638Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/6d/ceafe87587101e9ab0d370e4f6e5f3f3a85b9a697f2318738e5e7e176ce3/numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77", size = 18361734, upload-time = "2025-06-21T12:17:47.938Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/19/0fb49a3ea088be691f040c9bf1817e4669a339d6e98579f91859b902c636/numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab", size = 6320411, upload-time = "2025-06-21T12:17:58.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/3e/e28f4c1dd9e042eb57a3eb652f200225e311b608632bc727ae378623d4f8/numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76", size = 12734973, upload-time = "2025-06-21T12:18:17.601Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/a8/8a5e9079dc722acf53522b8f8842e79541ea81835e9b5483388701421073/numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30", size = 10191491, upload-time = "2025-06-21T12:18:33.585Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/bd/35ad97006d8abff8631293f8ea6adf07b0108ce6fec68da3c3fcca1197f2/numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8", size = 20889381, upload-time = "2025-06-21T12:19:04.103Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/4f/df5923874d8095b6062495b39729178eef4a922119cee32a12ee1bd4664c/numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e", size = 14152726, upload-time = "2025-06-21T12:19:25.599Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0", size = 5105145, upload-time = "2025-06-21T12:19:34.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/63/a7f7fd5f375b0361682f6ffbf686787e82b7bbd561268e4f30afad2bb3c0/numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d", size = 6639409, upload-time = "2025-06-21T12:19:45.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bf/0d/1854a4121af895aab383f4aa233748f1df4671ef331d898e32426756a8a6/numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1", size = 14257630, upload-time = "2025-06-21T12:20:06.544Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/30/af1b277b443f2fb08acf1c55ce9d68ee540043f158630d62cef012750f9f/numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1", size = 16627546, upload-time = "2025-06-21T12:20:31.002Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/ec/3b68220c277e463095342d254c61be8144c31208db18d3fd8ef02712bcd6/numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0", size = 15562538, upload-time = "2025-06-21T12:20:54.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/2b/4014f2bcc4404484021c74d4c5ee8eb3de7e3f7ac75f06672f8dcf85140a/numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8", size = 18360327, upload-time = "2025-06-21T12:21:21.053Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/8d/2ddd6c9b30fcf920837b8672f6c65590c7d92e43084c25fc65edc22e93ca/numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8", size = 6312330, upload-time = "2025-06-21T12:25:07.447Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/c8/beaba449925988d415efccb45bf977ff8327a02f655090627318f6398c7b/numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42", size = 12731565, upload-time = "2025-06-21T12:25:26.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/c3/5c0c575d7ec78c1126998071f58facfc124006635da75b090805e642c62e/numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e", size = 10190262, upload-time = "2025-06-21T12:25:42.196Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/19/a029cd335cf72f79d2644dcfc22d90f09caa86265cbbde3b5702ccef6890/numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8", size = 20987593, upload-time = "2025-06-21T12:21:51.664Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/91/8ea8894406209107d9ce19b66314194675d31761fe2cb3c84fe2eeae2f37/numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb", size = 14300523, upload-time = "2025-06-21T12:22:13.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/7f/06187b0066eefc9e7ce77d5f2ddb4e314a55220ad62dd0bfc9f2c44bac14/numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee", size = 5227993, upload-time = "2025-06-21T12:22:22.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/ec/a926c293c605fa75e9cfb09f1e4840098ed46d2edaa6e2152ee35dc01ed3/numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992", size = 6736652, upload-time = "2025-06-21T12:22:33.629Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/62/d68e52fb6fde5586650d4c0ce0b05ff3a48ad4df4ffd1b8866479d1d671d/numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c", size = 14331561, upload-time = "2025-06-21T12:22:55.056Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/ec/b74d3f2430960044bdad6900d9f5edc2dc0fb8bf5a0be0f65287bf2cbe27/numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48", size = 16693349, upload-time = "2025-06-21T12:23:20.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/15/def96774b9d7eb198ddadfcbd20281b20ebb510580419197e225f5c55c3e/numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee", size = 15642053, upload-time = "2025-06-21T12:23:43.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/57/c3203974762a759540c6ae71d0ea2341c1fa41d84e4971a8e76d7141678a/numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280", size = 18434184, upload-time = "2025-06-21T12:24:10.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/8a/ccdf201457ed8ac6245187850aff4ca56a79edbea4829f4e9f14d46fa9a5/numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e", size = 6440678, upload-time = "2025-06-21T12:24:21.596Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/7e/7f431d8bd8eb7e03d79294aed238b1b0b174b3148570d03a8a8a8f6a0da9/numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc", size = 12870697, upload-time = "2025-06-21T12:24:40.644Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/ca/af82bf0fad4c3e573c6930ed743b5308492ff19917c7caaf2f9b6f9e2e98/numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", size = 10260376, upload-time = "2025-06-21T12:24:56.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/34/facc13b9b42ddca30498fc51f7f73c3d0f2be179943a4b4da8686e259740/numpy-2.3.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3", size = 21070637, upload-time = "2025-06-21T12:26:12.518Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/b6/41b705d9dbae04649b529fc9bd3387664c3281c7cd78b404a4efe73dcc45/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b", size = 5304087, upload-time = "2025-06-21T12:26:22.294Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/b4/fe3ac1902bff7a4934a22d49e1c9d71a623204d654d4cc43c6e8fe337fcb/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7", size = 6817588, upload-time = "2025-06-21T12:26:32.939Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/ee/89bedf69c36ace1ac8f59e97811c1f5031e179a37e4821c3a230bf750142/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df", size = 14399010, upload-time = "2025-06-21T12:26:54.086Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/08/e00e7070ede29b2b176165eba18d6f9784d5349be3c0c1218338e79c27fd/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68", size = 16752042, upload-time = "2025-06-21T12:27:19.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/6b/1c6b515a83d5564b1698a61efa245727c8feecf308f4091f565988519d20/numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", size = 12927246, upload-time = "2025-06-21T12:27:38.618Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "25.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pefile"
|
||||
version = "2023.2.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/c5/3b3c62223f72e2360737fd2a57c30e5b2adecd85e70276879609a7403334/pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc", size = 74854, upload-time = "2023-02-07T12:23:55.958Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/55/26/d0ad8b448476d0a1e8d3ea5622dc77b916db84c6aa3cb1e1c0965af948fc/pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6", size = 71791, upload-time = "2023-02-07T12:28:36.678Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller"
|
||||
version = "6.14.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "altgraph" },
|
||||
{ name = "importlib-metadata", marker = "python_full_version < '3.10'" },
|
||||
{ name = "macholib", marker = "sys_platform == 'darwin'" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pefile", marker = "sys_platform == 'win32'" },
|
||||
{ name = "pyinstaller-hooks-contrib" },
|
||||
{ name = "pywin32-ctypes", marker = "sys_platform == 'win32'" },
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/d66d3a9c34349d73eb099401060e2591da8ccc5ed427e54fff3961302513/pyinstaller-6.14.1.tar.gz", hash = "sha256:35d5c06a668e21f0122178dbf20e40fd21012dc8f6170042af6050c4e7b3edca", size = 4284317, upload-time = "2025-06-08T18:45:46.367Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/f6/fa56e547fe849db4b8da0acaad6101a6382c18370c7e0f378a1cf0ea89f0/pyinstaller-6.14.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:da559cfe4f7a20a7ebdafdf12ea2a03ea94d3caa49736ef53ee2c155d78422c9", size = 999937, upload-time = "2025-06-08T18:44:26.429Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/a6/a2814978f47ae038b1ce112717adbdcfd8dfb9504e5c52437902331cde1a/pyinstaller-6.14.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:f040d1e3d42af3730104078d10d4a8ca3350bd1c78de48f12e1b26f761e0cbc3", size = 719569, upload-time = "2025-06-08T18:44:30.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/f0/86391a4c0f558aef43a7dac8f678d46f4e5b84bd133308e3ea81f7384ab9/pyinstaller-6.14.1-py3-none-manylinux2014_i686.whl", hash = "sha256:7b8813fb2d5a82ef4ceffc342ed9a11a6fc1ef21e68e833dbd8fedb8a188d3f5", size = 729824, upload-time = "2025-06-08T18:44:34.983Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/88/446814e335d937406e6e1ae4a77ed922b8eea8b90f3aaf69427a16b58ed2/pyinstaller-6.14.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e2cfdbc6dd41d19872054fc233da18856ec422a7fdea899b6985ae04f980376a", size = 727937, upload-time = "2025-06-08T18:44:38.954Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/0f/5aa891c61d303ad4a794b7e2f864aacf64fe0f6f5559e2aec0f742595fad/pyinstaller-6.14.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:a4d53b3ecb5786b097b79bda88c4089186fc1498ef7eaa6cee57599ae459241e", size = 724762, upload-time = "2025-06-08T18:44:42.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/92/e32ec0a1754852a8ed5a60f6746c6483e3da68aee97d314f3a3a99e0ed9e/pyinstaller-6.14.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c48dd257f77f61ebea2d1fdbaf11243730f2271873c88d3b5ecb7869525d3bcb", size = 724957, upload-time = "2025-06-08T18:44:46.829Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/66/1260f384e47bf939f6238f791d4cda7edb94771d2fa0a451e0edb21ac9c7/pyinstaller-6.14.1-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:5b05cbb2ffc033b4681268159b82bac94b875475c339603c7e605f00a73c8746", size = 724132, upload-time = "2025-06-08T18:44:51.081Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/8b/8570ab94ec07e0b2b1203f45840353ee76aa067a2540c97da43d43477b26/pyinstaller-6.14.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d5fd73757c8ea9adb2f9c1f81656335ba9890029ede3031835d768fde36e89f0", size = 723847, upload-time = "2025-06-08T18:44:54.896Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/43/6c68dc9e53b09ff948d6e46477932b387832bbb920c48061d734ef089368/pyinstaller-6.14.1-py3-none-win32.whl", hash = "sha256:547f7a93592e408cbfd093ce9fd9631215387dab0dbf3130351d3b0b1186a534", size = 1299744, upload-time = "2025-06-08T18:45:00.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/dd/bb8d5bcb0592f7f5d454ad308051d00ed34f8b08d5003400b825cfe35513/pyinstaller-6.14.1-py3-none-win_amd64.whl", hash = "sha256:0794290b4b56ef9d35858334deb29f36ec1e1f193b0f825212a0aa5a1bec5a2f", size = 1357625, upload-time = "2025-06-08T18:45:06.826Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/57/8a8979737980e50aa5031b77318ce783759bf25be2956317f2e1d7a65a09/pyinstaller-6.14.1-py3-none-win_arm64.whl", hash = "sha256:d9d99695827f892cb19644106da30681363e8ff27b8326ac8416d62890ab9c74", size = 1298607, upload-time = "2025-06-08T18:45:12.766Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller-hooks-contrib"
|
||||
version = "2025.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "importlib-metadata", marker = "python_full_version < '3.10'" },
|
||||
{ name = "packaging" },
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5f/ff/e3376595935d5f8135964d2177cd3e3e0c1b5a6237497d9775237c247a5d/pyinstaller_hooks_contrib-2025.5.tar.gz", hash = "sha256:707386770b8fe066c04aad18a71bc483c7b25e18b4750a756999f7da2ab31982", size = 163124, upload-time = "2025-06-08T18:47:53.26Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/2c/b4d317534e17dd1df95c394d4b37febb15ead006a1c07c2bb006481fb5e7/pyinstaller_hooks_contrib-2025.5-py3-none-any.whl", hash = "sha256:ebfae1ba341cb0002fb2770fad0edf2b3e913c2728d92df7ad562260988ca373", size = 437246, upload-time = "2025-06-08T18:47:51.516Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pythonwxpython"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "velopack" },
|
||||
{ name = "wxpython" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pyinstaller" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "velopack", directory = "../../src/lib-python" },
|
||||
{ name = "wxpython", specifier = ">=4.2.3" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "pyinstaller", specifier = ">=6.14.1" }]
|
||||
|
||||
[[package]]
|
||||
name = "pywin32-ctypes"
|
||||
version = "0.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "velopack"
|
||||
version = "0.0.1"
|
||||
source = { directory = "../../src/lib-python" }
|
||||
|
||||
[package.metadata]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "maturin", specifier = ">=1.8.6" },
|
||||
{ name = "pyinstaller", specifier = ">=6.13.0" },
|
||||
]
|
||||
test = [{ name = "pyinstaller", specifier = ">=6.13.0" }]
|
||||
|
||||
[[package]]
|
||||
name = "wxpython"
|
||||
version = "4.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" },
|
||||
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" },
|
||||
{ name = "numpy", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4c/d9/4451392d3d6ba45aa23aa77a6f1a9970b43351b956bf61e10fd513a1dc38/wxPython-4.2.3.tar.gz", hash = "sha256:20d6e0c927e27ced85643719bd63e9f7fd501df6e9a8aab1489b039897fd7c01", size = 58861286, upload-time = "2025-04-10T02:49:43.557Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/ee/883048ff3c8e83562a160c43a976034efaa7c502138774db9767679d648d/wxpython-4.2.3-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:80df5158129577b8b1153b9af28ef18cf738a8f200e87c836a1dfc9ca61f86b7", size = 18751324, upload-time = "2025-04-10T02:48:38.712Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/1d/2d26018397150818879a00be5aa66371877c39080d65edcf95674e9833ea/wxpython-4.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c8ce9223d256b69815ef2c64842fb6a70303ab46d262b601382adff053779ab3", size = 17844363, upload-time = "2025-04-10T02:48:42.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/a7/30946564eb241c02bf30c262114f1bf5540fdcc376f46245d2a5703ae9de/wxpython-4.2.3-cp310-cp310-win32.whl", hash = "sha256:d2cf6a99ec39440298a2c6fbbfd95e386f0ad7d56ae7880553c1ae45709c091a", size = 14791534, upload-time = "2025-04-10T02:48:45.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/48/b7f73096a5912033020d8c9ac1826c4f840724216253e2f95d575b50b62c/wxpython-4.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:8e729d3110a6ed5f6520371bb3cd5f05f993f6b40d5f80ec6446b8678f2fc2ac", size = 16819235, upload-time = "2025-04-10T02:48:48.055Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/f9/e9c38a0231d993810b8b4bc2f4e12a3162a3eb2d4d51788022f054f60a75/wxpython-4.2.3-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a66b0d6fe1d7e8e133fdfdee3cae95f70cc433929f36af08f377e103584f49c", size = 18746309, upload-time = "2025-04-10T02:48:51.12Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/43/e6dd8277465e03a372127d610dd7223de9126eb42fea381747ea67a91ebd/wxpython-4.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84a01d90c4514d738a05d9045f62b1f1850fbe8d967b4ae545ba090e74cb1216", size = 17841378, upload-time = "2025-04-10T02:48:54.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/28/18fc80c1ae7bdbbb2c03f6bc995b328b3518e5b3cd69a01fa5354b9acfa4/wxpython-4.2.3-cp311-cp311-win32.whl", hash = "sha256:4e5028d7092701ab20b3bef4547d6a7d528d82f12192d72595eeb98b2ebe6364", size = 14496540, upload-time = "2025-04-10T02:48:57.311Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/8a/beb38cf4c74a6d8587372aef86c00dde6fec2c8d88292b8e36389aa9dc73/wxpython-4.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:9040fe6ae7e0fd1b33c7020c392a08f94d205614a24e23b9c7a3a74a9836140d", size = 16562662, upload-time = "2025-04-10T02:48:59.804Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/2f/550022808bcf4cfafc94021d3f77fec2ceccfc21d37cc2ce465027802f87/wxpython-4.2.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c007b153ebf74a8429789a5dcb93c76b3901c531b1413695fdb96f222ec207fc", size = 18792609, upload-time = "2025-04-10T02:49:02.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/aa/86bf3300c921d81f59ccebcb919ca7516ca7ea2b560eab36ac45e1b9931d/wxpython-4.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a7c95c385895b94b4784a78c06a1626329c3552fcc47a78ab88f0a02ffe1e2db", size = 17851857, upload-time = "2025-04-10T02:49:05.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/63/40700ad4a43962e31adf754d420d6b2a5e2d50fa5e1041a01ed73b2b0e90/wxpython-4.2.3-cp312-cp312-win32.whl", hash = "sha256:361db46442376ba1cae4ce9f8fab4081b4d085458f973b4c10b68e04492067ad", size = 14505417, upload-time = "2025-04-10T02:49:08.993Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/25/ca90e9dc793c328fb97cc011ae92d48337c1a8ef8c54576979840d74226f/wxpython-4.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:9231853d8a15b0610a6153cbef65f392164c17f234c65916df499619f7e75bd9", size = 16567404, upload-time = "2025-04-10T02:49:12.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/d9/da813737843fe4290d63061f8c77d172a3c3f9242a2d3590ecec4ff91d6d/wxpython-4.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:718a1560e341b5c4755fe9e8a431a1c6796a9d742a4bfce7ebd90d8a71ac0dd4", size = 18796223, upload-time = "2025-04-10T02:49:15.582Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/b5/f65ba11cd6b1de8279085fba287ec869a35eb122743d620a58d65d54a177/wxpython-4.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a367e4242ae83aedbaf2728f622be8ee7aec4721eb4254fe8cf2d86f893bc5", size = 17853488, upload-time = "2025-04-10T02:49:18.412Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/42/fe653ffb7817d09cbc146bb67ace7fc690bdbe2739bbe472f99d8c51b01c/wxpython-4.2.3-cp313-cp313-win32.whl", hash = "sha256:676aeb82d64d3d3cb94210e882a508bb1013de5fb55917f54f8dd2c1483f9110", size = 14507572, upload-time = "2025-04-10T02:49:20.927Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/5c/1692523ab503b34065add84f184e1b0e4b6af6b5bde6447666a0d192b29d/wxpython-4.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:dac14ea1b04d90b403414f0401704beecae0d3e7143755a20da0ac2cfec02bf9", size = 16566260, upload-time = "2025-04-10T02:49:24.378Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/77/0baf8a17812185c15b47fad9acf19cdb609aacdccc7b7ba744de11797323/wxpython-4.2.3-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0b1b5ac5ced6bc46a4bf9041d16b3e35373a5a0c1dddac9384b59c43d06cc294", size = 18751292, upload-time = "2025-04-10T02:49:27.46Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/73/8e041128db1765aa456a9ff1360dd9cf67f7255156c5cedc11f2bc9e6023/wxpython-4.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0f73aebf960f0ec6961454841deed242c2d852066ab2c538e617c5eabd95bd7b", size = 17844562, upload-time = "2025-04-10T02:49:30.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/b3/044da69a38ebb3637ed15bb52466f0c601f892822e5fdd5a17c8835ed323/wxpython-4.2.3-cp39-cp39-win32.whl", hash = "sha256:23afd08aa530a5ede0bcee0526ce185e38e28374ef5c3d2f65f058c1d7204f67", size = 14795524, upload-time = "2025-04-10T02:49:34.12Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/1a/0940baecfb919f31fab688ebc33efe9dbc43c69f5237921e8e1132967f34/wxpython-4.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:f9d5a08199adb8e66ac15bdd494b398f5fa53e7a31ecd9dc07f522265d61aa47", size = 16820318, upload-time = "2025-04-10T02:49:37.535Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.23.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
|
||||
]
|
||||
@@ -7,4 +7,5 @@
|
||||
- [**C# / Uno**](CSharpUno) - Velopack in a cross-platform app with [Uno Platform](https://github.com/unoplatform/uno).
|
||||
- [**C# / Wpf**](CSharpWpf) - Velopack with WPF on Windows.
|
||||
- [**NodeJS / Electron**](NodeJSElectron) - Velopack in a cross-platform JavaScript app with [Electron](https://www.electronjs.org/).
|
||||
- [**Python / WXPython**](PythonWXPython) - Velopack in a cross-platform python app with the [WXPython](https://wxpython.org/) ui framework.
|
||||
- [**Rust / Iced**](RustIced) - Velopack in a cross-platform app with [Iced](https://github.com/iced-rs/iced).
|
||||
|
||||
152
samples/RustIced/Cargo.lock
generated
152
samples/RustIced/Cargo.lock
generated
@@ -20,9 +20,9 @@ checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
@@ -282,7 +282,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -344,7 +344,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -458,7 +458,7 @@ checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -495,9 +495,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.26"
|
||||
version = "1.2.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
|
||||
checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -512,9 +512,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
@@ -847,7 +847,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -921,7 +921,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1004,9 +1004,9 @@ checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.11"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147"
|
||||
checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
|
||||
dependencies = [
|
||||
"enumflags2_derive",
|
||||
"serde",
|
||||
@@ -1014,13 +1014,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2_derive"
|
||||
version = "0.7.11"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79"
|
||||
checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1179,7 +1179,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1267,7 +1267,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1328,7 +1328,7 @@ checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1513,9 +1513,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
@@ -1943,9 +1943,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
version = "0.2.173"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
@@ -1964,7 +1964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.53.0",
|
||||
"windows-targets 0.53.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1981,7 +1981,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"libc",
|
||||
"redox_syscall 0.5.12",
|
||||
"redox_syscall 0.5.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2053,9 +2053,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
@@ -2092,9 +2092,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
@@ -2228,7 +2228,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2524,7 +2524,7 @@ dependencies = [
|
||||
"by_address",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2576,7 +2576,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.5.12",
|
||||
"redox_syscall 0.5.13",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
@@ -2623,7 +2623,7 @@ dependencies = [
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2652,7 +2652,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2911,9 +2911,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.12"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
|
||||
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
@@ -3168,7 +3168,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3191,7 +3191,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3264,12 +3264,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
@@ -3351,7 +3348,7 @@ dependencies = [
|
||||
"objc2-foundation",
|
||||
"objc2-quartz-core",
|
||||
"raw-window-handle",
|
||||
"redox_syscall 0.5.12",
|
||||
"redox_syscall 0.5.13",
|
||||
"rustix 0.38.44",
|
||||
"tiny-xlib",
|
||||
"wasm-bindgen",
|
||||
@@ -3426,9 +3423,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
version = "2.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3443,7 +3440,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3503,7 +3500,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3514,17 +3511,16 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3627,7 +3623,7 @@ checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3786,9 +3782,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fadf18427d33828c311234884b7ba2afb57143e6e7e69fda7ee883b624661e36"
|
||||
checksum = "59db78ad1923f2b1be62b6da81fe80b173605ca0d57f85da2e005382adf693f7"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"http",
|
||||
@@ -3841,7 +3837,7 @@ checksum = "26b682e8c381995ea03130e381928e0e005b7c9eb483c6c8682f50e07b33c2b7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3879,7 +3875,7 @@ dependencies = [
|
||||
"ureq",
|
||||
"url",
|
||||
"uuid",
|
||||
"windows 0.61.1",
|
||||
"windows 0.61.3",
|
||||
"xml",
|
||||
"zip",
|
||||
]
|
||||
@@ -3919,9 +3915,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
@@ -3954,7 +3950,7 @@ dependencies = [
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -3989,7 +3985,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -4335,9 +4331,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.61.1"
|
||||
version = "0.61.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
|
||||
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core 0.61.2",
|
||||
@@ -4396,7 +4392,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4407,14 +4403,14 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
@@ -4519,9 +4515,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.0"
|
||||
version = "0.53.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
|
||||
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
@@ -4776,9 +4772,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.10"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
|
||||
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -4915,7 +4911,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -4966,7 +4962,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
@@ -5004,7 +5000,7 @@ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5024,7 +5020,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -5064,7 +5060,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5121,7 +5117,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
@@ -5133,5 +5129,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.101",
|
||||
"syn 2.0.103",
|
||||
]
|
||||
|
||||
@@ -12,9 +12,16 @@ cd %~dp0
|
||||
echo.
|
||||
echo Building Iced/Rust
|
||||
cargo build
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo.
|
||||
echo Building Velopack Release v%~1
|
||||
|
||||
mkdir publish
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
move target\debug\velorusticedsample.exe publish\velorusticedsample.exe
|
||||
vpk pack -u VeloRustIcedSample -o releases -p publish -v %*
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
vpk pack -u VeloRustIcedSample -o releases -p publish -v %*
|
||||
if errorlevel 1 exit /b 1
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Find the absolute path of the script
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
@@ -55,16 +55,16 @@ var types = new List<TypeMap>() {
|
||||
TypeMap.RustStruct("VelopackLocatorConfig", "vpkc_locator_config_t"),
|
||||
TypeMap.SystemType("String", "char", "string", "c_char"),
|
||||
TypeMap.SystemType("PathBuf", "char", "string", "c_char"),
|
||||
TypeMap.Primitive("bool", "bool"),
|
||||
TypeMap.Primitive("i32", "int32_t"),
|
||||
TypeMap.Primitive("i64", "int64_t"),
|
||||
TypeMap.Primitive("u32", "uint32_t"),
|
||||
TypeMap.Primitive("u64", "uint64_t"),
|
||||
TypeMap.Primitive("bool", "bool", "boolean"),
|
||||
TypeMap.Primitive("i32", "int32_t", "number"),
|
||||
TypeMap.Primitive("i64", "int64_t", "number"),
|
||||
TypeMap.Primitive("u32", "uint32_t", "number"),
|
||||
TypeMap.Primitive("u64", "uint64_t", "number"),
|
||||
}.ToDictionary(v => v.rustType, v => v);
|
||||
|
||||
var handlebarData = availableStructs.Select(s => {
|
||||
var fields = s.Fields.Select(f => {
|
||||
var isString = types[f.Type].rustType == "PathBuf" || types[f.Type].rustType == "String";
|
||||
//var isString = types[f.Type].rustType == "PathBuf" || types[f.Type].rustType == "String";
|
||||
var field = new RustStruct_Field {
|
||||
rust_comment = f.DocComment.ToRustComment(),
|
||||
cpp_comment = f.DocComment.ToCppComment(),
|
||||
@@ -74,6 +74,7 @@ var handlebarData = availableStructs.Select(s => {
|
||||
field_rust_type = f.Type,
|
||||
field_c_type = types[f.Type].interopType,
|
||||
field_cpp_type = types[f.Type].cppType,
|
||||
field_node_type = types[f.Type].nodeType,
|
||||
field_system = types[f.Type].system,
|
||||
field_primitive = types[f.Type].primitive,
|
||||
field_normal = !f.Vec && !types[f.Type].primitive,
|
||||
@@ -97,24 +98,30 @@ var handlebarData = availableStructs.Select(s => {
|
||||
return stru;
|
||||
}).ToArray();
|
||||
|
||||
// --- rust generation ---
|
||||
string rustTypes = Path.Combine(libcppDir, "src", "types.rs");
|
||||
var rustCTypesTemplate = Handlebars.Compile(File.ReadAllText(Path.Combine(templatesDir, "rust_types.hbs")));
|
||||
var rustCTypes = rustCTypesTemplate(handlebarData);
|
||||
Util.ReplaceTextInFile(rustTypes, "RUST_TYPES", rustCTypes.ToString().ReplaceLineEndings("\n"));
|
||||
|
||||
// --- C++ generation ---
|
||||
string rustCppInclude = Path.Combine(libcppDir, "include", "Velopack.hpp");
|
||||
var cppTypesTemplate = Handlebars.Compile(File.ReadAllText(Path.Combine(templatesDir, "cpp_mapping.hbs")));
|
||||
var cppTypes = cppTypesTemplate(handlebarData);
|
||||
|
||||
Console.WriteLine("Writing all to file");
|
||||
Util.ReplaceTextInFile(rustTypes, "RUST_TYPES", rustCTypes.ToString().ReplaceLineEndings("\n"));
|
||||
Util.ReplaceTextInFile(rustCppInclude, "CPP_TYPES", cppTypes.ToString().ReplaceLineEndings("\n"));
|
||||
|
||||
// --- Python asset.rs generation ---
|
||||
// --- python generation ---
|
||||
string pythonAssetRs = Path.Combine(scriptsDir, "..", "lib-python", "src", "types.rs");
|
||||
var pythonAssetTemplate = Handlebars.Compile(File.ReadAllText(Path.Combine(templatesDir, "python_asset.hbs")));
|
||||
var pythonAsset = pythonAssetTemplate(handlebarData);
|
||||
File.WriteAllText(pythonAssetRs, pythonAsset.ToString().ReplaceLineEndings("\n"));
|
||||
|
||||
// --- nodejs generation ---
|
||||
var libnodeTypesFile = Path.Combine(scriptsDir, "..", "lib-nodejs", "src", "types.ts");
|
||||
var nodeTemplate = Handlebars.Compile(File.ReadAllText(Path.Combine(templatesDir, "node_types.hbs")));
|
||||
var nodeData = nodeTemplate(handlebarData);
|
||||
File.WriteAllText(libnodeTypesFile, nodeData.ToString().ReplaceLineEndings("\n"));
|
||||
|
||||
return 0;
|
||||
|
||||
class TypeMap
|
||||
@@ -122,6 +129,7 @@ class TypeMap
|
||||
public string rustType;
|
||||
public string cType;
|
||||
public string cppType;
|
||||
public string nodeType;
|
||||
public string interopType;
|
||||
public bool primitive;
|
||||
public bool system;
|
||||
@@ -132,18 +140,20 @@ class TypeMap
|
||||
rustType = rustName,
|
||||
cType = cType,
|
||||
cppType = rustName,
|
||||
nodeType = rustName,
|
||||
interopType = cType,
|
||||
primitive = false,
|
||||
system = false,
|
||||
};
|
||||
}
|
||||
|
||||
public static TypeMap Primitive(string rustName, string cType)
|
||||
public static TypeMap Primitive(string rustName, string cType, string nodeType)
|
||||
{
|
||||
return new TypeMap() {
|
||||
rustType = rustName,
|
||||
cType = cType,
|
||||
cppType = cType,
|
||||
nodeType = nodeType,
|
||||
interopType = rustName,
|
||||
primitive = true,
|
||||
system = false,
|
||||
@@ -156,6 +166,7 @@ class TypeMap
|
||||
rustType = rustName,
|
||||
cType = cType,
|
||||
cppType = cppType,
|
||||
nodeType = cppType,
|
||||
interopType = interopType,
|
||||
primitive = false,
|
||||
system = true,
|
||||
@@ -179,6 +190,7 @@ class RustStruct_Field
|
||||
public string field_c_type;
|
||||
public string field_cpp_type;
|
||||
public string field_rust_type;
|
||||
public string field_node_type;
|
||||
public bool field_primitive;
|
||||
public bool field_optional;
|
||||
public bool field_vector;
|
||||
|
||||
12
src/code-generator/Templates/node_types.hbs
Normal file
12
src/code-generator/Templates/node_types.hbs
Normal file
@@ -0,0 +1,12 @@
|
||||
// This file is auto-generated. Do not edit by hand.
|
||||
|
||||
{{#each this}}
|
||||
{{cpp_comment}}
|
||||
export type {{struct_rust_name}} = {
|
||||
{{#each fields}}
|
||||
{{#indent "cpp_comment" " "}}
|
||||
{{field_name}}{{#if field_optional}}?{{/if}}: {{field_node_type}}{{#if field_vector}}[]{{/if}},
|
||||
{{/each}}
|
||||
}
|
||||
|
||||
{{/each}}
|
||||
@@ -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/NULL**.
|
||||
* 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'.
|
||||
@@ -209,11 +209,15 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* Create a new FileSource update source for a given file path.
|
||||
* @param psz_file_path The path to a local directory containing updates.
|
||||
* @returns A new vpkc_update_source_t instance, or null on error.
|
||||
*/
|
||||
vpkc_update_source_t *vpkc_new_source_file(const char *psz_file_path);
|
||||
|
||||
/**
|
||||
* Create a new HttpSource update source for a given HTTP URL.
|
||||
* @param psz_http_url The URL to a remote update server.
|
||||
* @returns A new vpkc_update_source_t instance, or null on error.
|
||||
*/
|
||||
vpkc_update_source_t *vpkc_new_source_http_url(const char *psz_http_url);
|
||||
|
||||
@@ -223,6 +227,11 @@ vpkc_update_source_t *vpkc_new_source_http_url(const char *psz_http_url);
|
||||
* for the lifetime of any UpdateManager's that use this source. You should call `vpkc_free_source` to free the source,
|
||||
* but note that if the source is still in use by an UpdateManager, it will not be freed until the UpdateManager is freed.
|
||||
* Therefore to avoid possible issues, it is recommended to create this type of source once for the lifetime of your application.
|
||||
* @param cb_release_feed A callback to fetch the release feed.
|
||||
* @param cb_free_release_feed A callback to free the memory allocated by `cb_release_feed`.
|
||||
* @param cb_download_entry A callback to download an asset.
|
||||
* @param p_user_data Optional user data to be passed to the callbacks.
|
||||
* @returns A new vpkc_update_source_t instance, or null on error. If null, the error will be available via `vpkc_get_last_error`.
|
||||
*/
|
||||
vpkc_update_source_t *vpkc_new_source_custom_callback(vpkc_release_feed_delegate_t cb_release_feed,
|
||||
vpkc_free_release_feed_t cb_free_release_feed,
|
||||
@@ -232,19 +241,24 @@ vpkc_update_source_t *vpkc_new_source_custom_callback(vpkc_release_feed_delegate
|
||||
/**
|
||||
* Sends a progress update to the callback with the specified ID. This is used by custom
|
||||
* update sources created with `vpkc_new_source_custom_callback` to report download progress.
|
||||
* @param progress_callback_id The ID of the progress callback to send the update to.
|
||||
* @param progress The progress value to send (0-100).
|
||||
*/
|
||||
void vpkc_source_report_progress(size_t progress_callback_id, int16_t progress);
|
||||
|
||||
/**
|
||||
* Frees a vpkc_update_source_t instance.
|
||||
* @param p_source The source to free.
|
||||
*/
|
||||
void vpkc_free_source(vpkc_update_source_t *p_source);
|
||||
|
||||
/**
|
||||
* Create a new UpdateManager instance.
|
||||
* @param urlOrPath Location of the update server or path to the local update directory.
|
||||
* @param options Optional extra configuration for update manager.
|
||||
* @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
* @param psz_url_or_path Location of the http update server url or path to the local update directory.
|
||||
* @param p_options Optional extra configuration for update manager.
|
||||
* @param p_locator Optional explicit path configuration for Velopack. If null, the default locator will be used.
|
||||
* @param p_manager A pointer to where the new vpkc_update_manager_t* instance will be stored.
|
||||
* @returns True if the update manager was created successfully, false otherwise. If false, the error will be available via `vpkc_get_last_error`.
|
||||
*/
|
||||
bool vpkc_new_update_manager(const char *psz_url_or_path,
|
||||
struct vpkc_update_options_t *p_options,
|
||||
@@ -253,9 +267,11 @@ bool vpkc_new_update_manager(const char *psz_url_or_path,
|
||||
|
||||
/**
|
||||
* Create a new UpdateManager instance with a custom UpdateSource.
|
||||
* @param urlOrPath Location of the update server or path to the local update directory.
|
||||
* @param options Optional extra configuration for update manager.
|
||||
* @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
* @param p_source A pointer to a custom UpdateSource.
|
||||
* @param p_options Optional extra configuration for update manager.
|
||||
* @param p_locator Optional explicit path configuration for Velopack. If null, the default locator will be used.
|
||||
* @param p_manager A pointer to where the new vpkc_update_manager_t* instance will be stored.
|
||||
* @returns True if the update manager was created successfully, false otherwise. If false, the error will be available via `vpkc_get_last_error`.
|
||||
*/
|
||||
bool vpkc_new_update_manager_with_source(vpkc_update_source_t *p_source,
|
||||
struct vpkc_update_options_t *p_options,
|
||||
@@ -264,6 +280,10 @@ bool vpkc_new_update_manager_with_source(vpkc_update_source_t *p_source,
|
||||
|
||||
/**
|
||||
* Returns the currently installed version of the app.
|
||||
* @param p_manager The update manager instance.
|
||||
* @param psz_version A buffer to store the version string.
|
||||
* @param c_version The size of the `psz_version` buffer.
|
||||
* @returns The number of characters written to `psz_version` (including null terminator), or the required buffer size if the buffer is too small.
|
||||
*/
|
||||
size_t vpkc_get_current_version(vpkc_update_manager_t *p_manager,
|
||||
char *psz_version,
|
||||
@@ -271,24 +291,38 @@ size_t vpkc_get_current_version(vpkc_update_manager_t *p_manager,
|
||||
|
||||
/**
|
||||
* Returns the currently installed app id.
|
||||
* @param p_manager The update manager instance.
|
||||
* @param psz_id A buffer to store the app id string.
|
||||
* @param c_id The size of the `psz_id` buffer.
|
||||
* @returns The number of characters written to `psz_id` (including null terminator), or the required buffer size if the buffer is too small.
|
||||
*/
|
||||
size_t vpkc_get_app_id(vpkc_update_manager_t *p_manager, char *psz_id, size_t c_id);
|
||||
size_t vpkc_get_app_id(vpkc_update_manager_t *p_manager,
|
||||
char *psz_id,
|
||||
size_t c_id);
|
||||
|
||||
/**
|
||||
* Returns whether the app is in portable mode. On Windows this can be true or false.
|
||||
* On MacOS and Linux this will always be true.
|
||||
* @param p_manager The update manager instance.
|
||||
* @returns True if the app is in portable mode, false otherwise.
|
||||
*/
|
||||
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.
|
||||
* Returns an asset if there is an update downloaded which still needs to be applied.
|
||||
* You can pass this asset to `vpkc_wait_exit_then_apply_updates` to apply the update.
|
||||
* @param p_manager The update manager instance.
|
||||
* @param p_asset A pointer to where the new vpkc_asset_t* instance will be stored.
|
||||
* @returns True if there is an update pending restart, false otherwise.
|
||||
*/
|
||||
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
|
||||
* Checks for updates. 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.
|
||||
* @param p_manager The update manager instance.
|
||||
* @param p_update A pointer to where the new vpkc_update_info_t* instance will be stored if an update is available.
|
||||
* @returns A `vpkc_update_check_t` value indicating the result of the check. If an update is available, the value will be `HasUpdate` and `p_update` will be populated.
|
||||
*/
|
||||
vpkc_update_check_t vpkc_check_for_updates(vpkc_update_manager_t *p_manager,
|
||||
struct vpkc_update_info_t **p_update);
|
||||
@@ -300,6 +334,11 @@ vpkc_update_check_t vpkc_check_for_updates(vpkc_update_manager_t *p_manager,
|
||||
* this method will attempt to unpack and prepare them.
|
||||
* - If there is no delta update available, or there is an error preparing delta
|
||||
* packages, this method will fall back to downloading the full version of the update.
|
||||
* @param p_manager The update manager instance.
|
||||
* @param p_update The update info object from `vpkc_check_for_updates`.
|
||||
* @param cb_progress An optional callback to report download progress (0-100).
|
||||
* @param p_user_data Optional user data to be passed to the progress callback.
|
||||
* @returns true on success, false on failure. If false, the error will be available via `vpkc_get_last_error`.
|
||||
*/
|
||||
bool vpkc_download_updates(vpkc_update_manager_t *p_manager,
|
||||
struct vpkc_update_info_t *p_update,
|
||||
@@ -309,7 +348,14 @@ bool vpkc_download_updates(vpkc_update_manager_t *p_manager,
|
||||
/**
|
||||
* This will launch the Velopack updater and tell it to wait for this program to exit gracefully.
|
||||
* You should then clean up any state and exit your app. The updater will apply updates and then
|
||||
* optionally restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
* (if specified) restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
* @param p_manager The update manager instance.
|
||||
* @param p_asset The asset to apply. This can be from `vpkc_update_pending_restart` or `vpkc_update_info_get_target_asset`.
|
||||
* @param b_silent True to attempt to apply the update without showing any UI.
|
||||
* @param b_restart True to restart the app after the update is applied.
|
||||
* @param p_restart_args An array of command line arguments to pass to the new process when it's restarted.
|
||||
* @param c_restart_args The number of arguments in `p_restart_args`.
|
||||
* @returns true on success, false on failure. If false, the error will be available via `vpkc_get_last_error`.
|
||||
*/
|
||||
bool vpkc_wait_exit_then_apply_updates(vpkc_update_manager_t *p_manager,
|
||||
struct vpkc_asset_t *p_asset,
|
||||
@@ -323,6 +369,14 @@ bool vpkc_wait_exit_then_apply_updates(vpkc_update_manager_t *p_manager,
|
||||
* 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).
|
||||
* @param p_manager The update manager instance.
|
||||
* @param p_asset The asset to apply. This can be from `vpkc_update_pending_restart` or `vpkc_update_info_get_target_asset`.
|
||||
* @param b_silent True to attempt to apply the update without showing any UI.
|
||||
* @param dw_wait_pid The process ID to wait for before applying updates. If 0, the updater will not wait.
|
||||
* @param b_restart True to restart the app after the update is applied.
|
||||
* @param p_restart_args An array of command line arguments to pass to the new process when it's restarted.
|
||||
* @param c_restart_args The number of arguments in `p_restart_args`.
|
||||
* @returns true on success, false on failure. If false, the error will be available via `vpkc_get_last_error`.
|
||||
*/
|
||||
bool vpkc_unsafe_apply_updates(vpkc_update_manager_t *p_manager,
|
||||
struct vpkc_asset_t *p_asset,
|
||||
@@ -334,90 +388,115 @@ bool vpkc_unsafe_apply_updates(vpkc_update_manager_t *p_manager,
|
||||
|
||||
/**
|
||||
* Frees a vpkc_update_manager_t instance.
|
||||
* @param p_manager The update manager instance to free.
|
||||
*/
|
||||
void vpkc_free_update_manager(vpkc_update_manager_t *p_manager);
|
||||
|
||||
/**
|
||||
* Frees a vpkc_update_info_t instance.
|
||||
* @param p_update_info The update info instance to free.
|
||||
*/
|
||||
void vpkc_free_update_info(struct vpkc_update_info_t *p_update_info);
|
||||
|
||||
/**
|
||||
* Frees a vpkc_asset_t instance.
|
||||
* @param p_asset The asset instance to free.
|
||||
*/
|
||||
void vpkc_free_asset(struct vpkc_asset_t *p_asset);
|
||||
|
||||
/**
|
||||
* VelopackApp helps you to handle app activation events correctly.
|
||||
* This should be used as early as possible in your application startup code.
|
||||
* (eg. the beginning of main() or wherever your entry point is)
|
||||
* (eg. the beginning of main() or wherever your entry point is).
|
||||
* This function will not return in some cases.
|
||||
* @param p_user_data Optional user data to be passed to the callbacks.
|
||||
*/
|
||||
void vpkc_app_run(void *p_user_data);
|
||||
|
||||
/**
|
||||
* Set whether to automatically apply downloaded updates on startup. This is ON by default.
|
||||
* @param b_auto_apply True to automatically apply updates, false otherwise.
|
||||
*/
|
||||
void vpkc_app_set_auto_apply_on_startup(bool b_auto_apply);
|
||||
|
||||
/**
|
||||
* Override the command line arguments used by VelopackApp. (by default this is env::args().skip(1))
|
||||
* @param p_args An array of command line arguments.
|
||||
* @param c_args The number of arguments in `p_args`.
|
||||
*/
|
||||
void vpkc_app_set_args(char **p_args, size_t c_args);
|
||||
|
||||
/**
|
||||
* VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth).
|
||||
* @param p_locator The locator configuration to use.
|
||||
*/
|
||||
void vpkc_app_set_locator(struct vpkc_locator_config_t *p_locator);
|
||||
|
||||
/**
|
||||
* Sets a callback to be run after the app is installed.
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cb_after_install The callback to run after the app is installed. The callback takes a user data pointer and the version of the app as a string.
|
||||
*/
|
||||
void vpkc_app_set_hook_after_install(vpkc_hook_callback_t cb_after_install);
|
||||
|
||||
/**
|
||||
* Sets a callback to be run before the app is uninstalled.
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cb_before_uninstall The callback to run before the app is uninstalled. The callback takes a user data pointer and the version of the app as a string.
|
||||
*/
|
||||
void vpkc_app_set_hook_before_uninstall(vpkc_hook_callback_t cb_before_uninstall);
|
||||
|
||||
/**
|
||||
* Sets a callback to be run before the app is updated.
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cb_before_update The callback to run before the app is updated. The callback takes a user data pointer and the version of the app as a string.
|
||||
*/
|
||||
void vpkc_app_set_hook_before_update(vpkc_hook_callback_t cb_before_update);
|
||||
|
||||
/**
|
||||
* Sets a callback to be run after the app is updated.
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cb_after_update The callback to run after the app is updated. The callback takes a user data pointer and the version of the app as a string.
|
||||
*/
|
||||
void vpkc_app_set_hook_after_update(vpkc_hook_callback_t cb_after_update);
|
||||
|
||||
/**
|
||||
* This hook is triggered when the application is started for the first time after installation.
|
||||
* @param cb_first_run The callback to run on first run. The callback takes a user data pointer and the version of the app as a string.
|
||||
*/
|
||||
void vpkc_app_set_hook_first_run(vpkc_hook_callback_t cb_first_run);
|
||||
|
||||
/**
|
||||
* This hook is triggered when the application is restarted by Velopack after installing updates.
|
||||
* @param cb_restarted The callback to run after the app is restarted. The callback takes a user data pointer and the version of the app as a string.
|
||||
*/
|
||||
void vpkc_app_set_hook_restarted(vpkc_hook_callback_t cb_restarted);
|
||||
|
||||
/**
|
||||
* Get the last error message that occurred in the Velopack library.
|
||||
* @param psz_error A buffer to store the error message.
|
||||
* @param c_error The size of the `psz_error` buffer.
|
||||
* @returns The number of characters written to `psz_error` (including null terminator). If the return value is greater than `c_error`, the buffer was too small and the message was truncated.
|
||||
*/
|
||||
size_t vpkc_get_last_error(char *psz_error, size_t c_error);
|
||||
size_t vpkc_get_last_error(char *psz_error,
|
||||
size_t c_error);
|
||||
|
||||
/**
|
||||
* Set a custom log callback. This will be called for all log messages generated by the Velopack library.
|
||||
* @param cb_log The callback to call with log messages. The callback takes a user data pointer, a log level, and the log message as a string.
|
||||
* @param p_user_data Optional user data to be passed to the callback.
|
||||
*/
|
||||
void vpkc_set_logger(vpkc_log_callback_t cb_log,
|
||||
void *p_user_data);
|
||||
|
||||
@@ -31,12 +31,6 @@ static inline std::optional<std::string> to_cpp_string(const char* psz)
|
||||
return psz == nullptr ? std::optional<std::string>("") : std::optional<std::string>(psz);
|
||||
}
|
||||
|
||||
static inline char* alloc_c_string(const std::optional<std::string>& str)
|
||||
{
|
||||
if (!str.has_value()) { return nullptr; }
|
||||
return alloc_c_string(str.value());
|
||||
}
|
||||
|
||||
static inline char* alloc_c_string(const std::string& str)
|
||||
{
|
||||
char* result = new char[str.size() + 1]; // +1 for null-terminator
|
||||
@@ -49,6 +43,12 @@ static inline char* alloc_c_string(const std::string& str)
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline char* alloc_c_string(const std::optional<std::string>& str)
|
||||
{
|
||||
if (!str.has_value()) { return nullptr; }
|
||||
return alloc_c_string(str.value());
|
||||
}
|
||||
|
||||
static inline void free_c_string(char* str)
|
||||
{
|
||||
delete[] str;
|
||||
@@ -165,7 +165,7 @@ static inline void free_c_VelopackLocatorConfig(vpkc_locator_config_t* obj) {
|
||||
free_c_string(obj->PackagesDir);
|
||||
free_c_string(obj->ManifestPath);
|
||||
free_c_string(obj->CurrentBinaryDir);
|
||||
|
||||
|
||||
delete obj;
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ static inline void free_c_VelopackAsset(vpkc_asset_t* obj) {
|
||||
free_c_string(obj->FileName);
|
||||
free_c_string(obj->SHA1);
|
||||
free_c_string(obj->SHA256);
|
||||
|
||||
|
||||
free_c_string(obj->NotesMarkdown);
|
||||
free_c_string(obj->NotesHtml);
|
||||
delete obj;
|
||||
@@ -354,7 +354,7 @@ static inline void free_c_UpdateInfo(vpkc_update_info_t* obj) {
|
||||
free_c_VelopackAsset(obj->TargetFullRelease);
|
||||
free_c_VelopackAsset(obj->BaseRelease);
|
||||
free_c_VelopackAsset_vec(obj->DeltasToTarget, obj->DeltasToTargetCount);
|
||||
|
||||
|
||||
delete obj;
|
||||
}
|
||||
|
||||
@@ -443,9 +443,9 @@ static inline vpkc_update_options_t** alloc_c_UpdateOptions_vec(const std::vecto
|
||||
|
||||
static inline void free_c_UpdateOptions(vpkc_update_options_t* obj) {
|
||||
if (obj == nullptr) { return; }
|
||||
|
||||
|
||||
free_c_string(obj->ExplicitChannel);
|
||||
|
||||
|
||||
delete obj;
|
||||
}
|
||||
|
||||
@@ -458,20 +458,23 @@ static inline void free_c_UpdateOptions_vec(vpkc_update_options_t** arr, size_t
|
||||
}
|
||||
// !! AUTO-GENERATED-END CPP_TYPES
|
||||
|
||||
/**
|
||||
/**
|
||||
* VelopackApp helps you to handle app activation events correctly.
|
||||
* This should be used as early as possible in your application startup code.
|
||||
* (eg. the beginning of main() or wherever your entry point is)
|
||||
* To use this class, you should create a new VelopackApp::Build() builder instance,
|
||||
* and then chain calls to the builder to configure your app.
|
||||
* Finally, call the Run() method to execute the Velopack logic.
|
||||
*/
|
||||
class VelopackApp {
|
||||
private:
|
||||
VelopackApp() {};
|
||||
public:
|
||||
/**
|
||||
* Build a new VelopackApp instance.
|
||||
* Create and return a new VelopackApp builder.
|
||||
*/
|
||||
static VelopackApp Build() {
|
||||
return VelopackApp();
|
||||
static VelopackApp Build() {
|
||||
return VelopackApp();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -491,7 +494,10 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Override the command line arguments used by VelopackApp. (by default this is env::args().skip(1))
|
||||
* Override the command line arguments used by VelopackApp.
|
||||
* By default, Velopack will use the command line arguments from the current process.
|
||||
* @param args The command line arguments to use.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& SetArgs(const std::vector<std::string>& args) {
|
||||
size_t c;
|
||||
@@ -502,7 +508,9 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth).
|
||||
* Override the default VelopackLocator. The locator is used to find important paths for the application.
|
||||
* @param locator The locator to use.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& SetLocator(const VelopackLocatorConfig& locator) {
|
||||
vpkc_locator_config_t* vpkc_locator = alloc_c_VelopackLocatorConfig(locator);
|
||||
@@ -512,68 +520,85 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* This hook is triggered after the app has been installed.
|
||||
* WARNING: This hook is run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cbAfterInstall The callback to run after the app has been installed.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& OnAfterInstall(vpkc_hook_callback_t cbInstall) {
|
||||
vpkc_app_set_hook_after_install(cbInstall);
|
||||
VelopackApp& OnAfterInstall(vpkc_hook_callback_t cbAfterInstall) {
|
||||
vpkc_app_set_hook_after_install(cbAfterInstall);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* This hook is triggered before the app is uninstalled.
|
||||
* WARNING: This hook is run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cbBeforeUninstall The callback to run before the app is uninstalled.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& OnBeforeUninstall(vpkc_hook_callback_t cbInstall) {
|
||||
vpkc_app_set_hook_before_uninstall(cbInstall);
|
||||
VelopackApp& OnBeforeUninstall(vpkc_hook_callback_t cbBeforeUninstall) {
|
||||
vpkc_app_set_hook_before_uninstall(cbBeforeUninstall);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* This hook is triggered before the app is updated.
|
||||
* WARNING: This hook is run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cbBeforeUpdate The callback to run before the app is updated.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& OnBeforeUpdate(vpkc_hook_callback_t cbInstall) {
|
||||
vpkc_app_set_hook_before_update(cbInstall);
|
||||
VelopackApp& OnBeforeUpdate(vpkc_hook_callback_t cbBeforeUpdate) {
|
||||
vpkc_app_set_hook_before_update(cbBeforeUpdate);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
* This hook is triggered after the app is updated.
|
||||
* WARNING: This hook is run during critical stages of Velopack operations.
|
||||
* Your code will be run and then the process will exit.
|
||||
* If your code has not completed within 30 seconds, it will be terminated.
|
||||
* Only supported on windows; On other operating systems, this will never be called.
|
||||
* @param cbAfterUpdate The callback to run after the app is updated.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& OnAfterUpdate(vpkc_hook_callback_t cbInstall) {
|
||||
vpkc_app_set_hook_after_update(cbInstall);
|
||||
VelopackApp& OnAfterUpdate(vpkc_hook_callback_t cbAfterUpdate) {
|
||||
vpkc_app_set_hook_after_update(cbAfterUpdate);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* This hook is triggered when the application is started for the first time after installation.
|
||||
* @param cbFirstRun The callback to run when the application is started for the first time.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& OnFirstRun(vpkc_hook_callback_t cbInstall) {
|
||||
vpkc_app_set_hook_first_run(cbInstall);
|
||||
VelopackApp& OnFirstRun(vpkc_hook_callback_t cbFirstRun) {
|
||||
vpkc_app_set_hook_first_run(cbFirstRun);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* This hook is triggered when the application is restarted by Velopack after installing updates.
|
||||
* @param cbRestarted The callback to run when the application is restarted.
|
||||
* @returns A reference to the builder.
|
||||
*/
|
||||
VelopackApp& OnRestarted(vpkc_hook_callback_t cbInstall) {
|
||||
vpkc_app_set_hook_restarted(cbInstall);
|
||||
VelopackApp& OnRestarted(vpkc_hook_callback_t cbRestarted) {
|
||||
vpkc_app_set_hook_restarted(cbRestarted);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs the Velopack startup logic. This should be the first thing to run in your app.
|
||||
* In some circumstances it may terminate/restart the process to perform tasks.
|
||||
* @param pUserData A pointer to user data that will be passed to any hooks that are executed.
|
||||
*/
|
||||
void Run(void* pUserData = 0) {
|
||||
vpkc_app_run(pUserData);
|
||||
@@ -586,7 +611,7 @@ public:
|
||||
typedef std::function<void(int16_t)> vpkc_progress_send_t;
|
||||
|
||||
/**
|
||||
* Abstract class for retrieving release feeds and downloading assets. You should subclass this and
|
||||
* Abstract class for retrieving release feeds and downloading assets. You should subclass this and
|
||||
* implement/override the GetReleaseFeed and DownloadReleaseEntry methods.
|
||||
* This class is used by the UpdateManager to fetch release feeds and download assets in a custom way.
|
||||
* SAFETY: It is your responsibility to ensure that a derived class instance is thread-safe,
|
||||
@@ -596,20 +621,26 @@ class IUpdateSource {
|
||||
friend class UpdateManager;
|
||||
friend class FileSource;
|
||||
friend class HttpSource;
|
||||
private:
|
||||
private:
|
||||
IUpdateSource(vpkc_update_source_t* pSource) : m_pSource(pSource) {}
|
||||
vpkc_update_source_t* m_pSource = 0;
|
||||
public:
|
||||
/**
|
||||
* Destructor for IUpdateSource.
|
||||
*/
|
||||
virtual ~IUpdateSource() {
|
||||
vpkc_free_source(m_pSource);
|
||||
}
|
||||
/**
|
||||
* Default constructor for IUpdateSource. This will create a new custom source that calls back into the virtual methods of this class.
|
||||
*/
|
||||
IUpdateSource() {
|
||||
m_pSource = vpkc_new_source_custom_callback(
|
||||
[](void* userData, const char* releasesName) {
|
||||
IUpdateSource* source = reinterpret_cast<IUpdateSource*>(userData);
|
||||
std::string json = source->GetReleaseFeed(releasesName);
|
||||
return alloc_c_string(json);
|
||||
},
|
||||
},
|
||||
[](void* userData, char* pszFeed) {
|
||||
free_c_string(pszFeed);
|
||||
},
|
||||
@@ -623,6 +654,9 @@ public:
|
||||
return source->DownloadReleaseEntry(asset, localPath, progress_callback);
|
||||
},
|
||||
this);
|
||||
if (!m_pSource) {
|
||||
throw_last_error();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -641,12 +675,16 @@ public:
|
||||
*/
|
||||
class FileSource : public IUpdateSource {
|
||||
public:
|
||||
/**
|
||||
* Creates a new FileSource.
|
||||
* @param filePath The path to the directory containing the releases.
|
||||
*/
|
||||
FileSource(const std::string& filePath) : IUpdateSource(vpkc_new_source_file(filePath.c_str())) { }
|
||||
const std::string GetReleaseFeed(const std::string releasesName) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
const std::string GetReleaseFeed(const std::string releasesName) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
bool DownloadReleaseEntry(const VelopackAsset& asset, const std::string localFilePath, vpkc_progress_send_t progress) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
bool DownloadReleaseEntry(const VelopackAsset& asset, const std::string localFilePath, vpkc_progress_send_t progress) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -655,17 +693,22 @@ public:
|
||||
*/
|
||||
class HttpSource : public IUpdateSource {
|
||||
public:
|
||||
/**
|
||||
* Creates a new HttpSource.
|
||||
* @param httpUrl The URL to the releases feed.
|
||||
*/
|
||||
HttpSource(const std::string& httpUrl) : IUpdateSource(vpkc_new_source_http_url(httpUrl.c_str())) { }
|
||||
const std::string GetReleaseFeed(const std::string releasesName) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
const std::string GetReleaseFeed(const std::string releasesName) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
bool DownloadReleaseEntry(const VelopackAsset& asset, const std::string localFilePath, vpkc_progress_send_t progress) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
bool DownloadReleaseEntry(const VelopackAsset& asset, const std::string localFilePath, vpkc_progress_send_t progress) override {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides functionality for checking for updates, downloading updates, and applying updates to the current application.
|
||||
* This class is the main entry point for interacting with Velopack.
|
||||
*/
|
||||
class UpdateManager {
|
||||
private:
|
||||
@@ -674,7 +717,7 @@ private:
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new UpdateManager instance.
|
||||
* Create a new UpdateManager instance for a local or remote directory of releases.
|
||||
* @param urlOrPath Location of the http update server or the local update directory path containing releases.
|
||||
* @param options Optional extra configuration for update manager.
|
||||
* @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
@@ -691,7 +734,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new UpdateManager instance.
|
||||
* Create a new UpdateManager instance with a custom update source.
|
||||
* @param updateSource The source to use for retrieving feed and downloading assets.
|
||||
* @param options Optional extra configuration for update manager.
|
||||
* @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
@@ -749,8 +792,9 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Returns a VelopackAsset object if there is an update downloaded which still needs to be applied.
|
||||
* You can pass this object to WaitExitThenApplyUpdates to apply the update.
|
||||
* @returns A VelopackAsset object if there is a pending update, otherwise null.
|
||||
*/
|
||||
std::optional<VelopackAsset> UpdatePendingRestart() noexcept {
|
||||
vpkc_asset_t* asset;
|
||||
@@ -763,8 +807,9 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks for updates, returning None if there are none available. If there are updates available, this method will return an
|
||||
* Checks for updates, returning null 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.
|
||||
* @returns An UpdateInfo object if there is an update available, otherwise null.
|
||||
*/
|
||||
std::optional<UpdateInfo> CheckForUpdates() {
|
||||
vpkc_update_info_t* update;
|
||||
@@ -791,6 +836,9 @@ public:
|
||||
* this method will attempt to unpack and prepare them.
|
||||
* - If there is no delta update available, or there is an error preparing delta
|
||||
* packages, this method will fall back to downloading the full version of the update.
|
||||
* @param update The update to download.
|
||||
* @param progress A callback to report progress to.
|
||||
* @param pUserData A pointer to user data that will be passed to the progress callback.
|
||||
*/
|
||||
void DownloadUpdates(const UpdateInfo& update, vpkc_progress_callback_t progress = nullptr, void* pUserData = 0) {
|
||||
vpkc_update_info_t* vpkc_update = alloc_c_UpdateInfo(update);
|
||||
@@ -805,6 +853,10 @@ public:
|
||||
* This will launch the Velopack updater and tell it to wait for this program to exit gracefully.
|
||||
* You should then clean up any state and exit your app. The updater will apply updates and then
|
||||
* optionally restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
* @param asset The UpdateInfo object for the update to apply.
|
||||
* @param silent If true, the updater will not show any UI.
|
||||
* @param restart If true, the app will be restarted after the update is applied.
|
||||
* @param restartArgs The arguments to pass to the app when it is restarted.
|
||||
*/
|
||||
void WaitExitThenApplyUpdates(const UpdateInfo& asset, bool silent = false, bool restart = true, std::vector<std::string> restartArgs = {}) {
|
||||
this->WaitExitThenApplyUpdates(asset.TargetFullRelease, silent, restart, restartArgs);
|
||||
@@ -814,6 +866,10 @@ public:
|
||||
* This will launch the Velopack updater and tell it to wait for this program to exit gracefully.
|
||||
* You should then clean up any state and exit your app. The updater will apply updates and then
|
||||
* optionally restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
* @param asset The update to apply.
|
||||
* @param silent If true, the updater will not show any UI.
|
||||
* @param restart If true, the app will be restarted after the update is applied.
|
||||
* @param restartArgs The arguments to pass to the app when it is restarted.
|
||||
*/
|
||||
void WaitExitThenApplyUpdates(const VelopackAsset& asset, bool silent = false, bool restart = true, std::vector<std::string> restartArgs = {}) {
|
||||
size_t cRestartArgs;
|
||||
@@ -829,9 +885,14 @@ public:
|
||||
|
||||
/**
|
||||
* 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 `WaitExitThenApplyUpdates` method is recommended for most use cases.
|
||||
* If waitPid is 0, the updater will not wait for any process to exit before applying updates (Not Recommended).
|
||||
* @param asset The update to apply.
|
||||
* @param silent If true, the updater will not show any UI.
|
||||
* @param waitPid The process ID to wait for before applying updates. If 0, the updater will not wait.
|
||||
* @param restart If true, the app will be restarted after the update is applied.
|
||||
* @param restartArgs The arguments to pass to the app when it is restarted.
|
||||
*/
|
||||
void UnsafeApplyUpdates(const VelopackAsset& asset, bool silent, uint32_t waitPid, bool restart, std::vector<std::string> restartArgs) {
|
||||
size_t cRestartArgs;
|
||||
|
||||
@@ -20,6 +20,8 @@ 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.
|
||||
/// @param psz_file_path The path to a local directory containing updates.
|
||||
/// @returns A new vpkc_update_source_t instance, or null on error.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -33,6 +35,8 @@ pub extern "C" fn vpkc_new_source_file(psz_file_path: *const c_char) -> *mut vpk
|
||||
}
|
||||
|
||||
/// Create a new HttpSource update source for a given HTTP URL.
|
||||
/// @param psz_http_url The URL to a remote update server.
|
||||
/// @returns A new vpkc_update_source_t instance, or null on error.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -50,6 +54,11 @@ pub extern "C" fn vpkc_new_source_http_url(psz_http_url: *const c_char) -> *mut
|
||||
/// for the lifetime of any UpdateManager's that use this source. You should call `vpkc_free_source` to free the source,
|
||||
/// but note that if the source is still in use by an UpdateManager, it will not be freed until the UpdateManager is freed.
|
||||
/// Therefore to avoid possible issues, it is recommended to create this type of source once for the lifetime of your application.
|
||||
/// @param cb_release_feed A callback to fetch the release feed.
|
||||
/// @param cb_free_release_feed A callback to free the memory allocated by `cb_release_feed`.
|
||||
/// @param cb_download_entry A callback to download an asset.
|
||||
/// @param p_user_data Optional user data to be passed to the callbacks.
|
||||
/// @returns A new vpkc_update_source_t instance, or null on error. If null, the error will be available via `vpkc_get_last_error`.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -59,8 +68,21 @@ pub extern "C" fn vpkc_new_source_custom_callback(
|
||||
cb_download_entry: vpkc_download_asset_delegate_t,
|
||||
p_user_data: *mut c_void,
|
||||
) -> *mut vpkc_update_source_t {
|
||||
if cb_release_feed.is_none() || cb_download_entry.is_none() || cb_free_release_feed.is_none() {
|
||||
log::error!("cb_release_feed, cb_download_entry, or cb_free_release_feed is null");
|
||||
if cb_release_feed.is_none() {
|
||||
log::error!("cb_release_feed must not be null");
|
||||
set_last_error("cb_release_feed must not be null");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
if cb_download_entry.is_none() {
|
||||
log::error!("cb_download_entry must not be null");
|
||||
set_last_error("cb_download_entry must not be null");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
if cb_free_release_feed.is_none() {
|
||||
log::error!("cb_free_release_feed must not be null");
|
||||
set_last_error("cb_free_release_feed must not be null");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
@@ -76,12 +98,15 @@ pub extern "C" fn vpkc_new_source_custom_callback(
|
||||
|
||||
/// Sends a progress update to the callback with the specified ID. This is used by custom
|
||||
/// update sources created with `vpkc_new_source_custom_callback` to report download progress.
|
||||
/// @param progress_callback_id The ID of the progress callback to send the update to.
|
||||
/// @param progress The progress value to send (0-100).
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_source_report_progress(progress_callback_id: size_t, progress: i16) {
|
||||
report_csource_progress(progress_callback_id, progress);
|
||||
}
|
||||
|
||||
/// Frees a vpkc_update_source_t instance.
|
||||
/// @param p_source The source to free.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -90,9 +115,11 @@ pub extern "C" fn vpkc_free_source(p_source: *mut vpkc_update_source_t) {
|
||||
}
|
||||
|
||||
/// Create a new UpdateManager instance.
|
||||
/// @param urlOrPath Location of the update server or path to the local update directory.
|
||||
/// @param options Optional extra configuration for update manager.
|
||||
/// @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
/// @param psz_url_or_path Location of the http update server url or path to the local update directory.
|
||||
/// @param p_options Optional extra configuration for update manager.
|
||||
/// @param p_locator Optional explicit path configuration for Velopack. If null, the default locator will be used.
|
||||
/// @param p_manager A pointer to where the new vpkc_update_manager_t* instance will be stored.
|
||||
/// @returns True if the update manager was created successfully, false otherwise. If false, the error will be available via `vpkc_get_last_error`.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -114,9 +141,11 @@ pub extern "C" fn vpkc_new_update_manager(
|
||||
}
|
||||
|
||||
/// Create a new UpdateManager instance with a custom UpdateSource.
|
||||
/// @param urlOrPath Location of the update server or path to the local update directory.
|
||||
/// @param options Optional extra configuration for update manager.
|
||||
/// @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
/// @param p_source A pointer to a custom UpdateSource.
|
||||
/// @param p_options Optional extra configuration for update manager.
|
||||
/// @param p_locator Optional explicit path configuration for Velopack. If null, the default locator will be used.
|
||||
/// @param p_manager A pointer to where the new vpkc_update_manager_t* instance will be stored.
|
||||
/// @returns True if the update manager was created successfully, false otherwise. If false, the error will be available via `vpkc_get_last_error`.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -137,6 +166,10 @@ pub extern "C" fn vpkc_new_update_manager_with_source(
|
||||
}
|
||||
|
||||
/// Returns the currently installed version of the app.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param psz_version A buffer to store the version string.
|
||||
/// @param c_version The size of the `psz_version` buffer.
|
||||
/// @returns The number of characters written to `psz_version` (including null terminator), or the required buffer size if the buffer is too small.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -151,6 +184,10 @@ pub extern "C" fn vpkc_get_current_version(p_manager: *mut vpkc_update_manager_t
|
||||
}
|
||||
|
||||
/// Returns the currently installed app id.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param psz_id A buffer to store the app id string.
|
||||
/// @param c_id The size of the `psz_id` buffer.
|
||||
/// @returns The number of characters written to `psz_id` (including null terminator), or the required buffer size if the buffer is too small.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -166,6 +203,8 @@ pub extern "C" fn vpkc_get_app_id(p_manager: *mut vpkc_update_manager_t, psz_id:
|
||||
|
||||
/// Returns whether the app is in portable mode. On Windows this can be true or false.
|
||||
/// On MacOS and Linux this will always be true.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @returns True if the app is in portable mode, false otherwise.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -176,8 +215,11 @@ pub extern "C" fn vpkc_is_portable(p_manager: *mut vpkc_update_manager_t) -> boo
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Returns an asset if there is an update downloaded which still needs to be applied.
|
||||
/// You can pass this asset to `vpkc_wait_exit_then_apply_updates` to apply the update.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param p_asset A pointer to where the new vpkc_asset_t* instance will be stored.
|
||||
/// @returns True if there is an update pending restart, false otherwise.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -194,8 +236,11 @@ pub extern "C" fn vpkc_update_pending_restart(p_manager: *mut vpkc_update_manage
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks for updates, returning None if there are none available. If there are updates available, this method will return an
|
||||
/// Checks for updates. 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.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param p_update A pointer to where the new vpkc_update_info_t* instance will be stored if an update is available.
|
||||
/// @returns A `vpkc_update_check_t` value indicating the result of the check. If an update is available, the value will be `HasUpdate` and `p_update` will be populated.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -229,6 +274,12 @@ pub extern "C" fn vpkc_check_for_updates(
|
||||
/// this method will attempt to unpack and prepare them.
|
||||
/// - If there is no delta update available, or there is an error preparing delta
|
||||
/// packages, this method will fall back to downloading the full version of the update.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param p_update The update info object from `vpkc_check_for_updates`.
|
||||
/// @param cb_progress An optional callback to report download progress (0-100).
|
||||
/// @param p_user_data Optional user data to be passed to the progress callback.
|
||||
/// @returns true on success, false on failure. If false, the error will be available via `vpkc_get_last_error`.
|
||||
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -294,7 +345,14 @@ pub extern "C" fn vpkc_download_updates(
|
||||
|
||||
/// This will launch the Velopack updater and tell it to wait for this program to exit gracefully.
|
||||
/// You should then clean up any state and exit your app. The updater will apply updates and then
|
||||
/// optionally restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
/// (if specified) restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param p_asset The asset to apply. This can be from `vpkc_update_pending_restart` or `vpkc_update_info_get_target_asset`.
|
||||
/// @param b_silent True to attempt to apply the update without showing any UI.
|
||||
/// @param b_restart True to restart the app after the update is applied.
|
||||
/// @param p_restart_args An array of command line arguments to pass to the new process when it's restarted.
|
||||
/// @param c_restart_args The number of arguments in `p_restart_args`.
|
||||
/// @returns true on success, false on failure. If false, the error will be available via `vpkc_get_last_error`.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -323,6 +381,14 @@ pub extern "C" fn vpkc_wait_exit_then_apply_updates(
|
||||
/// 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).
|
||||
/// @param p_manager The update manager instance.
|
||||
/// @param p_asset The asset to apply. This can be from `vpkc_update_pending_restart` or `vpkc_update_info_get_target_asset`.
|
||||
/// @param b_silent True to attempt to apply the update without showing any UI.
|
||||
/// @param dw_wait_pid The process ID to wait for before applying updates. If 0, the updater will not wait.
|
||||
/// @param b_restart True to restart the app after the update is applied.
|
||||
/// @param p_restart_args An array of command line arguments to pass to the new process when it's restarted.
|
||||
/// @param c_restart_args The number of arguments in `p_restart_args`.
|
||||
/// @returns true on success, false on failure. If false, the error will be available via `vpkc_get_last_error`.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -346,6 +412,7 @@ pub extern "C" fn vpkc_unsafe_apply_updates(
|
||||
}
|
||||
|
||||
/// Frees a vpkc_update_manager_t instance.
|
||||
/// @param p_manager The update manager instance to free.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -354,6 +421,7 @@ pub extern "C" fn vpkc_free_update_manager(p_manager: *mut vpkc_update_manager_t
|
||||
}
|
||||
|
||||
/// Frees a vpkc_update_info_t instance.
|
||||
/// @param p_update_info The update info instance to free.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -362,6 +430,7 @@ pub extern "C" fn vpkc_free_update_info(p_update_info: *mut vpkc_update_info_t)
|
||||
}
|
||||
|
||||
/// Frees a vpkc_asset_t instance.
|
||||
/// @param p_asset The asset instance to free.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -371,7 +440,9 @@ pub extern "C" fn vpkc_free_asset(p_asset: *mut vpkc_asset_t) {
|
||||
|
||||
/// VelopackApp helps you to handle app activation events correctly.
|
||||
/// This should be used as early as possible in your application startup code.
|
||||
/// (eg. the beginning of main() or wherever your entry point is)
|
||||
/// (eg. the beginning of main() or wherever your entry point is).
|
||||
/// This function will not return in some cases.
|
||||
/// @param p_user_data Optional user data to be passed to the callbacks.
|
||||
#[no_mangle]
|
||||
#[logfn(Trace)]
|
||||
#[logfn_inputs(Trace)]
|
||||
@@ -449,6 +520,7 @@ pub extern "C" fn vpkc_app_run(p_user_data: *mut c_void) {
|
||||
}
|
||||
|
||||
/// Set whether to automatically apply downloaded updates on startup. This is ON by default.
|
||||
/// @param b_auto_apply True to automatically apply updates, false otherwise.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_auto_apply_on_startup(b_auto_apply: bool) {
|
||||
update_app_options(|opt| {
|
||||
@@ -457,6 +529,8 @@ pub extern "C" fn vpkc_app_set_auto_apply_on_startup(b_auto_apply: bool) {
|
||||
}
|
||||
|
||||
/// Override the command line arguments used by VelopackApp. (by default this is env::args().skip(1))
|
||||
/// @param p_args An array of command line arguments.
|
||||
/// @param c_args The number of arguments in `p_args`.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_args(p_args: *mut *mut c_char, c_args: size_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -465,6 +539,7 @@ pub extern "C" fn vpkc_app_set_args(p_args: *mut *mut c_char, c_args: size_t) {
|
||||
}
|
||||
|
||||
/// VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth).
|
||||
/// @param p_locator The locator configuration to use.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_locator(p_locator: *mut vpkc_locator_config_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -472,10 +547,12 @@ pub extern "C" fn vpkc_app_set_locator(p_locator: *mut vpkc_locator_config_t) {
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets a callback to be run after the app is installed.
|
||||
/// WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
/// Your code will be run and then the process will exit.
|
||||
/// If your code has not completed within 30 seconds, it will be terminated.
|
||||
/// Only supported on windows; On other operating systems, this will never be called.
|
||||
/// @param cb_after_install The callback to run after the app is installed. The callback takes a user data pointer and the version of the app as a string.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_hook_after_install(cb_after_install: vpkc_hook_callback_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -483,10 +560,12 @@ pub extern "C" fn vpkc_app_set_hook_after_install(cb_after_install: vpkc_hook_ca
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets a callback to be run before the app is uninstalled.
|
||||
/// WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
/// Your code will be run and then the process will exit.
|
||||
/// If your code has not completed within 30 seconds, it will be terminated.
|
||||
/// Only supported on windows; On other operating systems, this will never be called.
|
||||
/// @param cb_before_uninstall The callback to run before the app is uninstalled. The callback takes a user data pointer and the version of the app as a string.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_hook_before_uninstall(cb_before_uninstall: vpkc_hook_callback_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -494,10 +573,12 @@ pub extern "C" fn vpkc_app_set_hook_before_uninstall(cb_before_uninstall: vpkc_h
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets a callback to be run before the app is updated.
|
||||
/// WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
/// Your code will be run and then the process will exit.
|
||||
/// If your code has not completed within 30 seconds, it will be terminated.
|
||||
/// Only supported on windows; On other operating systems, this will never be called.
|
||||
/// @param cb_before_update The callback to run before the app is updated. The callback takes a user data pointer and the version of the app as a string.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_hook_before_update(cb_before_update: vpkc_hook_callback_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -505,10 +586,12 @@ pub extern "C" fn vpkc_app_set_hook_before_update(cb_before_update: vpkc_hook_ca
|
||||
});
|
||||
}
|
||||
|
||||
/// Sets a callback to be run after the app is updated.
|
||||
/// WARNING: FastCallback hooks are run during critical stages of Velopack operations.
|
||||
/// Your code will be run and then the process will exit.
|
||||
/// If your code has not completed within 30 seconds, it will be terminated.
|
||||
/// Only supported on windows; On other operating systems, this will never be called.
|
||||
/// @param cb_after_update The callback to run after the app is updated. The callback takes a user data pointer and the version of the app as a string.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_hook_after_update(cb_after_update: vpkc_hook_callback_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -517,6 +600,7 @@ pub extern "C" fn vpkc_app_set_hook_after_update(cb_after_update: vpkc_hook_call
|
||||
}
|
||||
|
||||
/// This hook is triggered when the application is started for the first time after installation.
|
||||
/// @param cb_first_run The callback to run on first run. The callback takes a user data pointer and the version of the app as a string.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_hook_first_run(cb_first_run: vpkc_hook_callback_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -525,6 +609,7 @@ pub extern "C" fn vpkc_app_set_hook_first_run(cb_first_run: vpkc_hook_callback_t
|
||||
}
|
||||
|
||||
/// This hook is triggered when the application is restarted by Velopack after installing updates.
|
||||
/// @param cb_restarted The callback to run after the app is restarted. The callback takes a user data pointer and the version of the app as a string.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_app_set_hook_restarted(cb_restarted: vpkc_hook_callback_t) {
|
||||
update_app_options(|opt| {
|
||||
@@ -533,6 +618,9 @@ pub extern "C" fn vpkc_app_set_hook_restarted(cb_restarted: vpkc_hook_callback_t
|
||||
}
|
||||
|
||||
/// Get the last error message that occurred in the Velopack library.
|
||||
/// @param psz_error A buffer to store the error message.
|
||||
/// @param c_error The size of the `psz_error` buffer.
|
||||
/// @returns The number of characters written to `psz_error` (including null terminator). If the return value is greater than `c_error`, the buffer was too small and the message was truncated.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: size_t) -> size_t {
|
||||
let error = get_last_error();
|
||||
@@ -540,6 +628,8 @@ pub extern "C" fn vpkc_get_last_error(psz_error: *mut c_char, c_error: size_t) -
|
||||
}
|
||||
|
||||
/// Set a custom log callback. This will be called for all log messages generated by the Velopack library.
|
||||
/// @param cb_log The callback to call with log messages. The callback takes a user data pointer, a log level, and the log message as a string.
|
||||
/// @param p_user_data Optional user data to be passed to the callback.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn vpkc_set_logger(cb_log: vpkc_log_callback_t, p_user_data: *mut c_void) {
|
||||
set_log_callback(cb_log, p_user_data);
|
||||
|
||||
@@ -446,7 +446,7 @@ pub struct vpkc_update_options_t {
|
||||
/// ExplicitChannel to switch channels to another channel where the latest version on that
|
||||
/// channel is lower than the current version.
|
||||
pub AllowVersionDowngrade: bool,
|
||||
/// **This option should usually be left None**.
|
||||
/// **This option should usually be left None/NULL**.
|
||||
/// 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'.
|
||||
|
||||
@@ -128,13 +128,21 @@ namespace Velopack.Sources
|
||||
/// Given a repository URL (e.g. https://Gitea.com/myuser/myrepo) this function
|
||||
/// returns the API base for performing requests. (eg. "https://api.Gitea.com/"
|
||||
/// or http://internal.Gitea.server.local/api/v1)
|
||||
/// or http://localhost:3000/api/v1
|
||||
/// </summary>
|
||||
/// <param name="repoUrl"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual Uri GetApiBaseUrl(Uri repoUrl)
|
||||
{
|
||||
Uri baseAddress = new Uri(string.Format("{0}{1}{2}/api/v1/", repoUrl.Scheme, Uri.SchemeDelimiter, repoUrl.Host));
|
||||
// above ^^ notice the end slashes for the baseAddress, explained here: http://stackoverflow.com/a/23438417/162694
|
||||
Uri baseAddress;
|
||||
|
||||
if (repoUrl.IsDefaultPort) {
|
||||
baseAddress = new Uri(string.Format("{0}{1}{2}/api/v1/", repoUrl.Scheme, Uri.SchemeDelimiter, repoUrl.Host));
|
||||
// above ^^ notice the end slashes for the baseAddress, explained here: http://stackoverflow.com/a/23438417/162694
|
||||
} else {
|
||||
baseAddress = new Uri(string.Format("{0}{1}{2}:{3}/api/v1/", repoUrl.Scheme, Uri.SchemeDelimiter, repoUrl.Host, repoUrl.Port));
|
||||
}
|
||||
|
||||
return baseAddress;
|
||||
}
|
||||
}
|
||||
|
||||
56
src/lib-csharp/Util/SymbolicLink.Unix.cs
Normal file
56
src/lib-csharp/Util/SymbolicLink.Unix.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Text;
|
||||
|
||||
namespace Velopack.Util
|
||||
{
|
||||
internal static partial class SymbolicLink
|
||||
{
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern nint readlink(string path, byte[] buffer, ulong bufferSize);
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int symlink(string target, string linkPath);
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static string UnixReadLink(string symlinkPath)
|
||||
{
|
||||
const int bufferSize = 1024;
|
||||
const int EINTR = 4;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
nint bytesWritten;
|
||||
|
||||
do {
|
||||
bytesWritten = readlink(symlinkPath, buffer, bufferSize);
|
||||
} while (bytesWritten == -1 && Marshal.GetLastWin32Error() == EINTR);
|
||||
|
||||
if (bytesWritten < 1) {
|
||||
throw new InvalidOperationException($"Error resolving symlink: {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetString(buffer, 0, (int) bytesWritten);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
private static void UnixCreateSymlink(string target, string linkPath)
|
||||
{
|
||||
const int EINTR = 4;
|
||||
int result;
|
||||
|
||||
do {
|
||||
result = symlink(target, linkPath);
|
||||
} while (result == -1 && Marshal.GetLastWin32Error() == EINTR);
|
||||
|
||||
if (result == -1) {
|
||||
throw new InvalidOperationException($"Error creating symlink: {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
211
src/lib-csharp/Util/SymbolicLink.Windows.cs
Normal file
211
src/lib-csharp/Util/SymbolicLink.Windows.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Text;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace Velopack.Util
|
||||
{
|
||||
internal static partial class SymbolicLink
|
||||
{
|
||||
private const string Kernel32 = "kernel32.dll";
|
||||
|
||||
private const uint FSCTL_GET_REPARSE_POINT = 0x000900A8;
|
||||
private const uint IO_REPARSE_TAG_SYMLINK = 0xA000000C;
|
||||
private const uint IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003;
|
||||
private const int ERROR_NOT_A_REPARSE_POINT = 4390;
|
||||
private const int MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024;
|
||||
private const uint SYMLINK_FLAG_RELATIVE = 1;
|
||||
|
||||
private const uint GENERIC_READ = 0x80000000;
|
||||
private const uint FILE_SHARE_READ = 0x00000001;
|
||||
private const uint FILE_SHARE_WRITE = 0x00000002;
|
||||
private const uint OPEN_EXISTING = 3;
|
||||
private const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
|
||||
private const uint FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct ReparseHeader
|
||||
{
|
||||
public uint ReparseTag;
|
||||
public ushort ReparseDataLength;
|
||||
public ushort Reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct SymbolicData
|
||||
{
|
||||
public ushort SubstituteNameOffset;
|
||||
public ushort SubstituteNameLength;
|
||||
public ushort PrintNameOffset;
|
||||
public ushort PrintNameLength;
|
||||
public uint Flags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct JunctionData
|
||||
{
|
||||
public ushort SubstituteNameOffset;
|
||||
public ushort SubstituteNameLength;
|
||||
public ushort PrintNameOffset;
|
||||
public ushort PrintNameLength;
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateSymbolicLinkW")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
private static extern bool PInvokeWindowsCreateSymlink(
|
||||
[In]
|
||||
string lpSymlinkFileName,
|
||||
[In]
|
||||
string lpTargetFileName,
|
||||
[In]
|
||||
SymbolicLinkFlag dwFlags);
|
||||
|
||||
[DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern SafeFileHandle CreateFile(
|
||||
string lpFileName,
|
||||
uint dwDesiredAccess,
|
||||
uint dwShareMode,
|
||||
IntPtr lpSecurityAttributes,
|
||||
uint dwCreationDisposition,
|
||||
uint dwFlagsAndAttributes,
|
||||
IntPtr hTemplateFile);
|
||||
|
||||
[DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Auto)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool DeviceIoControl(
|
||||
SafeFileHandle hDevice,
|
||||
uint dwIoControlCode,
|
||||
IntPtr lpInBuffer,
|
||||
int nInBufferSize,
|
||||
IntPtr lpOutBuffer,
|
||||
int nOutBufferSize,
|
||||
out int lpBytesReturned,
|
||||
IntPtr lpOverlapped);
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static string WindowsReadLink(string symlinkPath)
|
||||
{
|
||||
using (var hReparsePoint = CreateFile(
|
||||
symlinkPath,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
IntPtr.Zero,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
IntPtr.Zero)) {
|
||||
if (hReparsePoint.IsInvalid) {
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
}
|
||||
|
||||
var buffer = Marshal.AllocHGlobal(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||
try {
|
||||
int bytesReturned;
|
||||
var success = DeviceIoControl(
|
||||
hReparsePoint,
|
||||
FSCTL_GET_REPARSE_POINT,
|
||||
IntPtr.Zero,
|
||||
0,
|
||||
buffer,
|
||||
MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
|
||||
out bytesReturned,
|
||||
IntPtr.Zero);
|
||||
|
||||
if (!success) {
|
||||
int error = Marshal.GetLastWin32Error();
|
||||
// The file or directory is not a reparse point.
|
||||
if (error == ERROR_NOT_A_REPARSE_POINT) {
|
||||
throw new InvalidOperationException($"Path is not a symbolic link: {symlinkPath}");
|
||||
}
|
||||
|
||||
throw new Win32Exception(error);
|
||||
}
|
||||
|
||||
var reparseHeader = Marshal.PtrToStructure<ReparseHeader>(buffer);
|
||||
var reparseHeaderSize = Marshal.SizeOf<ReparseHeader>();
|
||||
|
||||
// We always use SubstituteName instead of PrintName,
|
||||
// the latter is just the display name and can show something unrelated to the target.
|
||||
if (reparseHeader.ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
||||
var symbolicData = Marshal.PtrToStructure<SymbolicData>(buffer + reparseHeaderSize);
|
||||
var offset = Marshal.SizeOf<SymbolicData>() + reparseHeaderSize;
|
||||
var target = ReadStringFromBuffer(buffer, offset + symbolicData.SubstituteNameOffset, symbolicData.SubstituteNameLength);
|
||||
|
||||
bool isRelative = (symbolicData.Flags & SYMLINK_FLAG_RELATIVE) != 0;
|
||||
if (!isRelative) {
|
||||
// Absolute target is in NT format and we need to clean it up
|
||||
return ParseNTPath(target);
|
||||
}
|
||||
|
||||
// Return relative path as-is
|
||||
return target;
|
||||
} else if (reparseHeader.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
|
||||
var junctionData = Marshal.PtrToStructure<JunctionData>(buffer + reparseHeaderSize);
|
||||
var offset = Marshal.SizeOf<JunctionData>() + reparseHeaderSize;
|
||||
var target = ReadStringFromBuffer(buffer, offset + junctionData.SubstituteNameOffset, junctionData.SubstituteNameLength);
|
||||
|
||||
// Mount points are always absolute and in NT format
|
||||
return ParseNTPath(target);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Unsupported reparse point type: 0x{reparseHeader.ReparseTag:X}");
|
||||
} finally {
|
||||
Marshal.FreeHGlobal(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadStringFromBuffer(IntPtr buffer, int offset, int byteCount)
|
||||
{
|
||||
var bytes = new byte[byteCount];
|
||||
Marshal.Copy(buffer + offset, bytes, 0, byteCount);
|
||||
return Encoding.Unicode.GetString(bytes);
|
||||
}
|
||||
|
||||
private static string ParseNTPath(string path)
|
||||
{
|
||||
// NT paths come in different forms:
|
||||
// \??\C:\foo - DOS device path
|
||||
// \DosDevices\C:\foo - DOS device path
|
||||
// \Global??\C:\foo - DOS device path
|
||||
// \??\UNC\server\share - UNC path
|
||||
|
||||
const string NTPathPrefix = "\\??\\";
|
||||
const string UNCNTPathPrefix = "\\??\\UNC\\";
|
||||
const string UNCPathPrefix = "\\\\";
|
||||
|
||||
if (path.StartsWith(UNCNTPathPrefix, StringComparison.OrdinalIgnoreCase)) {
|
||||
// Convert \??\UNC\server\share to \\server\share
|
||||
return UNCPathPrefix + path.Substring(UNCNTPathPrefix.Length);
|
||||
}
|
||||
|
||||
string[] dosDevicePrefixes = { NTPathPrefix, "\\DosDevices\\", "\\Global??\\" };
|
||||
|
||||
foreach (var prefix in dosDevicePrefixes) {
|
||||
if (path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) {
|
||||
path = path.Substring(prefix.Length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove trailing backslash except for root paths like C:\
|
||||
if (path.Length > 3 && path.EndsWith("\\")) {
|
||||
path = path.TrimEnd('\\');
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void WindowsCreateSymlink(string target, string linkPath, SymbolicLinkFlag mode)
|
||||
{
|
||||
if (!PInvokeWindowsCreateSymlink(linkPath, target, mode)) {
|
||||
var errorCode = Marshal.GetLastWin32Error();
|
||||
throw new InvalidOperationException($"Error creating symlink: {errorCode}", new Win32Exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using NCode.ReparsePoints;
|
||||
|
||||
namespace Velopack.Util
|
||||
{
|
||||
internal static class SymbolicLink
|
||||
internal static partial class SymbolicLink
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a symlink from the specified directory to the specified target directory.
|
||||
@@ -38,9 +35,9 @@ namespace Velopack.Util
|
||||
: targetPath;
|
||||
|
||||
if (Directory.Exists(targetPath)) {
|
||||
CreateDirectoryLink(linkPath, finalTarget, targetPath);
|
||||
CreateSymlink(linkPath, finalTarget, SymbolicLinkFlag.Directory);
|
||||
} else if (File.Exists(targetPath)) {
|
||||
CreateFileLink(linkPath, finalTarget);
|
||||
CreateSymlink(linkPath, finalTarget, SymbolicLinkFlag.File);
|
||||
} else {
|
||||
throw new IOException("Target path does not exist.");
|
||||
}
|
||||
@@ -63,7 +60,7 @@ namespace Velopack.Util
|
||||
{
|
||||
var isLink = TryGetLinkFsi(linkPath, out var fsi);
|
||||
if (fsi != null && !isLink) {
|
||||
throw new IOException("Path is not a junction point / symlink.");
|
||||
ThrowPathNotASymlinkException(linkPath);
|
||||
} else {
|
||||
fsi?.Delete();
|
||||
}
|
||||
@@ -77,6 +74,7 @@ namespace Velopack.Util
|
||||
public static string GetTarget(string linkPath, bool relative = false)
|
||||
{
|
||||
var target = GetUnresolvedTarget(linkPath);
|
||||
|
||||
if (relative) {
|
||||
if (Path.IsPathRooted(target)) {
|
||||
return PathUtil.MakePathRelativeTo(Path.GetDirectoryName(linkPath)!, target);
|
||||
@@ -92,63 +90,62 @@ namespace Velopack.Util
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateFileLink(string linkPath, string targetPath)
|
||||
[Serializable]
|
||||
private enum SymbolicLinkFlag : uint
|
||||
{
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var rp = new ReparsePointProvider();
|
||||
rp.CreateSymbolicLink(linkPath, targetPath, false);
|
||||
} else {
|
||||
#if NETSTANDARD
|
||||
UnixCreateSymlink(targetPath, linkPath);
|
||||
#elif NET6_0_OR_GREATER
|
||||
File.CreateSymbolicLink(linkPath, targetPath);
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
File = 0,
|
||||
Directory = 1,
|
||||
}
|
||||
|
||||
private static void CreateDirectoryLink(string linkPath, string targetPath, string absoluteTargetPath)
|
||||
private static void CreateSymlink(string linkPath, string targetPath, SymbolicLinkFlag mode)
|
||||
{
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var rp = new ReparsePointProvider();
|
||||
try {
|
||||
rp.CreateSymbolicLink(linkPath, targetPath, true);
|
||||
} catch (Win32Exception ex) when (ex.NativeErrorCode == 1314) {
|
||||
// on windows 10 and below, symbolic links can only be created by an administrator
|
||||
// junctions also do not support relative target path's
|
||||
rp.CreateJunction(linkPath, absoluteTargetPath);
|
||||
}
|
||||
} else {
|
||||
#if NETSTANDARD
|
||||
UnixCreateSymlink(targetPath, linkPath);
|
||||
#elif NET6_0_OR_GREATER
|
||||
linkPath = linkPath.TrimEnd('\\', '/');
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
if (mode == SymbolicLinkFlag.File) {
|
||||
File.CreateSymbolicLink(linkPath, targetPath);
|
||||
} else if (mode == SymbolicLinkFlag.Directory) {
|
||||
Directory.CreateSymbolicLink(linkPath, targetPath);
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
#endif
|
||||
} else {
|
||||
throw new ArgumentOutOfRangeException(nameof(mode), mode, "Invalid symbolic link mode.");
|
||||
}
|
||||
#else
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
WindowsCreateSymlink(targetPath, linkPath, mode);
|
||||
} else if (VelopackRuntimeInfo.IsLinux || VelopackRuntimeInfo.IsOSX) {
|
||||
UnixCreateSymlink(targetPath, linkPath);
|
||||
} else {
|
||||
throw new NotSupportedException("Symbolic links are not supported on this platform.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static string GetUnresolvedTarget(string linkPath)
|
||||
{
|
||||
linkPath = linkPath.TrimEnd('\\', '/');
|
||||
|
||||
if (!TryGetLinkFsi(linkPath, out var fsi)) {
|
||||
throw new IOException("Path does not exist or is not a junction point / symlink.");
|
||||
ThrowPathNotASymlinkException(linkPath);
|
||||
}
|
||||
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var rp = new ReparsePointProvider();
|
||||
var link = rp.GetLink(linkPath);
|
||||
return link.Target;
|
||||
} else {
|
||||
#if NETSTANDARD
|
||||
return UnixReadLink(linkPath);
|
||||
#elif NET6_0_OR_GREATER
|
||||
return fsi!.LinkTarget!;
|
||||
string target;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
target = fsi!.LinkTarget!;
|
||||
#else
|
||||
throw new NotSupportedException();
|
||||
#endif
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
target = WindowsReadLink(linkPath);
|
||||
} else if (VelopackRuntimeInfo.IsLinux || VelopackRuntimeInfo.IsOSX) {
|
||||
target = UnixReadLink(linkPath);
|
||||
} else {
|
||||
throw new NotSupportedException("Symbolic links are not supported on this platform.");
|
||||
}
|
||||
#endif
|
||||
if (String.IsNullOrEmpty(target)) {
|
||||
ThrowPathNotASymlinkException(linkPath);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
private static bool TryGetLinkFsi(string path, out FileSystemInfo? fsi)
|
||||
@@ -167,36 +164,12 @@ namespace Velopack.Util
|
||||
return (fsi.Attributes & FileAttributes.ReparsePoint) != 0;
|
||||
}
|
||||
|
||||
#if NETSTANDARD
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern nint readlink(string path, byte[] buffer, ulong bufferSize);
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int symlink(string target, string linkPath);
|
||||
|
||||
private static string UnixReadLink(string symlinkPath)
|
||||
{
|
||||
const int bufferSize = 1024;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
nint bytesWritten = readlink(symlinkPath, buffer, bufferSize);
|
||||
|
||||
if (bytesWritten < 1) {
|
||||
throw new InvalidOperationException($"Error resolving symlink: {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetString(buffer, 0, (int) bytesWritten);
|
||||
}
|
||||
|
||||
private static void UnixCreateSymlink(string target, string linkPath)
|
||||
{
|
||||
// Call the symlink function from libc
|
||||
int result = symlink(target, linkPath);
|
||||
|
||||
// Check for errors (-1 return value indicates failure)
|
||||
if (result == -1) {
|
||||
throw new InvalidOperationException($"Error creating symlink: {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
}
|
||||
#if NET6_0_OR_GREATER
|
||||
[DoesNotReturn]
|
||||
#endif
|
||||
private static void ThrowPathNotASymlinkException(string path)
|
||||
{
|
||||
throw new IOException($"The path '{path}' is not a symbolic link or junction point.");
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/lib-nodejs/package-lock.json
generated
24
src/lib-nodejs/package-lock.json
generated
@@ -1459,9 +1459,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1566,9 +1566,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001721",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
|
||||
"integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
|
||||
"version": "1.0.30001723",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz",
|
||||
"integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -1898,9 +1898,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.165",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz",
|
||||
"integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==",
|
||||
"version": "1.5.167",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz",
|
||||
"integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
@@ -2073,9 +2073,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/filelist/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { VelopackAsset } from "./VelopackAsset";
|
||||
|
||||
/**
|
||||
* Holds information about the current version and pending updates, such as how many there are, and access to release notes.
|
||||
*/
|
||||
export type UpdateInfo = {
|
||||
/**
|
||||
* The available version that we are updating to.
|
||||
*/
|
||||
TargetFullRelease: VelopackAsset,
|
||||
/**
|
||||
* The base release that this update is based on. This is only available if the update is a delta update.
|
||||
*/
|
||||
BaseRelease: VelopackAsset | null,
|
||||
/**
|
||||
* The list of delta updates that can be applied to the base version to get to the target version.
|
||||
*/
|
||||
DeltasToTarget: Array<VelopackAsset>,
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
IsDowngrade: boolean, };
|
||||
@@ -1,28 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Options to customise the behaviour of UpdateManager.
|
||||
*/
|
||||
export type UpdateOptions = {
|
||||
/**
|
||||
* Allows UpdateManager to update to a version that's lower than the current version (i.e. downgrading).
|
||||
* This could happen if a release has bugs and was retracted from the release feed, or if you're using
|
||||
* ExplicitChannel to switch channels to another channel where the latest version on that
|
||||
* channel is lower than the current version.
|
||||
*/
|
||||
AllowVersionDowngrade: boolean,
|
||||
/**
|
||||
* **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'.
|
||||
* This allows users to automatically receive updates from the same channel they installed from. This options
|
||||
* 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.
|
||||
*/
|
||||
ExplicitChannel: string | null,
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
MaximumDeltasBeforeFallback: number, };
|
||||
@@ -1,42 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* An individual Velopack asset, could refer to an asset on-disk or in a remote package feed.
|
||||
*/
|
||||
export type VelopackAsset = {
|
||||
/**
|
||||
* The name or Id of the package containing this release.
|
||||
*/
|
||||
PackageId: string,
|
||||
/**
|
||||
* The version of this release.
|
||||
*/
|
||||
Version: string,
|
||||
/**
|
||||
* The type of asset (eg. "Full" or "Delta").
|
||||
*/
|
||||
Type: string,
|
||||
/**
|
||||
* The filename of the update package containing this release.
|
||||
*/
|
||||
FileName: string,
|
||||
/**
|
||||
* The SHA1 checksum of the update package containing this release.
|
||||
*/
|
||||
SHA1: string,
|
||||
/**
|
||||
* The SHA256 checksum of the update package containing this release.
|
||||
*/
|
||||
SHA256: string,
|
||||
/**
|
||||
* The size in bytes of the update package containing this release.
|
||||
*/
|
||||
Size: bigint,
|
||||
/**
|
||||
* The release notes in markdown format, as passed to Velopack when packaging the release. This may be an empty string.
|
||||
*/
|
||||
NotesMarkdown: string,
|
||||
/**
|
||||
* The release notes in HTML format, transformed from Markdown when packaging the release. This may be an empty string.
|
||||
*/
|
||||
NotesHtml: string, };
|
||||
@@ -1,30 +0,0 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth).
|
||||
*/
|
||||
export type VelopackLocatorConfig = {
|
||||
/**
|
||||
* The root directory of the current app.
|
||||
*/
|
||||
RootAppDir: string,
|
||||
/**
|
||||
* The path to the Update.exe binary.
|
||||
*/
|
||||
UpdateExePath: string,
|
||||
/**
|
||||
* The path to the packages' directory.
|
||||
*/
|
||||
PackagesDir: string,
|
||||
/**
|
||||
* The current app manifest.
|
||||
*/
|
||||
ManifestPath: string,
|
||||
/**
|
||||
* The directory containing the application's user binaries.
|
||||
*/
|
||||
CurrentBinaryDir: string,
|
||||
/**
|
||||
* Whether the current application is portable or installed.
|
||||
*/
|
||||
IsPortable: boolean, };
|
||||
@@ -1,9 +1,7 @@
|
||||
import * as addon from "./load";
|
||||
import type { UpdateInfo } from "./bindings/UpdateInfo";
|
||||
import type { UpdateOptions } from "./bindings/UpdateOptions";
|
||||
import type { VelopackLocatorConfig } from "./bindings/VelopackLocatorConfig";
|
||||
|
||||
export { UpdateInfo, UpdateOptions, VelopackLocatorConfig };
|
||||
import type { UpdateInfo, UpdateOptions, VelopackLocatorConfig, VelopackAsset } from "./types";
|
||||
export { UpdateInfo, UpdateOptions, VelopackLocatorConfig, VelopackAsset };
|
||||
|
||||
type UpdateManagerOpaque = {};
|
||||
declare module "./load" {
|
||||
@@ -21,7 +19,7 @@ declare module "./load" {
|
||||
|
||||
function js_update_pending_restart(
|
||||
um: UpdateManagerOpaque,
|
||||
): UpdateInfo | null;
|
||||
): string | null;
|
||||
|
||||
function js_check_for_updates_async(
|
||||
um: UpdateManagerOpaque,
|
||||
@@ -241,11 +239,15 @@ export class UpdateManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Returns an VelopackAsset object if there is an update downloaded which still needs to be applied.
|
||||
* You can pass the VelopackAsset object to waitExitThenApplyUpdate to apply the update.
|
||||
*/
|
||||
getUpdatePendingRestart(): UpdateInfo | null {
|
||||
return addon.js_update_pending_restart(this.opaque);
|
||||
getUpdatePendingRestart(): VelopackAsset | null {
|
||||
let json: string | null = addon.js_update_pending_restart(this.opaque);
|
||||
if (json && json.length > 0) {
|
||||
return JSON.parse(json);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,7 +294,7 @@ export class UpdateManager {
|
||||
* optionally restart your app. The updater will only wait for 60 seconds before giving up.
|
||||
*/
|
||||
waitExitThenApplyUpdate(
|
||||
update: UpdateInfo,
|
||||
update: UpdateInfo | VelopackAsset,
|
||||
silent: boolean = false,
|
||||
restart: boolean = true,
|
||||
restartArgs: string[] = [],
|
||||
@@ -300,6 +302,12 @@ export class UpdateManager {
|
||||
if (!update) {
|
||||
throw new Error("update is required");
|
||||
}
|
||||
|
||||
// the backend API only accepts VelopackAsset, so we need to extract it from UpdateInfo
|
||||
if ("TargetFullRelease" in update && typeof update.TargetFullRelease === "object") {
|
||||
update = update.TargetFullRelease;
|
||||
}
|
||||
|
||||
addon.js_wait_exit_then_apply_update(
|
||||
this.opaque,
|
||||
JSON.stringify(update),
|
||||
|
||||
82
src/lib-nodejs/src/types.ts
Normal file
82
src/lib-nodejs/src/types.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
// This file is auto-generated. Do not edit by hand.
|
||||
|
||||
/** VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth). */
|
||||
export type VelopackLocatorConfig = {
|
||||
/** The root directory of the current app. */
|
||||
RootAppDir: string,
|
||||
/** The path to the Update.exe binary. */
|
||||
UpdateExePath: string,
|
||||
/** The path to the packages' directory. */
|
||||
PackagesDir: string,
|
||||
/** The current app manifest. */
|
||||
ManifestPath: string,
|
||||
/** The directory containing the application's user binaries. */
|
||||
CurrentBinaryDir: string,
|
||||
/** Whether the current application is portable or installed. */
|
||||
IsPortable: boolean,
|
||||
}
|
||||
|
||||
/** An individual Velopack asset, could refer to an asset on-disk or in a remote package feed. */
|
||||
export type VelopackAsset = {
|
||||
/** The name or Id of the package containing this release. */
|
||||
PackageId: string,
|
||||
/** The version of this release. */
|
||||
Version: string,
|
||||
/** The type of asset (eg. "Full" or "Delta"). */
|
||||
Type: string,
|
||||
/** The filename of the update package containing this release. */
|
||||
FileName: string,
|
||||
/** The SHA1 checksum of the update package containing this release. */
|
||||
SHA1: string,
|
||||
/** The SHA256 checksum of the update package containing this release. */
|
||||
SHA256: string,
|
||||
/** The size in bytes of the update package containing this release. */
|
||||
Size: number,
|
||||
/** The release notes in markdown format, as passed to Velopack when packaging the release. This may be an empty string. */
|
||||
NotesMarkdown: string,
|
||||
/** The release notes in HTML format, transformed from Markdown when packaging the release. This may be an empty string. */
|
||||
NotesHtml: string,
|
||||
}
|
||||
|
||||
/** Holds information about the current version and pending updates, such as how many there are, and access to release notes. */
|
||||
export type UpdateInfo = {
|
||||
/** The available version that we are updating to. */
|
||||
TargetFullRelease: VelopackAsset,
|
||||
/** The base release that this update is based on. This is only available if the update is a delta update. */
|
||||
BaseRelease?: VelopackAsset,
|
||||
/** The list of delta updates that can be applied to the base version to get to the target version. */
|
||||
DeltasToTarget: VelopackAsset[],
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
IsDowngrade: boolean,
|
||||
}
|
||||
|
||||
/** Options to customise the behaviour of UpdateManager. */
|
||||
export type UpdateOptions = {
|
||||
/**
|
||||
* Allows UpdateManager to update to a version that's lower than the current version (i.e. downgrading).
|
||||
* This could happen if a release has bugs and was retracted from the release feed, or if you're using
|
||||
* ExplicitChannel to switch channels to another channel where the latest version on that
|
||||
* channel is lower than the current version.
|
||||
*/
|
||||
AllowVersionDowngrade: boolean,
|
||||
/**
|
||||
* **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'.
|
||||
* This allows users to automatically receive updates from the same channel they installed from. This options
|
||||
* 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.
|
||||
*/
|
||||
ExplicitChannel?: string,
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
MaximumDeltasBeforeFallback: number,
|
||||
}
|
||||
|
||||
@@ -24,8 +24,4 @@ semver.workspace = true
|
||||
log.workspace = true
|
||||
simplelog.workspace = true
|
||||
lazy_static.workspace = true
|
||||
neon.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
velopack = { workspace = true, features = ["typescript"] }
|
||||
ts-rs.workspace = true
|
||||
neon.workspace = true
|
||||
@@ -1,12 +0,0 @@
|
||||
use std::{env, path::Path};
|
||||
use locator::VelopackLocatorConfig;
|
||||
use ts_rs::TS;
|
||||
use velopack::*;
|
||||
|
||||
fn main() {
|
||||
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let bindings_dir = Path::new(&manifest_dir).join("..").join("src").join("bindings");
|
||||
UpdateInfo::export_all_to(&bindings_dir).unwrap();
|
||||
UpdateOptions::export_all_to(&bindings_dir).unwrap();
|
||||
VelopackLocatorConfig::export_all_to(&bindings_dir).unwrap();
|
||||
}
|
||||
@@ -209,12 +209,12 @@ fn js_wait_exit_then_apply_update(mut cx: FunctionContext) -> JsResult<JsUndefin
|
||||
let arg_silent = cx.argument::<JsBoolean>(2)?.value(&mut cx);
|
||||
let arg_restart = cx.argument::<JsBoolean>(3)?.value(&mut cx);
|
||||
|
||||
let update_info = serde_json::from_str::<UpdateInfo>(&arg_update).or_else(|e| cx.throw_error(e.to_string()))?;
|
||||
let asset = serde_json::from_str::<VelopackAsset>(&arg_update).or_else(|e| cx.throw_error(e.to_string()))?;
|
||||
|
||||
let arg_restart_args = cx.argument::<JsArray>(4)?;
|
||||
let restart_args = args_array_to_vec_string(&mut cx, arg_restart_args)?;
|
||||
|
||||
mgr_ref.wait_exit_then_apply_updates(update_info, arg_silent, arg_restart, restart_args).or_else(|e| cx.throw_error(e.to_string()))?;
|
||||
mgr_ref.wait_exit_then_apply_updates(asset, arg_silent, arg_restart, restart_args).or_else(|e| cx.throw_error(e.to_string()))?;
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,28 @@ use app::VelopackAppWrapper;
|
||||
mod manager;
|
||||
use manager::UpdateManagerWrapper;
|
||||
|
||||
use ::velopack::VelopackAsset;
|
||||
|
||||
#[derive(FromPyObject)]
|
||||
pub enum PyUpdateInfoOrAsset {
|
||||
UpdateInfo(PyUpdateInfo),
|
||||
Asset(PyVelopackAsset),
|
||||
}
|
||||
|
||||
impl PyUpdateInfoOrAsset {
|
||||
pub fn into_asset(self) -> VelopackAsset {
|
||||
match self {
|
||||
PyUpdateInfoOrAsset::UpdateInfo(update_info) => update_info.TargetFullRelease.into(),
|
||||
PyUpdateInfoOrAsset::Asset(asset) => asset.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymodule]
|
||||
#[pyo3(name = "velopack")]
|
||||
fn velopack(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
pyo3_log::init();
|
||||
|
||||
|
||||
// auto-generated DTO's
|
||||
m.add_class::<PyVelopackAsset>()?;
|
||||
m.add_class::<PyUpdateInfo>()?;
|
||||
|
||||
@@ -4,9 +4,9 @@ use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
use velopack::sources::AutoSource;
|
||||
use velopack::{UpdateCheck, UpdateInfo, UpdateManager as VelopackUpdateManagerRust};
|
||||
use velopack::{UpdateCheck, UpdateInfo, UpdateManager as VelopackUpdateManagerRust, VelopackAsset};
|
||||
|
||||
use crate::types::*;
|
||||
use crate::{types::*, PyUpdateInfoOrAsset};
|
||||
|
||||
#[pyclass(name = "UpdateManager")]
|
||||
pub struct UpdateManagerWrapper {
|
||||
@@ -19,13 +19,30 @@ impl UpdateManagerWrapper {
|
||||
#[pyo3(signature = (source, options = None, locator = None))]
|
||||
pub fn new(source: String, options: Option<PyUpdateOptions>, locator: Option<PyVelopackLocatorConfig>) -> Result<Self> {
|
||||
let source = AutoSource::new(&source);
|
||||
// set myinner to a new VelopackUpdateManager with the source
|
||||
let inner = VelopackUpdateManagerRust::new(source, options.map(Into::into), locator.map(Into::into))?;
|
||||
Ok(UpdateManagerWrapper { inner })
|
||||
}
|
||||
|
||||
pub fn check_for_updates(&mut self) -> Result<Option<PyUpdateInfo>> {
|
||||
let update_check = self.inner.check_for_updates()?;
|
||||
pub fn get_current_version(&self) -> String {
|
||||
self.inner.get_current_version_as_string()
|
||||
}
|
||||
|
||||
pub fn get_app_id(&self) -> String {
|
||||
self.inner.get_app_id().to_string()
|
||||
}
|
||||
|
||||
pub fn get_is_portable(&self) -> bool {
|
||||
self.inner.get_is_portable()
|
||||
}
|
||||
|
||||
pub fn get_update_pending_restart(&self) -> Option<PyVelopackAsset> {
|
||||
let pending = self.inner.get_update_pending_restart();
|
||||
pending.map(Into::into)
|
||||
}
|
||||
|
||||
pub fn check_for_updates(&mut self, py: Python) -> Result<Option<PyUpdateInfo>> {
|
||||
// Release GIL during network operation
|
||||
let update_check = py.allow_threads(|| self.inner.check_for_updates())?;
|
||||
match update_check {
|
||||
UpdateCheck::UpdateAvailable(updates) => {
|
||||
let py_updates = PyUpdateInfo::from(updates);
|
||||
@@ -37,44 +54,80 @@ impl UpdateManagerWrapper {
|
||||
}
|
||||
|
||||
#[pyo3(signature = (update_info, progress_callback = None))]
|
||||
pub fn download_updates(&mut self, update_info: &PyUpdateInfo, progress_callback: Option<PyObject>) -> Result<()> {
|
||||
pub fn download_updates(&mut self, py: Python, update_info: PyUpdateInfo, progress_callback: Option<PyObject>) -> Result<()> {
|
||||
// Convert PyUpdateInfo back to rust UpdateInfo
|
||||
let rust_update_info: UpdateInfo = update_info.clone().into();
|
||||
let rust_update_info: UpdateInfo = update_info.into();
|
||||
|
||||
if let Some(callback) = progress_callback {
|
||||
// Create a channel for progress updates
|
||||
let (sender, receiver) = mpsc::channel::<i16>();
|
||||
|
||||
// Spawn a thread to handle progress updates
|
||||
let progress_thread = thread::spawn(move || {
|
||||
Python::with_gil(|py| {
|
||||
// Clone the callback for the thread
|
||||
let callback_clone = callback.clone_ref(py);
|
||||
|
||||
// Release the GIL before starting the download
|
||||
py.allow_threads(|| {
|
||||
// Spawn a thread to handle progress updates
|
||||
let progress_thread = thread::spawn(move || {
|
||||
while let Ok(progress) = receiver.recv() {
|
||||
if let Err(e) = callback.call1(py, (progress,)) {
|
||||
// Log error but continue - don't break the download
|
||||
eprintln!("Progress callback error: {}", e);
|
||||
break;
|
||||
}
|
||||
// Acquire GIL only when needed to call the callback
|
||||
Python::with_gil(|py| {
|
||||
if let Err(e) = callback_clone.call1(py, (progress,)) {
|
||||
// Log error but continue - don't break the download
|
||||
eprintln!("Progress callback error: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Call download with the sender
|
||||
let result = self.inner.download_updates(&rust_update_info, Some(sender))?;
|
||||
// Call download with the sender
|
||||
let result = self.inner.download_updates(&rust_update_info, Some(sender));
|
||||
|
||||
// Wait for the progress thread to finish
|
||||
let _ = progress_thread.join();
|
||||
Ok(result)
|
||||
// Wait for the progress thread to finish
|
||||
let _ = progress_thread.join();
|
||||
|
||||
result
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
// No progress callback provided
|
||||
self.inner.download_updates(&rust_update_info, None)?;
|
||||
// No progress callback provided - still release GIL for the download
|
||||
py.allow_threads(|| {
|
||||
self.inner.download_updates(&rust_update_info, None)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_updates_and_restart(&mut self, update_info: &PyUpdateInfo) -> Result<()> {
|
||||
// Convert PyUpdateInfo back to rust UpdateInfo
|
||||
let rust_update_info: UpdateInfo = update_info.clone().into();
|
||||
self.inner.apply_updates_and_restart(&rust_update_info)?;
|
||||
pub fn apply_updates_and_restart(&mut self, update: PyUpdateInfoOrAsset) -> Result<()> {
|
||||
let asset: VelopackAsset = update.into_asset();
|
||||
self.inner.apply_updates_and_restart(&asset)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply_updates_and_restart_with_args(&mut self, update: PyUpdateInfoOrAsset, restart_args: Vec<String>) -> Result<()> {
|
||||
let asset: VelopackAsset = update.into_asset();
|
||||
self.inner.apply_updates_and_restart_with_args(&asset, restart_args)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply_updates_and_exit(&mut self, update: PyUpdateInfoOrAsset) -> Result<()> {
|
||||
let asset: VelopackAsset = update.into_asset();
|
||||
self.inner.apply_updates_and_exit(&asset)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pyo3(signature = (update, silent = false, restart = true, restart_args = None))]
|
||||
pub fn wait_exit_then_apply_updates(
|
||||
&mut self,
|
||||
update: PyUpdateInfoOrAsset,
|
||||
silent: bool,
|
||||
restart: bool,
|
||||
restart_args: Option<Vec<String>>,
|
||||
) -> Result<()> {
|
||||
let asset: VelopackAsset = update.into_asset();
|
||||
let args = restart_args.unwrap_or_default();
|
||||
self.inner.wait_exit_then_apply_updates(&asset, silent, restart, args)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
69
src/lib-python/uv.lock
generated
69
src/lib-python/uv.lock
generated
@@ -38,7 +38,7 @@ resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "zipp", version = "3.22.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
||||
{ name = "zipp", version = "3.23.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" }
|
||||
wheels = [
|
||||
@@ -59,25 +59,25 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "maturin"
|
||||
version = "1.8.6"
|
||||
version = "1.8.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/34/bc/c7df50a359c3a31490785c77d1ddd5fc83cc8cc07a4eddd289dbae53545a/maturin-1.8.6.tar.gz", hash = "sha256:0e0dc2e0bfaa2e1bd238e0236cf8a2b7e2250ccaa29c1aa8d0e61fa664b0289d", size = 203320, upload-time = "2025-05-13T13:56:11.033Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5d/67/71098eb8cac6dacfc71b6b81645017811ad377c22c959cff524505cbc8d4/maturin-1.8.7.tar.gz", hash = "sha256:96c76353f94a153c5dc1a9d3916e75fcd17e6bf216a06dcdc2f84b9f98f374af", size = 205116, upload-time = "2025-06-09T13:58:15.09Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/f1/e493add40aebdab88ac1aefb41b9c84ac288fb00025bc96b9213ee02c958/maturin-1.8.6-py3-none-linux_armv6l.whl", hash = "sha256:1bf4c743dd2b24448e82b8c96251597818956ddf848e1d16b59356512c7e58d8", size = 7831195, upload-time = "2025-05-13T13:55:42.634Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/1c/588afdb7bf79c4f15e33e9af6d7f3b12ec662bc63a22919e3bf39afa2a1e/maturin-1.8.6-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4ea89cf76048bc760e12b36b608fc3f5ef4f7359c0895e9afe737be34041d948", size = 15276471, upload-time = "2025-05-13T13:55:46.196Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/0b/4ce97f7f3a42068fbb42ba47d8b072e098c060fc1f64d8523e5588c57543/maturin-1.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4dd2e2f005ca63ac7ef0dddf2d65324ee480277a11544dcc4e7e436af68034dd", size = 7966129, upload-time = "2025-05-13T13:55:48.633Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/bf/4eae9d12920c580baf9d47ee63fec3ae0233e90a3aa8987bd7909cdc36a0/maturin-1.8.6-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:b0637604774e2c50ab48a0e9023fe2f071837ecbc817c04ec28e1cfcc25224c2", size = 7835935, upload-time = "2025-05-13T13:55:51.235Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/aa/8090f8b3f5f7ec46bc95deb0f5b29bf52c98156ef594f2e65d20bf94cea1/maturin-1.8.6-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:bec5948c6475954c8089b17fae349966258756bb2ca05e54099e476a08070795", size = 8282553, upload-time = "2025-05-13T13:55:53.266Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/50/4348da6cc16c006dab4e6cd479cf00dc0afa80db289a115a314df9909ee6/maturin-1.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:62a65f70ebaadd6eb6083f5548413744f2ef12400445778e08d41d4facf15bbe", size = 7618339, upload-time = "2025-05-13T13:55:55.706Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/77/16458e29487d068c8cdb7f06a4403393568a10b44993fe2ec9c3b29fdccd/maturin-1.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:5c0ff7ad43883920032b63c94c76dcdd5758710d7b72b68db69e7826c40534ac", size = 7686748, upload-time = "2025-05-13T13:55:57.97Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/c1/a52f3c1171c053810606c7c7fae5ce4637446ef9df44f281862d2bef3750/maturin-1.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:ca30fdb158a24cf312f3e53072a6e987182c103fa613efea2d28b5f52707d04a", size = 9767394, upload-time = "2025-05-13T13:56:00.694Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/ab/abae74f36a0f200384eda985ebeb9ee5dcbb19bfe1558c3335ef6f297094/maturin-1.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1e786ec9b5f7315c7e3fcc62b0715f9d99ffe477b06d0d62655a71e6a51a67b", size = 10995574, upload-time = "2025-05-13T13:56:03.101Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/1c/c478578a62c1e34b5b0641a474de78cb56d6c4aad0ba88f90dfa9f2a15f7/maturin-1.8.6-py3-none-win32.whl", hash = "sha256:dade5edfaf508439ff6bbc7be4f207e04c0999c47d9ef7e1bae16258e76b1518", size = 7027171, upload-time = "2025-05-13T13:56:05.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/89/2c57d29f25e06696cb3c5b3770ba0b40dfe87f91a879ecbcdc92e071a26b/maturin-1.8.6-py3-none-win_amd64.whl", hash = "sha256:6bc9281b90cd37e2a7985f2e5d6e3d35a1d64cf6e4d04ce5ed25603d162995b9", size = 7947998, upload-time = "2025-05-13T13:56:07.428Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/f5/3ee1c6aa4e277323bef38ea0ec07262a9b88711d1a29cb5bb08ce3807a6f/maturin-1.8.6-py3-none-win_arm64.whl", hash = "sha256:24f66624db69b895b134a8f1592efdf04cd223c9b3b65243ad32080477936d14", size = 6684974, upload-time = "2025-05-13T13:56:09.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/58/fcd05985cbd9edd0232146a768e5fdcbda1f954ea82ec1c81f4d75d275c2/maturin-1.8.7-py3-none-linux_armv6l.whl", hash = "sha256:43526cc7fdc025b0d134b09d2cdbbe8fe816c4d72351822fa967d36784764bab", size = 8097702, upload-time = "2025-06-09T13:57:49.497Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/a5/f02d9661fe21321f6852ef740eda54fe257e91c5c906265db902d1989bc8/maturin-1.8.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5e134fc67e7f28e9f57d01dc2603c243456f80e76f93ef54ee61a4403dccd7e3", size = 16059837, upload-time = "2025-06-09T13:57:52.713Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/bc/51c9ce286909831bee0c5a64d769355cd8a84f373e22f7d7d07c78a829ec/maturin-1.8.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b560b86d6119c82430f9682f76708b3ea4984e5976afab6b844c9c8094709f78", size = 8381884, upload-time = "2025-06-09T13:57:55.275Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/ed/a5d84adbd0df3bb1b1e0f75b13a89446455f66d0070562f29ac30db5054a/maturin-1.8.7-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:272f34df99ff9be27174b0d2afaec98bac5217670bceddd796f45a0095849dd9", size = 8141538, upload-time = "2025-06-09T13:57:56.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/f8/ef902fb50454fd57a514b6bc1203f55b8c5dd5b0c5439fabe22aca0ef60e/maturin-1.8.7-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:c39f288b72ceae9274e612131c8a1a18bc248170910e27eb39956ffbd62bd712", size = 8795313, upload-time = "2025-06-09T13:57:58.99Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/13/9cfb7d799ceda322651be21af7d2b541eb125477db30a8dba408ec4a9813/maturin-1.8.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8766377b5339b354fc83195ee1d9879db2b1323ea485305c6932f97b1661334d", size = 7899633, upload-time = "2025-06-09T13:58:00.868Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/d2/46c98e5aef3011efa56dd0fc0ffc9bba4fef236339352af5876f0027af03/maturin-1.8.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:987b4e821c5ec2b5c6d75f4fcb6141d6418188356c3ff229c67f58c11ae54ded", size = 7960920, upload-time = "2025-06-09T13:58:02.826Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/b7/ec2dde6c5aefcf38279c6276a96f9351081f22174e9db56db394d0f32e67/maturin-1.8.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:15ec5919b334e421e97623446907a3f994fc04427ab2c9e5eab5a461565e6ce3", size = 10155481, upload-time = "2025-06-09T13:58:04.761Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/38/ef38d4a7008068212f8d11643178e8b0291d7cdd047b47f449243be5e5cd/maturin-1.8.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec37762228b76d4763e0ad18f7d70d8dbe52298ecdb0737bb4fd383a49fc2f06", size = 8995379, upload-time = "2025-06-09T13:58:07.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/79/f1b64d1d0e11ca4eb24a8b82d0916bc0e3e477b8a6879e9a6bee93b731f3/maturin-1.8.7-py3-none-win32.whl", hash = "sha256:834c2f8029c1e19e272b360102eead74fdb6df93d1cb6e645d6aeaec86b532f6", size = 7261393, upload-time = "2025-06-09T13:58:09.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/1e/efc95e4cab8fbbede2f8d28481bae44eee4a43cfe456e78854ef9952ec6b/maturin-1.8.7-py3-none-win_amd64.whl", hash = "sha256:ef44ade7b2401ebbd4b0d268e4b953b4256295c827a21e806a51d29f629ab638", size = 8300461, upload-time = "2025-06-09T13:58:11.545Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/2b/270b772f31844aae4297f178e81d5890c259973dedc68a48084a36c34ec1/maturin-1.8.7-py3-none-win_arm64.whl", hash = "sha256:20813b2262661a403fc0c695e3d4836257f992927fa2234928eb3510b13de2cd", size = 6973691, upload-time = "2025-06-09T13:58:13.223Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -100,7 +100,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller"
|
||||
version = "6.13.0"
|
||||
version = "6.14.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "altgraph" },
|
||||
@@ -114,24 +114,24 @@ dependencies = [
|
||||
{ name = "setuptools", version = "75.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
||||
{ name = "setuptools", version = "80.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/b1/2949fe6d3874e961898ca5cfc1bf2cf13bdeea488b302e74a745bc28c8ba/pyinstaller-6.13.0.tar.gz", hash = "sha256:38911feec2c5e215e5159a7e66fdb12400168bd116143b54a8a7a37f08733456", size = 4276427, upload-time = "2025-04-15T23:25:31.646Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/d66d3a9c34349d73eb099401060e2591da8ccc5ed427e54fff3961302513/pyinstaller-6.14.1.tar.gz", hash = "sha256:35d5c06a668e21f0122178dbf20e40fd21012dc8f6170042af6050c4e7b3edca", size = 4284317, upload-time = "2025-06-08T18:45:46.367Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/02/d1a347d35b1b627da1e148159e617576555619ac3bb8bbd5fed661fc7bb5/pyinstaller-6.13.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:aa404f0b02cd57948098055e76ee190b8e65ccf7a2a3f048e5000f668317069f", size = 1001923, upload-time = "2025-04-15T23:24:17.646Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/80/6da39f7aeac65c9ca5afad0fac37887d75fdfd480178a7077c9d30b0704c/pyinstaller-6.13.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:92efcf2f09e78f07b568c5cb7ed48c9940f5dad627af4b49bede6320fab2a06e", size = 718135, upload-time = "2025-04-15T23:24:22.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/2c/d21d31f780a489609e7bf6385c0f7635238dc98b37cba8645b53322b7450/pyinstaller-6.13.0-py3-none-manylinux2014_i686.whl", hash = "sha256:9f82f113c463f012faa0e323d952ca30a6f922685d9636e754bd3a256c7ed200", size = 728543, upload-time = "2025-04-15T23:24:27.02Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/20/e6ca87bbed6c0163533195707f820f05e10b8da1223fc6972cfe3c3c50c7/pyinstaller-6.13.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:db0e7945ebe276f604eb7c36e536479556ab32853412095e19172a5ec8fca1c5", size = 726868, upload-time = "2025-04-15T23:24:31.779Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/d5/53b19285f8817ab6c4b07c570208d62606bab0e5a049d50c93710a1d9dc6/pyinstaller-6.13.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:92fe7337c5aa08d42b38d7a79614492cb571489f2cb0a8f91dc9ef9ccbe01ed3", size = 725037, upload-time = "2025-04-15T23:24:36.244Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/5b/08e0b305ba71e6d7cb247e27d714da7536895b0283132d74d249bf662366/pyinstaller-6.13.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:bc09795f5954135dd4486c1535650958c8218acb954f43860e4b05fb515a21c0", size = 721027, upload-time = "2025-04-15T23:24:40.16Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/9c/d8d0a7120103471be8dbe1c5419542aa794b9b9ec2ef628b542f9e6f9ef0/pyinstaller-6.13.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:589937548d34978c568cfdc39f31cf386f45202bc27fdb8facb989c79dfb4c02", size = 723443, upload-time = "2025-04-15T23:24:50.63Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/c7/8a9d81569dda2352068ecc6ee779d5feff6729569dd1b4ffd1236ecd38fe/pyinstaller-6.13.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:b7260832f7501ba1d2ce1834d4cddc0f2b94315282bc89c59333433715015447", size = 719915, upload-time = "2025-04-15T23:24:54.917Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/e6/cccadb02b90198c7ed4ffb8bc34d420efb72b996f47cbd4738067a602d65/pyinstaller-6.13.0-py3-none-win32.whl", hash = "sha256:80c568848529635aa7ca46d8d525f68486d53e03f68b7bb5eba2c88d742e302c", size = 1294997, upload-time = "2025-04-15T23:25:01.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/06/15cbe0e25d1e73d5b981fa41ff0bb02b15e924e30b8c61256f4a28c4c837/pyinstaller-6.13.0-py3-none-win_amd64.whl", hash = "sha256:8d4296236b85aae570379488c2da833b28828b17c57c2cc21fccd7e3811fe372", size = 1352714, upload-time = "2025-04-15T23:25:08.061Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/ef/74379298d46e7caa6aa7ceccc865106d3d4b15ac487ffdda2a35bfb6fe79/pyinstaller-6.13.0-py3-none-win_arm64.whl", hash = "sha256:d9f21d56ca2443aa6a1e255e7ad285c76453893a454105abe1b4d45e92bb9a20", size = 1293589, upload-time = "2025-04-15T23:25:14.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/f6/fa56e547fe849db4b8da0acaad6101a6382c18370c7e0f378a1cf0ea89f0/pyinstaller-6.14.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:da559cfe4f7a20a7ebdafdf12ea2a03ea94d3caa49736ef53ee2c155d78422c9", size = 999937, upload-time = "2025-06-08T18:44:26.429Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/a6/a2814978f47ae038b1ce112717adbdcfd8dfb9504e5c52437902331cde1a/pyinstaller-6.14.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:f040d1e3d42af3730104078d10d4a8ca3350bd1c78de48f12e1b26f761e0cbc3", size = 719569, upload-time = "2025-06-08T18:44:30.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/f0/86391a4c0f558aef43a7dac8f678d46f4e5b84bd133308e3ea81f7384ab9/pyinstaller-6.14.1-py3-none-manylinux2014_i686.whl", hash = "sha256:7b8813fb2d5a82ef4ceffc342ed9a11a6fc1ef21e68e833dbd8fedb8a188d3f5", size = 729824, upload-time = "2025-06-08T18:44:34.983Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/88/446814e335d937406e6e1ae4a77ed922b8eea8b90f3aaf69427a16b58ed2/pyinstaller-6.14.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e2cfdbc6dd41d19872054fc233da18856ec422a7fdea899b6985ae04f980376a", size = 727937, upload-time = "2025-06-08T18:44:38.954Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/0f/5aa891c61d303ad4a794b7e2f864aacf64fe0f6f5559e2aec0f742595fad/pyinstaller-6.14.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:a4d53b3ecb5786b097b79bda88c4089186fc1498ef7eaa6cee57599ae459241e", size = 724762, upload-time = "2025-06-08T18:44:42.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/92/e32ec0a1754852a8ed5a60f6746c6483e3da68aee97d314f3a3a99e0ed9e/pyinstaller-6.14.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c48dd257f77f61ebea2d1fdbaf11243730f2271873c88d3b5ecb7869525d3bcb", size = 724957, upload-time = "2025-06-08T18:44:46.829Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/66/1260f384e47bf939f6238f791d4cda7edb94771d2fa0a451e0edb21ac9c7/pyinstaller-6.14.1-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:5b05cbb2ffc033b4681268159b82bac94b875475c339603c7e605f00a73c8746", size = 724132, upload-time = "2025-06-08T18:44:51.081Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/8b/8570ab94ec07e0b2b1203f45840353ee76aa067a2540c97da43d43477b26/pyinstaller-6.14.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:d5fd73757c8ea9adb2f9c1f81656335ba9890029ede3031835d768fde36e89f0", size = 723847, upload-time = "2025-06-08T18:44:54.896Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/43/6c68dc9e53b09ff948d6e46477932b387832bbb920c48061d734ef089368/pyinstaller-6.14.1-py3-none-win32.whl", hash = "sha256:547f7a93592e408cbfd093ce9fd9631215387dab0dbf3130351d3b0b1186a534", size = 1299744, upload-time = "2025-06-08T18:45:00.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/dd/bb8d5bcb0592f7f5d454ad308051d00ed34f8b08d5003400b825cfe35513/pyinstaller-6.14.1-py3-none-win_amd64.whl", hash = "sha256:0794290b4b56ef9d35858334deb29f36ec1e1f193b0f825212a0aa5a1bec5a2f", size = 1357625, upload-time = "2025-06-08T18:45:06.826Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/57/8a8979737980e50aa5031b77318ce783759bf25be2956317f2e1d7a65a09/pyinstaller-6.14.1-py3-none-win_arm64.whl", hash = "sha256:d9d99695827f892cb19644106da30681363e8ff27b8326ac8416d62890ab9c74", size = 1298607, upload-time = "2025-06-08T18:45:12.766Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyinstaller-hooks-contrib"
|
||||
version = "2025.4"
|
||||
version = "2025.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "importlib-metadata", version = "8.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
||||
@@ -140,9 +140,9 @@ dependencies = [
|
||||
{ name = "setuptools", version = "75.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
||||
{ name = "setuptools", version = "80.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/94/dfc5c7903306211798f990e6794c2eb7b8685ac487b26979e9255790419c/pyinstaller_hooks_contrib-2025.4.tar.gz", hash = "sha256:5ce1afd1997b03e70f546207031cfdf2782030aabacc102190677059e2856446", size = 162628, upload-time = "2025-05-03T20:15:55.983Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5f/ff/e3376595935d5f8135964d2177cd3e3e0c1b5a6237497d9775237c247a5d/pyinstaller_hooks_contrib-2025.5.tar.gz", hash = "sha256:707386770b8fe066c04aad18a71bc483c7b25e18b4750a756999f7da2ab31982", size = 163124, upload-time = "2025-06-08T18:47:53.26Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/e1/ed48c7074145898e5c5b0072e87be975c5bd6a1d0f08c27a1daa7064fca0/pyinstaller_hooks_contrib-2025.4-py3-none-any.whl", hash = "sha256:6c2d73269b4c484eb40051fc1acee0beb113c2cfb3b37437b8394faae6f0d072", size = 434451, upload-time = "2025-05-03T20:15:54.579Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/2c/b4d317534e17dd1df95c394d4b37febb15ead006a1c07c2bb006481fb5e7/pyinstaller_hooks_contrib-2025.5-py3-none-any.whl", hash = "sha256:ebfae1ba341cb0002fb2770fad0edf2b3e913c2728d92df7ad562260988ca373", size = 437246, upload-time = "2025-06-08T18:47:51.516Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -219,6 +219,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "velopack"
|
||||
version = "0.0.1"
|
||||
source = { editable = "." }
|
||||
|
||||
[package.dev-dependencies]
|
||||
@@ -253,12 +254,12 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.22.0"
|
||||
version = "3.23.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
resolution-markers = [
|
||||
"python_full_version >= '3.9'",
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257, upload-time = "2025-05-26T14:46:32.217Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796, upload-time = "2025-05-26T14:46:30.775Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" },
|
||||
]
|
||||
|
||||
@@ -16,7 +16,6 @@ rust-version.workspace = true
|
||||
[features]
|
||||
default = []
|
||||
async = ["async-std"]
|
||||
typescript = ["ts-rs"]
|
||||
file-logging = ["log-panics", "simplelog", "time"]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
@@ -50,9 +49,6 @@ sha1.workspace = true
|
||||
sha2.workspace = true
|
||||
uuid.workspace = true
|
||||
|
||||
# typescript
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
# async
|
||||
async-std = { workspace = true, optional = true }
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ pub fn load_bundle_from_file<'a, P: AsRef<Path>>(file_name: P) -> Result<BundleZ
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_bundle_from_memory(zip_range: &[u8]) -> Result<BundleZip, Error> {
|
||||
pub fn load_bundle_from_memory<'a>(zip_range: &'a [u8]) -> Result<BundleZip<'a>, Error> {
|
||||
info!("Loading bundle from embedded zip...");
|
||||
let cursor: Box<dyn ReadSeek> = Box::new(Cursor::new(zip_range));
|
||||
let zip = ZipArchive::new(cursor)?;
|
||||
|
||||
@@ -59,7 +59,6 @@ impl ShortcutLocationFlags {
|
||||
/// VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth).
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
pub struct VelopackLocatorConfig {
|
||||
/// The root directory of the current app.
|
||||
pub RootAppDir: PathBuf,
|
||||
|
||||
@@ -52,7 +52,6 @@ impl VelopackAssetFeed {
|
||||
/// An individual Velopack asset, could refer to an asset on-disk or in a remote package feed.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(default)]
|
||||
pub struct VelopackAsset {
|
||||
/// The name or Id of the package containing this release.
|
||||
@@ -78,7 +77,6 @@ pub struct VelopackAsset {
|
||||
/// Holds information about the current version and pending updates, such as how many there are, and access to release notes.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(default)]
|
||||
pub struct UpdateInfo {
|
||||
/// The available version that we are updating to.
|
||||
@@ -118,7 +116,6 @@ impl AsRef<VelopackAsset> for VelopackAsset {
|
||||
/// Options to customise the behaviour of UpdateManager.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
|
||||
#[serde(default)]
|
||||
pub struct UpdateOptions {
|
||||
/// Allows UpdateManager to update to a version that's lower than the current version (i.e. downgrading).
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Azure;
|
||||
using System.Text;
|
||||
using Azure;
|
||||
using Azure.Storage;
|
||||
using Azure.Storage.Blobs;
|
||||
using Azure.Storage.Blobs.Models;
|
||||
@@ -19,6 +20,8 @@ public class AzureDownloadOptions : RepositoryOptions, IObjectDownloadOptions
|
||||
public string Container { get; set; }
|
||||
|
||||
public string SasToken { get; set; }
|
||||
|
||||
public string Prefix { get; set; }
|
||||
}
|
||||
|
||||
public class AzureUploadOptions : AzureDownloadOptions, IObjectUploadOptions
|
||||
@@ -26,13 +29,26 @@ public class AzureUploadOptions : AzureDownloadOptions, IObjectUploadOptions
|
||||
public int KeepMaxReleases { get; set; }
|
||||
}
|
||||
|
||||
public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploadOptions, BlobContainerClient>
|
||||
public class AzureBlobClient(BlobContainerClient client, string prefix)
|
||||
{
|
||||
public virtual Task DeleteBlobIfExistsAsync(string key, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return client.DeleteBlobIfExistsAsync(prefix + key, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public virtual BlobClient GetBlobClient(string key)
|
||||
{
|
||||
return client.GetBlobClient(prefix + key);
|
||||
}
|
||||
}
|
||||
|
||||
public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploadOptions, AzureBlobClient>
|
||||
{
|
||||
public AzureRepository(ILogger logger) : base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
protected override BlobContainerClient CreateClient(AzureDownloadOptions options)
|
||||
protected override AzureBlobClient CreateClient(AzureDownloadOptions options)
|
||||
{
|
||||
var serviceUrl = options.Endpoint ?? "https://" + options.Account + ".blob.core.windows.net";
|
||||
if (options.Endpoint == null) {
|
||||
@@ -51,10 +67,21 @@ public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploa
|
||||
client = new BlobServiceClient(new Uri(serviceUrl), new StorageSharedKeyCredential(options.Account, options.Key), clientOptions);
|
||||
}
|
||||
|
||||
return client.GetBlobContainerClient(options.Container);
|
||||
var containerClient = client.GetBlobContainerClient(options.Container);
|
||||
|
||||
var prefix = options.Prefix?.Trim();
|
||||
if (prefix == null) {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(prefix) && !prefix.EndsWith("/")) {
|
||||
prefix += "/";
|
||||
}
|
||||
|
||||
return new AzureBlobClient(containerClient, prefix);
|
||||
}
|
||||
|
||||
protected override async Task DeleteObject(BlobContainerClient client, string key)
|
||||
protected override async Task DeleteObject(AzureBlobClient client, string key)
|
||||
{
|
||||
await RetryAsync(
|
||||
async () => {
|
||||
@@ -63,7 +90,7 @@ public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploa
|
||||
"Deleting " + key);
|
||||
}
|
||||
|
||||
protected override async Task<byte[]> GetObjectBytes(BlobContainerClient client, string key)
|
||||
protected override async Task<byte[]> GetObjectBytes(AzureBlobClient client, string key)
|
||||
{
|
||||
return await RetryAsyncRet(
|
||||
async () => {
|
||||
@@ -79,6 +106,17 @@ public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploa
|
||||
$"Downloading {key}...");
|
||||
}
|
||||
|
||||
protected override async Task<VelopackAssetFeed> GetReleasesAsync(AzureDownloadOptions options)
|
||||
{
|
||||
var releasesName = CoreUtil.GetVeloReleaseIndexName(options.Channel);
|
||||
var client = CreateClient(options);
|
||||
var bytes = await GetObjectBytes(client, releasesName);
|
||||
if (bytes == null || bytes.Length == 0) {
|
||||
return new VelopackAssetFeed();
|
||||
}
|
||||
return VelopackAssetFeed.FromJson(Encoding.UTF8.GetString(bytes));
|
||||
}
|
||||
|
||||
protected override async Task SaveEntryToFileAsync(AzureDownloadOptions options, VelopackAsset entry, string filePath)
|
||||
{
|
||||
await RetryAsync(
|
||||
@@ -90,7 +128,8 @@ public class AzureRepository : ObjectRepository<AzureDownloadOptions, AzureUploa
|
||||
$"Downloading {entry.FileName}...");
|
||||
}
|
||||
|
||||
protected override async Task UploadObject(BlobContainerClient client, string key, FileInfo f, bool overwriteRemote, bool noCache)
|
||||
|
||||
protected override async Task UploadObject(AzureBlobClient client, string key, FileInfo f, bool overwriteRemote, bool noCache)
|
||||
{
|
||||
var blobClient = client.GetBlobClient(key);
|
||||
try {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AWSSDK.S3" Version="4.0.1.3" />
|
||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.24.0" />
|
||||
<PackageReference Include="Gitea.Net.API" Version="25.3.5" />
|
||||
<PackageReference Include="Gitea.Net.API" Version="25.8.18" />
|
||||
<PackageReference Include="Octokit" Version="14.0.0" />
|
||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.10" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.11" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -34,6 +34,10 @@ public class LinuxPackCommandRunner : PackageBuilder<LinuxPackOptions>
|
||||
File.Copy(icon, Path.Combine(dir.FullName, iconFilename), true);
|
||||
File.Copy(icon, Path.Combine(dir.FullName, ".DirIcon"), true);
|
||||
|
||||
string iconDirPath = Path.Combine(dir.FullName, "usr", "share", "icons", "hicolor", "scalable", "apps");
|
||||
Directory.CreateDirectory(iconDirPath);
|
||||
File.Copy(icon, Path.Combine(iconDirPath, iconFilename), true);
|
||||
|
||||
var categories = String.IsNullOrWhiteSpace(Options.Categories)
|
||||
? "Utility"
|
||||
: Options.Categories.TrimEnd(';');
|
||||
|
||||
@@ -46,7 +46,6 @@ public class OsxPackCommandRunner : PackageBuilder<OsxPackOptions>
|
||||
|
||||
var structure = new OsxStructureBuilder(dir.FullName);
|
||||
var macosdir = structure.MacosDirectory;
|
||||
File.WriteAllText(Path.Combine(macosdir, "sq.version"), GenerateNuspecContent());
|
||||
File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), Path.Combine(macosdir, "UpdateMac"), true);
|
||||
|
||||
foreach (var f in Directory.GetFiles(macosdir, "*", SearchOption.AllDirectories)) {
|
||||
@@ -56,6 +55,12 @@ public class OsxPackCommandRunner : PackageBuilder<OsxPackOptions>
|
||||
}
|
||||
}
|
||||
|
||||
// Files in the MacOS directory need to be signed, but text files are signed via xattrs, which we don't yet preserve
|
||||
// in nupkg releases. Instead we can put it in the Resources dir and symlink to it. Symlinks don't need to be signed.
|
||||
var resourcesdir = structure.ResourcesDirectory;
|
||||
File.WriteAllText(Path.Combine(resourcesdir, "sq.version"), GenerateNuspecContent());
|
||||
SymbolicLink.Create(Path.Combine(macosdir, "sq.version"), Path.Combine(resourcesdir, "sq.version"), false, true);
|
||||
|
||||
progress(100);
|
||||
return Task.FromResult(dir.FullName);
|
||||
}
|
||||
@@ -96,9 +101,6 @@ public class OsxPackCommandRunner : PackageBuilder<OsxPackOptions>
|
||||
var structure = new OsxStructureBuilder(packDir);
|
||||
var updateMacPath = Path.Combine(structure.MacosDirectory, "UpdateMac");
|
||||
helper.CodeSign(Options.SignAppIdentity, entitlements, updateMacPath, false, keychainPath);
|
||||
signProgress(25);
|
||||
var versionPath = Path.Combine(structure.MacosDirectory, "sq.version");
|
||||
helper.CodeSign(Options.SignAppIdentity, entitlements, versionPath, false, keychainPath);
|
||||
signProgress(50);
|
||||
|
||||
Log.Info("Code signing application bundle...");
|
||||
|
||||
@@ -12,31 +12,37 @@ public class AzureBaseCommand : OutputCommand
|
||||
|
||||
public string SasToken { get; private set; }
|
||||
|
||||
public string Prefix { get; private set; }
|
||||
|
||||
public double Timeout { get; private set; }
|
||||
|
||||
protected AzureBaseCommand(string name, string description)
|
||||
: base(name, description)
|
||||
{
|
||||
AddOption<string>((v) => Account = v, "--account")
|
||||
.SetDescription("Account name")
|
||||
.SetDescription("Account name.")
|
||||
.SetArgumentHelpName("ACCOUNT")
|
||||
.SetRequired();
|
||||
|
||||
var key = AddOption<string>((v) => Key = v, "--key")
|
||||
.SetDescription("Account secret key")
|
||||
.SetDescription("Account secret key.")
|
||||
.SetArgumentHelpName("KEY");
|
||||
|
||||
var sas = AddOption<string>((v) => SasToken = v, "--sas")
|
||||
.SetDescription("Shared access signature token (not the url)")
|
||||
.SetDescription("Shared access signature token (not the url).")
|
||||
.SetArgumentHelpName("TOKEN");
|
||||
|
||||
AddOption<string>((v) => Container = v, "--container")
|
||||
.SetDescription("Azure container name")
|
||||
.SetDescription("Azure storage container name.")
|
||||
.SetArgumentHelpName("NAME")
|
||||
.SetRequired();
|
||||
|
||||
AddOption<string>((v) => Prefix = v, "--prefix")
|
||||
.SetDescription("Optional blob filename path prefix.")
|
||||
.SetArgumentHelpName("PREFIX");
|
||||
|
||||
AddOption<Uri>((v) => Endpoint = v.ToAbsoluteOrNull(), "--endpoint")
|
||||
.SetDescription("Service url (eg. https://<account-name>.blob.core.windows.net)")
|
||||
.SetDescription("Service url (eg. https://<account-name>.blob.core.windows.net).")
|
||||
.SetArgumentHelpName("URL")
|
||||
.MustBeValidHttpUri();
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public class S3BaseCommand : OutputCommand
|
||||
.SetRequired();
|
||||
|
||||
AddOption<string>((v) => Prefix = v, "--prefix")
|
||||
.SetDescription("Prefix to the S3 url.")
|
||||
.SetDescription("Optional filename path prefix.")
|
||||
.SetArgumentHelpName("PREFIX");
|
||||
|
||||
AddOption<bool>((v) => DisablePathStyle = v, "--disablePathStyle")
|
||||
|
||||
@@ -6,6 +6,11 @@ namespace Velopack.CommandLine.Tests.Commands;
|
||||
public abstract class AzureCommandTests<T> : BaseCommandTests<T>
|
||||
where T : AzureBaseCommand, new()
|
||||
{
|
||||
protected override string GetRequiredDefaultOptions()
|
||||
{
|
||||
return "--account \"test-account\" --key \"test-key\" --container \"test-container\" ";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Command_WithRequiredEndpointOptions_ParsesValue()
|
||||
{
|
||||
@@ -23,20 +28,37 @@ public abstract class AzureCommandTests<T> : BaseCommandTests<T>
|
||||
}
|
||||
|
||||
public class AzureDownloadCommandTests : AzureCommandTests<AzureDownloadCommand>
|
||||
{ }
|
||||
{
|
||||
[Fact]
|
||||
public void Folder_WithPath_ParsesValue()
|
||||
{
|
||||
var command = new AzureDownloadCommand();
|
||||
|
||||
string cli = GetRequiredDefaultOptions() + " --prefix \"releases/v1\"";
|
||||
ParseResult parseResult = command.ParseAndApply(cli);
|
||||
|
||||
Assert.Equal("releases/v1", command.Prefix);
|
||||
}
|
||||
}
|
||||
|
||||
public class AzureUploadCommandTests : AzureCommandTests<AzureUploadCommand>
|
||||
{
|
||||
public override bool ShouldBeNonEmptyReleaseDir => true;
|
||||
|
||||
protected override string GetRequiredDefaultOptions()
|
||||
{
|
||||
return base.GetRequiredDefaultOptions() + "--releaseDir \"./releases\" ";
|
||||
}
|
||||
|
||||
//[Fact]
|
||||
//public void KeepMaxReleases_WithNumber_ParsesValue()
|
||||
//{
|
||||
// var command = new S3UploadCommand();
|
||||
[Fact]
|
||||
public void Folder_WithPath_ParsesValue()
|
||||
{
|
||||
var command = new AzureUploadCommand();
|
||||
|
||||
// string cli = GetRequiredDefaultOptions() + "--keepMaxReleases 42";
|
||||
// ParseResult parseResult = command.ParseAndApply(cli);
|
||||
string cli = GetRequiredDefaultOptions() + " --prefix \"releases/v1\"";
|
||||
ParseResult parseResult = command.ParseAndApply(cli);
|
||||
|
||||
Assert.Equal("releases/v1", command.Prefix);
|
||||
}
|
||||
|
||||
// Assert.Equal(42, command.KeepMaxReleases);
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class DeploymentTests
|
||||
};
|
||||
|
||||
var updateUrl = $"https://{AZ_ENDPOINT}/{AZ_CONTAINER}";
|
||||
await Deploy<AzureRepository, AzureDownloadOptions, AzureUploadOptions, BlobContainerClient>("AZTestApp", repo, options, releaseDir, updateUrl, logger);
|
||||
await Deploy<AzureRepository, AzureDownloadOptions, AzureUploadOptions, AzureBlobClient>("AZTestApp", repo, options, releaseDir, updateUrl, logger);
|
||||
}
|
||||
|
||||
static SemanticVersion GenerateSemverFromDateTime()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.ComponentModel;
|
||||
using System.IO.Compression;
|
||||
using NCode.ReparsePoints;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using Velopack.Logging;
|
||||
using Velopack.Util;
|
||||
using NCode.ReparsePoints;
|
||||
|
||||
namespace Velopack.Tests;
|
||||
|
||||
@@ -270,4 +270,356 @@ public class SymbolicLinkTests
|
||||
Assert.True(File.Exists(currentSym));
|
||||
Assert.Equal("A/", File.ReadAllText(currentSym));
|
||||
}
|
||||
|
||||
// ===== New comprehensive tests =====
|
||||
|
||||
[Fact]
|
||||
public void Create_SymlinkToNonExistentTarget_ShouldWork()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "NonExistent");
|
||||
var link = Path.Combine(tempFolder, "Link");
|
||||
|
||||
// Should be able to create symlink to non-existent target
|
||||
File.WriteAllText(target, "test");
|
||||
SymbolicLink.Create(link, target);
|
||||
Assert.True(SymbolicLink.Exists(link));
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(link));
|
||||
|
||||
// Clean up
|
||||
SymbolicLink.Delete(link);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_MultipleLevelsOfSymlinks()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var file = Path.Combine(tempFolder, "Original.txt");
|
||||
var link1 = Path.Combine(tempFolder, "Link1.txt");
|
||||
var link2 = Path.Combine(tempFolder, "Link2.txt");
|
||||
var link3 = Path.Combine(tempFolder, "Link3.txt");
|
||||
|
||||
File.WriteAllText(file, "Hello");
|
||||
|
||||
// Create chain: link3 -> link2 -> link1 -> file
|
||||
SymbolicLink.Create(link1, file);
|
||||
SymbolicLink.Create(link2, link1);
|
||||
SymbolicLink.Create(link3, link2);
|
||||
|
||||
// All should resolve to the same content
|
||||
Assert.Equal("Hello", File.ReadAllText(link1));
|
||||
Assert.Equal("Hello", File.ReadAllText(link2));
|
||||
Assert.Equal("Hello", File.ReadAllText(link3));
|
||||
|
||||
// Each should point to their immediate target
|
||||
Assert.Equal(file, SymbolicLink.GetTarget(link1));
|
||||
Assert.Equal(link1, SymbolicLink.GetTarget(link2));
|
||||
Assert.Equal(link2, SymbolicLink.GetTarget(link3));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetTarget_WithTrailingSlash_ShouldWork()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "Target");
|
||||
var link = Path.Combine(tempFolder, "Link");
|
||||
|
||||
Directory.CreateDirectory(target);
|
||||
SymbolicLink.Create(link, target);
|
||||
|
||||
// Should work with and without trailing slash
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(link));
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(link + Path.DirectorySeparatorChar));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_WithSpecialCharactersInPath()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "Target With Spaces & Special-Chars");
|
||||
var link = Path.Combine(tempFolder, "Link With Spaces & Special-Chars");
|
||||
|
||||
Directory.CreateDirectory(target);
|
||||
File.WriteAllText(Path.Combine(target, "file.txt"), "content");
|
||||
|
||||
SymbolicLink.Create(link, target);
|
||||
Assert.True(SymbolicLink.Exists(link));
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(link));
|
||||
Assert.Equal("content", File.ReadAllText(Path.Combine(link, "file.txt")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_AbsoluteVsRelativeComparison()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var subdir = Directory.CreateDirectory(Path.Combine(tempFolder, "subdir")).FullName;
|
||||
var target = Path.Combine(tempFolder, "target.txt");
|
||||
var linkAbs = Path.Combine(subdir, "link_abs.txt");
|
||||
var linkRel = Path.Combine(subdir, "link_rel.txt");
|
||||
|
||||
File.WriteAllText(target, "test");
|
||||
|
||||
// Create absolute and relative links
|
||||
SymbolicLink.Create(linkAbs, target, relative: false);
|
||||
SymbolicLink.Create(linkRel, target, relative: true);
|
||||
|
||||
// Both should work
|
||||
Assert.Equal("test", File.ReadAllText(linkAbs));
|
||||
Assert.Equal("test", File.ReadAllText(linkRel));
|
||||
|
||||
// Check targets
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(linkAbs));
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(linkRel));
|
||||
|
||||
// Relative target should be different when requested
|
||||
var relTarget = SymbolicLink.GetTarget(linkRel, relative: true);
|
||||
Assert.Contains("..", relTarget);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileSymlink_AllImplementationsAgree()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "target.txt");
|
||||
var link = Path.Combine(tempFolder, "link.txt");
|
||||
|
||||
File.WriteAllText(target, "test content");
|
||||
|
||||
// Create with our implementation
|
||||
SymbolicLink.Create(link, target);
|
||||
|
||||
// Verify all implementations agree
|
||||
var ourTarget = SymbolicLink.GetTarget(link);
|
||||
Assert.Equal(target, ourTarget);
|
||||
|
||||
// Compare with NCode.ReparsePoints (Windows only)
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var provider = new ReparsePointProvider();
|
||||
var linkInfo = provider.GetLink(link);
|
||||
Assert.Equal(LinkType.Symbolic, linkInfo.Type);
|
||||
Assert.Equal(target, linkInfo.Target);
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
var fileInfo = new FileInfo(link);
|
||||
Assert.NotNull(fileInfo.LinkTarget);
|
||||
Assert.Equal(target, Path.GetFullPath(fileInfo.LinkTarget));
|
||||
|
||||
// Test interoperability: create with framework, read with ours
|
||||
var link2 = Path.Combine(tempFolder, "link2.txt");
|
||||
File.CreateSymbolicLink(link2, target);
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(link2));
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DirectorySymlink_AllImplementationsAgree()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "targetDir");
|
||||
var link = Path.Combine(tempFolder, "linkDir");
|
||||
|
||||
Directory.CreateDirectory(target);
|
||||
File.WriteAllText(Path.Combine(target, "file.txt"), "content");
|
||||
|
||||
// Create with our implementation
|
||||
SymbolicLink.Create(link, target);
|
||||
|
||||
// Verify all implementations agree
|
||||
var ourTarget = SymbolicLink.GetTarget(link);
|
||||
Assert.Equal(target, ourTarget);
|
||||
|
||||
// Compare with NCode.ReparsePoints (Windows only)
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var provider = new ReparsePointProvider();
|
||||
var linkInfo = provider.GetLink(link);
|
||||
// Directory symlinks on Windows are actually junctions
|
||||
Assert.True(linkInfo.Type == LinkType.Junction || linkInfo.Type == LinkType.Symbolic);
|
||||
Assert.Equal(target, linkInfo.Target);
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
var dirInfo = new DirectoryInfo(link);
|
||||
Assert.NotNull(dirInfo.LinkTarget);
|
||||
Assert.Equal(target, Path.GetFullPath(dirInfo.LinkTarget));
|
||||
|
||||
// Test interoperability: create with framework, read with ours
|
||||
var link2 = Path.Combine(tempFolder, "linkDir2");
|
||||
Directory.CreateSymbolicLink(link2, target);
|
||||
Assert.Equal(target, SymbolicLink.GetTarget(link2));
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RelativeSymlink_AllImplementationsAgree()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var subdir = Directory.CreateDirectory(Path.Combine(tempFolder, "subdir")).FullName;
|
||||
var target = Path.Combine(tempFolder, "target.txt");
|
||||
var link = Path.Combine(subdir, "link.txt");
|
||||
|
||||
File.WriteAllText(target, "test");
|
||||
|
||||
// Create relative symlink with our implementation
|
||||
SymbolicLink.Create(link, target, relative: true);
|
||||
|
||||
// Verify our implementation handles relative vs absolute correctly
|
||||
var ourAbsoluteTarget = SymbolicLink.GetTarget(link);
|
||||
var ourRelativeTarget = SymbolicLink.GetTarget(link, relative: true);
|
||||
Assert.Equal(target, ourAbsoluteTarget);
|
||||
Assert.Contains("..", ourRelativeTarget);
|
||||
|
||||
// Compare with NCode.ReparsePoints (Windows only)
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var provider = new ReparsePointProvider();
|
||||
var linkInfo = provider.GetLink(link);
|
||||
Assert.Equal(LinkType.Symbolic, linkInfo.Type);
|
||||
// NCode returns the raw target path as stored in the symlink
|
||||
// For relative symlinks, this will be the relative path, not absolute
|
||||
Assert.Equal(ourRelativeTarget, linkInfo.Target);
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
var fileInfo = new FileInfo(link);
|
||||
Assert.NotNull(fileInfo.LinkTarget);
|
||||
// Framework returns the relative path for relative symlinks
|
||||
Assert.Contains("..", fileInfo.LinkTarget);
|
||||
Assert.Equal(fileInfo.LinkTarget, ourRelativeTarget);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MultipleLevelsOfSymlinks_AllImplementationsAgree()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var file = Path.Combine(tempFolder, "original.txt");
|
||||
var link1 = Path.Combine(tempFolder, "link1.txt");
|
||||
var link2 = Path.Combine(tempFolder, "link2.txt");
|
||||
|
||||
File.WriteAllText(file, "content");
|
||||
|
||||
// Create chain: link2 -> link1 -> file
|
||||
SymbolicLink.Create(link1, file);
|
||||
SymbolicLink.Create(link2, link1);
|
||||
|
||||
// Verify our implementation
|
||||
Assert.Equal(file, SymbolicLink.GetTarget(link1));
|
||||
Assert.Equal(link1, SymbolicLink.GetTarget(link2));
|
||||
|
||||
// Verify content access works through the chain
|
||||
Assert.Equal("content", File.ReadAllText(link1));
|
||||
Assert.Equal("content", File.ReadAllText(link2));
|
||||
|
||||
// Compare with NCode.ReparsePoints (Windows only)
|
||||
if (VelopackRuntimeInfo.IsWindows) {
|
||||
var provider = new ReparsePointProvider();
|
||||
var link1Info = provider.GetLink(link1);
|
||||
var link2Info = provider.GetLink(link2);
|
||||
Assert.Equal(LinkType.Symbolic, link1Info.Type);
|
||||
Assert.Equal(LinkType.Symbolic, link2Info.Type);
|
||||
Assert.Equal(file, link1Info.Target);
|
||||
Assert.Equal(link1, link2Info.Target);
|
||||
}
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
var fileInfo1 = new FileInfo(link1);
|
||||
var fileInfo2 = new FileInfo(link2);
|
||||
Assert.NotNull(fileInfo1.LinkTarget);
|
||||
Assert.NotNull(fileInfo2.LinkTarget);
|
||||
Assert.Equal(file, Path.GetFullPath(fileInfo1.LinkTarget));
|
||||
Assert.Equal(link1, Path.GetFullPath(fileInfo2.LinkTarget));
|
||||
|
||||
// Test ResolveLinkTarget for final resolution
|
||||
var finalTarget = fileInfo2.ResolveLinkTarget(true);
|
||||
Assert.Equal(file, finalTarget?.FullName);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_OnlyDeletesLinkNotTarget()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "target.txt");
|
||||
var link = Path.Combine(tempFolder, "link.txt");
|
||||
|
||||
File.WriteAllText(target, "important data");
|
||||
SymbolicLink.Create(link, target);
|
||||
|
||||
// Delete the link
|
||||
SymbolicLink.Delete(link);
|
||||
|
||||
// Link should be gone, but target should remain
|
||||
Assert.False(File.Exists(link));
|
||||
Assert.False(SymbolicLink.Exists(link));
|
||||
Assert.True(File.Exists(target));
|
||||
Assert.Equal("important data", File.ReadAllText(target));
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void Exists_ReturnsFalseForHardLink()
|
||||
{
|
||||
Skip.IfNot(VelopackRuntimeInfo.IsWindows);
|
||||
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target = Path.Combine(tempFolder, "target.txt");
|
||||
var hardLink = Path.Combine(tempFolder, "hardlink.txt");
|
||||
|
||||
File.WriteAllText(target, "test");
|
||||
|
||||
// Create hard link using P/Invoke
|
||||
if (!CreateHardLink(hardLink, target, IntPtr.Zero)) {
|
||||
// Skip test if hard link creation fails (may need elevation)
|
||||
return;
|
||||
}
|
||||
|
||||
// Hard link should exist as a file but not as a symbolic link
|
||||
Assert.True(File.Exists(hardLink));
|
||||
Assert.False(SymbolicLink.Exists(hardLink));
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes);
|
||||
|
||||
[Fact]
|
||||
public void GetTarget_ErrorMessages_AreDescriptive()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var regularFile = Path.Combine(tempFolder, "regular.txt");
|
||||
var regularDir = Path.Combine(tempFolder, "regularDir");
|
||||
var nonExistent = Path.Combine(tempFolder, "nonExistent");
|
||||
|
||||
File.WriteAllText(regularFile, "test");
|
||||
Directory.CreateDirectory(regularDir);
|
||||
|
||||
// Test various error conditions
|
||||
var ex1 = Assert.Throws<IOException>(() => SymbolicLink.GetTarget(regularFile));
|
||||
Assert.Contains("junction", ex1.Message.ToLower());
|
||||
|
||||
var ex2 = Assert.Throws<IOException>(() => SymbolicLink.GetTarget(regularDir));
|
||||
Assert.Contains("junction", ex2.Message.ToLower());
|
||||
|
||||
var ex3 = Assert.Throws<IOException>(() => SymbolicLink.GetTarget(nonExistent));
|
||||
Assert.Contains("junction", ex2.Message.ToLower());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_OverwriteExistingSymlink()
|
||||
{
|
||||
using var _1 = TempUtil.GetTempDirectory(out var tempFolder);
|
||||
var target1 = Path.Combine(tempFolder, "target1.txt");
|
||||
var target2 = Path.Combine(tempFolder, "target2.txt");
|
||||
var link = Path.Combine(tempFolder, "link.txt");
|
||||
|
||||
File.WriteAllText(target1, "content1");
|
||||
File.WriteAllText(target2, "content2");
|
||||
|
||||
// Create initial symlink
|
||||
SymbolicLink.Create(link, target1);
|
||||
Assert.Equal("content1", File.ReadAllText(link));
|
||||
|
||||
// Overwrite with new target
|
||||
SymbolicLink.Create(link, target2, overwrite: true);
|
||||
Assert.Equal("content2", File.ReadAllText(link));
|
||||
Assert.Equal(target2, SymbolicLink.GetTarget(link));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user