mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-11 10:43:31 +02:00
Compare commits
21 Commits
tauri-code
...
feat/cli/k
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fa69531ea | ||
|
|
510b62261c | ||
|
|
b0f27814b9 | ||
|
|
cc3d8e7731 | ||
|
|
8ce51cec3b | ||
|
|
0bff8c325d | ||
|
|
a9b2c0625c | ||
|
|
7aa30dec85 | ||
|
|
4926648751 | ||
|
|
06890c70c6 | ||
|
|
1ca69bcf2f | ||
|
|
6bdba1f330 | ||
|
|
b546b42db7 | ||
|
|
67d7877f27 | ||
|
|
89911296e4 | ||
|
|
8f8729d918 | ||
|
|
446fc99bbe | ||
|
|
6e48837860 | ||
|
|
883e52153e | ||
|
|
32c61f8f23 | ||
|
|
7b8c23aa37 |
5
.changes/add-section-priority-changelog.md
Normal file
5
.changes/add-section-priority-changelog.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-bundler": patch:feat
|
||||
---
|
||||
|
||||
Add `priority`, `section` and `changelog` options in Debian config.
|
||||
5
.changes/bundler-socks-proxy.md
Normal file
5
.changes/bundler-socks-proxy.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-bundler": patch:enhance
|
||||
---
|
||||
|
||||
Support using socks proxy from environment when downloading files.
|
||||
6
.changes/cli-dev-profile.md
Normal file
6
.changes/cli-dev-profile.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'tauri-cli': 'patch:bug'
|
||||
'@tauri-apps/cli': 'patch:bug'
|
||||
---
|
||||
|
||||
Fix `fail to rename app` when using `--profile dev`.
|
||||
6
.changes/cli-devserver-queryparam.md
Normal file
6
.changes/cli-devserver-queryparam.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
Fix the built-in dev server failing to serve files when URL had queries `?` and other url components.
|
||||
5
.changes/cli-js-kill-dev-fn.md
Normal file
5
.changes/cli-js-kill-dev-fn.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@tauri-apps/cli': 'minor:feat'
|
||||
---
|
||||
|
||||
Add `killDevApp` API to kill the dev app process manually.
|
||||
5
.changes/cli-rs-kill-dev-fn.md
Normal file
5
.changes/cli-rs-kill-dev-fn.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri-cli': 'minor:feat'
|
||||
---
|
||||
|
||||
Add `tauri_cli::kill_dev_app` API to kill the dev app process manually.
|
||||
6
.changes/cli-watch-ws-members.md
Normal file
6
.changes/cli-watch-ws-members.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
The cli now also watches cargo workspace members if the tauri folder is the workspace root.
|
||||
5
.changes/export-url.md
Normal file
5
.changes/export-url.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri': 'patch:feat'
|
||||
---
|
||||
|
||||
Re-export `Url` type.
|
||||
5
.changes/fix-command-spawn-deadlock.md
Normal file
5
.changes/fix-command-spawn-deadlock.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": patch:bug
|
||||
---
|
||||
|
||||
Fixes a deadlock when reading a stdout or stderr line returns an error.
|
||||
5
.changes/fix-formbody-order.md
Normal file
5
.changes/fix-formbody-order.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri': 'patch:bug'
|
||||
---
|
||||
|
||||
Preserve the order of JS object/map keys in IPC calls. This also fixes issues with the JS `http` module when calling to servers that required a specific order of `FormBody` contents.
|
||||
6
.changes/fix-non-standard-permission-bug.md
Normal file
6
.changes/fix-non-standard-permission-bug.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'tauri-bundler': 'patch:bug'
|
||||
---
|
||||
|
||||
|
||||
Fix the `non-standard-file-perm` and `non-standard-dir-perm` issue in Debian packages
|
||||
5
.changes/libflate-to-flate2.md
Normal file
5
.changes/libflate-to-flate2.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri-bundler": patch:deps
|
||||
---
|
||||
|
||||
Replace `libflate` with `flate2` , this will help to provide additional functionalities and features.
|
||||
6
.changes/mac-bundler-nested-code-sign.md
Normal file
6
.changes/mac-bundler-nested-code-sign.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:feat
|
||||
"tauri-bundler": patch:feat
|
||||
---
|
||||
|
||||
On macOS, support for signing nested .dylib, .app, .xpc and .framework under predefined directories inside the bundled frameworks ("MacOS", "Frameworks", "Plugins", "Helpers", "XPCServices" and "Libraries").
|
||||
5
.changes/runtime-wry-wayland.md
Normal file
5
.changes/runtime-wry-wayland.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
tauri-runtime-wry: patch:bug
|
||||
---
|
||||
|
||||
Add missing `arboard` feature flag to prevent panics in wayland session.
|
||||
5
.changes/tauri-bundler-nsis-args.md
Normal file
5
.changes/tauri-bundler-nsis-args.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri-bundler': 'minor:feat'
|
||||
---
|
||||
|
||||
On Windows, NSIS installer now supports `/ARGS` flag to pass arguments to be used when launching the app after installation, only works if `/R` is used.
|
||||
5
.changes/tauri-data-drag-region-macos-maximize.md
Normal file
5
.changes/tauri-data-drag-region-macos-maximize.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri': 'patch:bug'
|
||||
---
|
||||
|
||||
On macOS, allow cancelling maximization when doubleclick happens on `data-tauri-drag-region` by simply keeping the left moust button pressed and then moving the mouse away of the starting position of the click, which is consistent with the native behavior of macOS.
|
||||
5
.changes/tauri-updater-retain-args.md
Normal file
5
.changes/tauri-updater-retain-args.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri': 'minor:enhance'
|
||||
---
|
||||
|
||||
On Windows, retain command line args when relaunching the app after an update. Supports NSIS and WiX (without elevated update task).
|
||||
101
.github/workflows/covector-version-or-publish-v1.yml
vendored
101
.github/workflows/covector-version-or-publish-v1.yml
vendored
@@ -10,8 +10,101 @@ on:
|
||||
- 1.x
|
||||
|
||||
jobs:
|
||||
msrv-list:
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- {
|
||||
target: x86_64-pc-windows-msvc,
|
||||
os: windows-latest,
|
||||
toolchain: '1.61.0'
|
||||
}
|
||||
- {
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
os: ubuntu-latest,
|
||||
toolchain: '1.60.0'
|
||||
}
|
||||
- {
|
||||
target: x86_64-apple-darwin,
|
||||
os: macos-latest,
|
||||
toolchain: '1.60.0'
|
||||
}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: install rust ${{ matrix.platform.toolchain }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.platform.toolchain }}
|
||||
target: ${{ matrix.platform.target }}
|
||||
override: true
|
||||
default: true
|
||||
|
||||
- name: install Linux dependencies
|
||||
if: contains(matrix.platform.target, 'unknown-linux')
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: delete lockfile
|
||||
run: rm Cargo.lock
|
||||
|
||||
- name: Downgrade crates with MSRV conflict
|
||||
# The --precise flag can only be used once per invocation.
|
||||
run: |
|
||||
cargo update -p system-deps:6.2.0 --precise 6.1.1
|
||||
cargo update -p toml:0.7.8 --precise 0.7.3
|
||||
cargo update -p toml_edit:0.19.15 --precise 0.19.8
|
||||
cargo update -p embed-resource --precise 2.3.0
|
||||
cargo update -p toml_datetime --precise 0.6.1
|
||||
cargo update -p serde_spanned --precise 0.6.1
|
||||
cargo update -p winnow --precise 0.4.1
|
||||
cargo update -p plist --precise 1.5.1
|
||||
cargo update -p time --precise 0.3.15
|
||||
cargo update -p ignore --precise 0.4.18
|
||||
cargo update -p raw-window-handle --precise 0.5.0
|
||||
cargo update -p cargo_toml:0.15.3 --precise 0.15.2
|
||||
cargo update -p zbus --precise 3.13.0
|
||||
cargo update -p zbus_names --precise 2.5.0
|
||||
cargo update -p colored --precise 2.0.2
|
||||
cargo update -p tempfile --precise 3.6.0
|
||||
cargo update -p serde_with:3.4.0 --precise 3.0.0
|
||||
cargo update -p tokio --precise 1.29.0
|
||||
cargo update -p flate2 --precise 1.0.26
|
||||
cargo update -p h2 --precise 0.3.20
|
||||
cargo update -p reqwest --precise 0.11.18
|
||||
cargo update -p bstr --precise 1.6.2
|
||||
cargo update -p cfg-expr:0.15.6 --precise 0.15.4
|
||||
cargo update -p memchr --precise 2.6.2
|
||||
cargo update -p async-executor --precise 1.5.1
|
||||
cargo update -p proptest --precise 1.2.0
|
||||
cargo update -p regex --precise 1.9.6
|
||||
cargo update -p bstr --precise 1.6.2
|
||||
cargo update -p backtrace --precise 0.3.68
|
||||
cargo update -p blocking --precise 1.4.1
|
||||
cargo update -p ignore --precise 0.4.18
|
||||
cargo update -p regex --precise 1.9.6
|
||||
cargo update -p globset --precise 0.4.13
|
||||
cargo update -p crossbeam-channel --precise 0.5.8
|
||||
cargo update -p crossbeam-utils --precise 0.8.16
|
||||
cargo update -p image --precise 0.24.4
|
||||
cargo update -p async-process --precise 1.7.0
|
||||
cargo update -p is-terminal --precise 0.4.7
|
||||
cargo update -p tar --precise 0.4.39
|
||||
cargo update -p serde_json --precise 1.0.97
|
||||
cargo update -p arboard --precise 3.2.1
|
||||
cargo update -p petgraph --precise 0.6.3
|
||||
|
||||
- name: test build
|
||||
run: cargo check --target ${{ matrix.platform.target }} --features tracing,compression,wry,linux-protocol-headers,isolation,custom-protocol,api-all,cli,updater,system-tray,windows7-compat,http-multipart,test,
|
||||
|
||||
run-integration-tests:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
needs: msrv-list
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -19,7 +112,7 @@ jobs:
|
||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: install stable
|
||||
@@ -66,7 +159,7 @@ jobs:
|
||||
- run-integration-tests
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -121,8 +214,6 @@ jobs:
|
||||
contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli')
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
|
||||
repository: tauri-apps/tauri
|
||||
event-type: publish-js-cli
|
||||
client-payload: >-
|
||||
{"releaseId": "${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }}" }
|
||||
@@ -133,6 +224,4 @@ jobs:
|
||||
contains(steps.covector.outputs.packagesPublished, 'tauri-cli')
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
|
||||
repository: tauri-apps/tauri
|
||||
event-type: publish-clirs
|
||||
|
||||
@@ -121,8 +121,6 @@ jobs:
|
||||
contains(steps.covector.outputs.packagesPublished, '@tauri-apps/cli')
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
|
||||
repository: tauri-apps/tauri
|
||||
event-type: publish-js-cli
|
||||
client-payload: >-
|
||||
{"releaseId": "${{ steps.covector.outputs['-tauri-apps-cli-releaseId'] }}" }
|
||||
@@ -133,6 +131,4 @@ jobs:
|
||||
contains(steps.covector.outputs.packagesPublished, 'tauri-cli')
|
||||
uses: peter-evans/repository-dispatch@v1
|
||||
with:
|
||||
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
|
||||
repository: tauri-apps/tauri
|
||||
event-type: publish-clirs
|
||||
|
||||
42
.github/workflows/test-core.yml
vendored
42
.github/workflows/test-core.yml
vendored
@@ -82,47 +82,5 @@ jobs:
|
||||
workspaces: core -> ../target
|
||||
save-if: ${{ matrix.features.key == 'all' }}
|
||||
|
||||
- name: Downgrade crates with MSRV conflict
|
||||
# The --precise flag can only be used once per invocation.
|
||||
run: |
|
||||
cargo update -p system-deps:6.2.0 --precise 6.1.1
|
||||
cargo update -p toml:0.7.8 --precise 0.7.3
|
||||
cargo update -p toml_edit:0.19.15 --precise 0.19.8
|
||||
cargo update -p embed-resource --precise 2.3.0
|
||||
cargo update -p toml_datetime --precise 0.6.1
|
||||
cargo update -p serde_spanned --precise 0.6.1
|
||||
cargo update -p winnow --precise 0.4.1
|
||||
cargo update -p plist --precise 1.5.1
|
||||
cargo update -p time --precise 0.3.15
|
||||
cargo update -p ignore --precise 0.4.18
|
||||
cargo update -p raw-window-handle --precise 0.5.0
|
||||
cargo update -p cargo_toml:0.15.3 --precise 0.15.2
|
||||
cargo update -p zbus --precise 3.13.0
|
||||
cargo update -p zbus_names --precise 2.5.0
|
||||
cargo update -p colored --precise 2.0.2
|
||||
cargo update -p tempfile --precise 3.6.0
|
||||
cargo update -p serde_with:3.4.0 --precise 3.0.0
|
||||
cargo update -p tokio --precise 1.29.0
|
||||
cargo update -p flate2 --precise 1.0.26
|
||||
cargo update -p h2 --precise 0.3.20
|
||||
cargo update -p reqwest --precise 0.11.18
|
||||
cargo update -p cfg-expr:0.15.5 --precise 0.15.4
|
||||
cargo update -p memchr --precise 2.6.2
|
||||
cargo update -p async-executor --precise 1.5.1
|
||||
cargo update -p proptest --precise 1.2.0
|
||||
cargo update -p regex --precise 1.9.6
|
||||
cargo update -p bstr --precise 1.6.2
|
||||
cargo update -p backtrace --precise 0.3.68
|
||||
cargo update -p blocking --precise 1.4.1
|
||||
cargo update -p ignore --precise 0.4.18
|
||||
cargo update -p regex --precise 1.9.6
|
||||
cargo update -p globset --precise 0.4.13
|
||||
cargo update -p crossbeam-channel --precise 0.5.8
|
||||
cargo update -p crossbeam-utils --precise 0.8.16
|
||||
cargo update -p image --precise 0.24.4
|
||||
cargo update -p async-process --precise 1.7.0
|
||||
cargo update -p is-terminal --precise 0.4.7
|
||||
cargo update -p tar --precise 0.4.39
|
||||
|
||||
- name: test
|
||||
run: cargo test --target ${{ matrix.platform.target }} ${{ matrix.features.args }}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -73,7 +73,7 @@ TODO.md
|
||||
target
|
||||
|
||||
# lock for libs
|
||||
/Cargo.lock
|
||||
#/Cargo.lock Committed to prevent msrv checks from failing
|
||||
/tooling/bench/tests/Cargo.lock
|
||||
/yarn.lock
|
||||
|
||||
|
||||
5727
Cargo.lock
generated
Normal file
5727
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1320,6 +1320,27 @@
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"section": {
|
||||
"description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"priority": {
|
||||
"description": "Change the priority of the Debian Package. By default, it is set to `optional`. Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"changelog": {
|
||||
"description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -48,6 +48,6 @@ macos-private-api = [
|
||||
]
|
||||
objc-exception = [ "wry/objc-exception" ]
|
||||
global-shortcut = [ "tauri-runtime/global-shortcut" ]
|
||||
clipboard = [ "tauri-runtime/clipboard", "arboard" ]
|
||||
clipboard = [ "tauri-runtime/clipboard", "arboard/wayland-data-control" ]
|
||||
linux-headers = [ "wry/linux-headers", "webkit2gtk/v2_36" ]
|
||||
tracing = [ "dep:tracing", "wry/tracing" ]
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pub use tauri_runtime::{
|
||||
menu::{
|
||||
Menu, MenuEntry, MenuItem, MenuUpdate, Submenu, SystemTrayMenu, SystemTrayMenuEntry,
|
||||
SystemTrayMenuItem, TrayHandle,
|
||||
},
|
||||
menu::{MenuUpdate, SystemTrayMenu, SystemTrayMenuEntry, SystemTrayMenuItem, TrayHandle},
|
||||
Icon, SystemTrayEvent,
|
||||
};
|
||||
use wry::application::event_loop::EventLoopWindowTarget;
|
||||
|
||||
@@ -280,6 +280,14 @@ pub struct DebConfig {
|
||||
///
|
||||
/// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
|
||||
pub desktop_template: Option<PathBuf>,
|
||||
/// Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
|
||||
pub section: Option<String>,
|
||||
/// Change the priority of the Debian Package. By default, it is set to `optional`.
|
||||
/// Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`
|
||||
pub priority: Option<String>,
|
||||
/// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
|
||||
/// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes
|
||||
pub changelog: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn de_minimum_system_version<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||
@@ -2578,6 +2586,9 @@ impl WindowsUpdateInstallMode {
|
||||
}
|
||||
|
||||
/// Returns the associated nsis arguments.
|
||||
///
|
||||
/// [WindowsUpdateInstallMode::Passive] will return `["/P", "/R"]`
|
||||
/// [WindowsUpdateInstallMode::Quiet] will return `["/S", "/R"]`
|
||||
pub fn nsis_args(&self) -> &'static [&'static str] {
|
||||
match self {
|
||||
Self::Passive => &["/P", "/R"],
|
||||
|
||||
@@ -49,7 +49,7 @@ targets = [
|
||||
normal = [ "reqwest" ]
|
||||
|
||||
[dependencies]
|
||||
serde_json = { version = "1.0", features = [ "raw_value" ] }
|
||||
serde_json = { version = "1.0", features = [ "raw_value", "preserve_order" ] }
|
||||
serde = { version = "1.0", features = [ "derive" ] }
|
||||
tokio = { version = "1", features = [ "rt", "rt-multi-thread", "sync", "fs", "io-util" ] }
|
||||
futures-util = "0.3"
|
||||
@@ -95,6 +95,7 @@ ico = { version = "0.2.0", optional = true }
|
||||
encoding_rs = "0.8.31"
|
||||
sys-locale = { version = "0.2.3", optional = true }
|
||||
tracing = { version = "0.1", optional = true }
|
||||
indexmap = { version = "1", features = [ "std", "serde" ], optional = true }
|
||||
|
||||
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
|
||||
rfd = { version = "0.10", optional = true, features = [ "gtk3", "common-controls-v6" ] }
|
||||
@@ -111,6 +112,7 @@ cocoa = "0.24"
|
||||
objc = "0.2"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
dunce = "1"
|
||||
webview2-com = "0.19.1"
|
||||
win7-notifications = { version = "0.4", optional = true }
|
||||
|
||||
@@ -156,7 +158,7 @@ updater = [
|
||||
"dialog-ask",
|
||||
"fs-extract-api"
|
||||
]
|
||||
http-api = [ "reqwest", "bytes" ]
|
||||
http-api = [ "reqwest", "bytes", "indexmap" ]
|
||||
http-multipart = [ "reqwest/multipart" ]
|
||||
os-api = [ "sys-locale" ]
|
||||
shell-open-api = [ "open", "regex", "tauri-macros/shell-scope" ]
|
||||
|
||||
@@ -142,16 +142,40 @@
|
||||
)
|
||||
}
|
||||
|
||||
// drag region
|
||||
//-----------------------//
|
||||
// data-tauri-drag-region
|
||||
//
|
||||
// drag on mousedown and maximize on double click on Windows and Linux
|
||||
// while macOS macos maximization should be on mouseup and if the mouse
|
||||
// moves after the double click, it should be cancelled (see https://github.com/tauri-apps/tauri/issues/8306)
|
||||
//-----------------------//
|
||||
const TAURI_DRAG_REGION_ATTR = 'data-tauri-drag-region';
|
||||
let x = 0, y = 0;
|
||||
document.addEventListener('mousedown', (e) => {
|
||||
if (e.target.hasAttribute('data-tauri-drag-region') && e.button === 0) {
|
||||
if (
|
||||
// element has the magic data attribute
|
||||
e.target.hasAttribute(TAURI_DRAG_REGION_ATTR) &&
|
||||
// and was left mouse button
|
||||
e.button === 0 &&
|
||||
// and was normal click to drag or double click to maximize
|
||||
(e.detail === 1 || e.detail === 2)
|
||||
) {
|
||||
|
||||
// macOS maximization happens on `mouseup`,
|
||||
// so we save needed state and early return
|
||||
if (osName === 'macos' && e.detail == 2) {
|
||||
x = e.clientX
|
||||
y = e.clientY
|
||||
return
|
||||
}
|
||||
|
||||
// prevents text cursor
|
||||
e.preventDefault()
|
||||
|
||||
// fix #2549: double click on drag region edge causes content to maximize without window sizing change
|
||||
// https://github.com/tauri-apps/tauri/issues/2549#issuecomment-1250036908
|
||||
e.stopImmediatePropagation()
|
||||
|
||||
// start dragging if the element has a `tauri-drag-region` data attribute and maximize on double-clicking it
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Window',
|
||||
message: {
|
||||
@@ -165,6 +189,34 @@
|
||||
})
|
||||
}
|
||||
})
|
||||
// on macOS we maximze on mouseup instead, to match the system behavior where maximization can be canceled
|
||||
// if the mouse moves outside the data-tauri-drag-region
|
||||
if (osName === "macos") {
|
||||
document.addEventListener('mouseup', (e) => {
|
||||
if (
|
||||
// element has the magic data attribute
|
||||
e.target.hasAttribute(TAURI_DRAG_REGION_ATTR) &&
|
||||
// and was left mouse button
|
||||
e.button === 0 &&
|
||||
// and was double click
|
||||
e.detail === 2 &&
|
||||
// and the cursor hasn't moved from initial mousedown
|
||||
e.clientX === x && e.clientY === y
|
||||
) {
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Window',
|
||||
message: {
|
||||
cmd: 'manage',
|
||||
data: {
|
||||
cmd: {
|
||||
type: '__toggleMaximize'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let permissionSettable = false
|
||||
let permissionValue = 'default'
|
||||
|
||||
@@ -250,11 +250,16 @@ pub enum FormPart {
|
||||
|
||||
/// Form body definition.
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct FormBody(pub(crate) HashMap<String, FormPart>);
|
||||
pub struct FormBody(pub(crate) indexmap::IndexMap<String, FormPart>);
|
||||
|
||||
impl FormBody {
|
||||
/// Creates a new form body.
|
||||
pub fn new(data: HashMap<String, FormPart>) -> Self {
|
||||
Self(indexmap::IndexMap::from_iter(data))
|
||||
}
|
||||
|
||||
/// Creates a new form body with pre-ordered keys. Useful if the api requires a specific order.
|
||||
pub fn new_ordered(data: indexmap::IndexMap<String, FormPart>) -> Self {
|
||||
Self(data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,6 +420,7 @@ fn spawn_pipe_reader<F: Fn(String) -> CommandEvent + Send + Copy + 'static>(
|
||||
Err(e) => {
|
||||
let tx_ = tx.clone();
|
||||
let _ = block_on_task(async move { tx_.send(CommandEvent::Error(e.to_string())).await });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,6 +225,57 @@ impl Listeners {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unlisten_js(listeners_object_name: String, event_name: String, event_id: u32) -> String {
|
||||
format!(
|
||||
"
|
||||
(function () {{
|
||||
const listeners = (window['{listeners_object_name}'] || {{}})['{event_name}']
|
||||
if (listeners) {{
|
||||
const index = window['{listeners_object_name}']['{event_name}'].findIndex(e => e.id === {event_id})
|
||||
if (index > -1) {{
|
||||
window['{listeners_object_name}']['{event_name}'].splice(index, 1)
|
||||
}}
|
||||
}}
|
||||
}})()
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
pub fn listen_js(
|
||||
listeners_object_name: String,
|
||||
event: String,
|
||||
event_id: u32,
|
||||
window_label: Option<String>,
|
||||
handler: String,
|
||||
) -> String {
|
||||
format!(
|
||||
"
|
||||
(function () {{
|
||||
if (window['{listeners}'] === void 0) {{
|
||||
Object.defineProperty(window, '{listeners}', {{ value: Object.create(null) }});
|
||||
}}
|
||||
if (window['{listeners}'][{event}] === void 0) {{
|
||||
Object.defineProperty(window['{listeners}'], {event}, {{ value: [] }});
|
||||
}}
|
||||
const eventListeners = window['{listeners}'][{event}]
|
||||
const listener = {{
|
||||
id: {event_id},
|
||||
windowLabel: {window_label},
|
||||
handler: {handler}
|
||||
}};
|
||||
eventListeners.push(listener);
|
||||
}})()
|
||||
",
|
||||
listeners = listeners_object_name,
|
||||
window_label = if let Some(l) = window_label {
|
||||
crate::runtime::window::assert_label_is_valid(&l);
|
||||
format!("'{l}'")
|
||||
} else {
|
||||
"null".to_owned()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -298,54 +349,3 @@ mod test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unlisten_js(listeners_object_name: String, event_name: String, event_id: u32) -> String {
|
||||
format!(
|
||||
"
|
||||
(function () {{
|
||||
const listeners = (window['{listeners_object_name}'] || {{}})['{event_name}']
|
||||
if (listeners) {{
|
||||
const index = window['{listeners_object_name}']['{event_name}'].findIndex(e => e.id === {event_id})
|
||||
if (index > -1) {{
|
||||
window['{listeners_object_name}']['{event_name}'].splice(index, 1)
|
||||
}}
|
||||
}}
|
||||
}})()
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
pub fn listen_js(
|
||||
listeners_object_name: String,
|
||||
event: String,
|
||||
event_id: u32,
|
||||
window_label: Option<String>,
|
||||
handler: String,
|
||||
) -> String {
|
||||
format!(
|
||||
"
|
||||
(function () {{
|
||||
if (window['{listeners}'] === void 0) {{
|
||||
Object.defineProperty(window, '{listeners}', {{ value: Object.create(null) }});
|
||||
}}
|
||||
if (window['{listeners}'][{event}] === void 0) {{
|
||||
Object.defineProperty(window['{listeners}'], {event}, {{ value: [] }});
|
||||
}}
|
||||
const eventListeners = window['{listeners}'][{event}]
|
||||
const listener = {{
|
||||
id: {event_id},
|
||||
windowLabel: {window_label},
|
||||
handler: {handler}
|
||||
}};
|
||||
eventListeners.push(listener);
|
||||
}})()
|
||||
",
|
||||
listeners = listeners_object_name,
|
||||
window_label = if let Some(l) = window_label {
|
||||
crate::runtime::window::assert_label_is_valid(&l);
|
||||
format!("'{l}'")
|
||||
} else {
|
||||
"null".to_owned()
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -176,6 +176,8 @@ pub use error::Error;
|
||||
pub use regex;
|
||||
pub use tauri_macros::{command, generate_handler};
|
||||
|
||||
pub use url::Url;
|
||||
|
||||
pub mod api;
|
||||
pub(crate) mod app;
|
||||
pub mod async_runtime;
|
||||
|
||||
@@ -706,6 +706,7 @@ impl<R: Runtime> Update<R> {
|
||||
&self.extract_path,
|
||||
self.with_elevated_task,
|
||||
&self.app.config(),
|
||||
&self.app.env(),
|
||||
)?;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
copy_files_and_run(archive_buffer, &self.extract_path)?;
|
||||
@@ -805,6 +806,7 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
_extract_path: &Path,
|
||||
with_elevated_task: bool,
|
||||
config: &crate::Config,
|
||||
env: &crate::Env,
|
||||
) -> Result {
|
||||
// FIXME: We need to create a memory buffer with the MSI and then run it.
|
||||
// (instead of extracting the MSI to a temp path)
|
||||
@@ -830,6 +832,8 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
|p| format!("{p}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"),
|
||||
);
|
||||
|
||||
let current_exe_args = env.args.clone();
|
||||
|
||||
for path in paths {
|
||||
let found_path = path?.path();
|
||||
// we support 2 type of files exe & msi for now
|
||||
@@ -842,29 +846,39 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
installer_path.push("\"");
|
||||
|
||||
let installer_args = [
|
||||
config.tauri.updater.windows.install_mode.nsis_args(),
|
||||
config
|
||||
.tauri
|
||||
.updater
|
||||
.windows
|
||||
.install_mode
|
||||
.nsis_args()
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect(),
|
||||
vec!["/ARGS".to_string()],
|
||||
current_exe_args,
|
||||
config
|
||||
.tauri
|
||||
.updater
|
||||
.windows
|
||||
.installer_args
|
||||
.iter()
|
||||
.map(AsRef::as_ref)
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>(),
|
||||
]
|
||||
.concat();
|
||||
|
||||
// Run the EXE
|
||||
let mut cmd = Command::new(powershell_path);
|
||||
cmd
|
||||
.args(["-NoProfile", "-WindowStyle", "Hidden"])
|
||||
.args(["Start-Process"])
|
||||
.args(["-NoProfile", "-WindowStyle", "Hidden", "Start-Process"])
|
||||
.arg(installer_path);
|
||||
if !installer_args.is_empty() {
|
||||
cmd.arg("-ArgumentList").arg(installer_args.join(", "));
|
||||
}
|
||||
cmd.spawn().expect("installer failed to start");
|
||||
cmd
|
||||
.spawn()
|
||||
.expect("Running NSIS installer from powershell has failed to start");
|
||||
|
||||
exit(0);
|
||||
} else if found_path.extension() == Some(OsStr::new("msi")) {
|
||||
@@ -908,10 +922,10 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
}
|
||||
|
||||
// we need to wrap the current exe path in quotes for Start-Process
|
||||
let mut current_exe_arg = std::ffi::OsString::new();
|
||||
current_exe_arg.push("\"");
|
||||
current_exe_arg.push(current_exe()?);
|
||||
current_exe_arg.push("\"");
|
||||
let mut current_executable = std::ffi::OsString::new();
|
||||
current_executable.push("\"");
|
||||
current_executable.push(dunce::simplified(¤t_exe()?));
|
||||
current_executable.push("\"");
|
||||
|
||||
let mut msi_path = std::ffi::OsString::new();
|
||||
msi_path.push("\"\"\"");
|
||||
@@ -933,7 +947,9 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
.concat();
|
||||
|
||||
// run the installer and relaunch the application
|
||||
let powershell_install_res = Command::new(powershell_path)
|
||||
let mut powershell_cmd = Command::new(powershell_path);
|
||||
|
||||
powershell_cmd
|
||||
.args(["-NoProfile", "-WindowStyle", "Hidden"])
|
||||
.args([
|
||||
"Start-Process",
|
||||
@@ -946,8 +962,15 @@ fn copy_files_and_run<R: Read + Seek>(
|
||||
.arg(&msi_path)
|
||||
.arg(format!(", {}, /promptrestart;", installer_args.join(", ")))
|
||||
.arg("Start-Process")
|
||||
.arg(current_exe_arg)
|
||||
.spawn();
|
||||
.arg(current_executable);
|
||||
|
||||
if !current_exe_args.is_empty() {
|
||||
powershell_cmd
|
||||
.arg("-ArgumentList")
|
||||
.arg(current_exe_args.join(", "));
|
||||
}
|
||||
|
||||
let powershell_install_res = powershell_cmd.spawn();
|
||||
if powershell_install_res.is_err() {
|
||||
// fallback to running msiexec directly - relaunch won't be available
|
||||
// we use this here in case powershell fails in an older machine somehow
|
||||
|
||||
@@ -45,21 +45,21 @@
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-terser": "0.4.4",
|
||||
"@rollup/plugin-typescript": "11.1.5",
|
||||
"@types/node": "20.9.0",
|
||||
"@types/node": "20.10.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.62.0",
|
||||
"eslint-config-standard-with-typescript": "34.0.1",
|
||||
"@typescript-eslint/parser": "5.62.0",
|
||||
"eslint": "8.53.0",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "8.10.0",
|
||||
"eslint-plugin-import": "2.29.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-n": "15.7.0",
|
||||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-security": "1.7.1",
|
||||
"fast-glob": "3.3.2",
|
||||
"prettier": "3.0.3",
|
||||
"prettier": "3.1.1",
|
||||
"rollup": "3.29.4",
|
||||
"typescript": "5.2.2"
|
||||
"typescript": "5.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.6.0",
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz#1816b5f6948029c5eaacb0703b850ee0cb37d8f8"
|
||||
integrity sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==
|
||||
|
||||
"@eslint/eslintrc@^2.1.3":
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz#797470a75fe0fbd5a53350ee715e85e87baff22d"
|
||||
integrity sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==
|
||||
"@eslint/eslintrc@^2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
|
||||
integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
@@ -39,10 +39,10 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@8.53.0":
|
||||
version "8.53.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.53.0.tgz#bea56f2ed2b5baea164348ff4d5a879f6f81f20d"
|
||||
integrity sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==
|
||||
"@eslint/js@8.56.0":
|
||||
version "8.56.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b"
|
||||
integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.13":
|
||||
version "0.11.13"
|
||||
@@ -165,10 +165,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/node@20.9.0":
|
||||
version "20.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298"
|
||||
integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==
|
||||
"@types/node@20.10.5":
|
||||
version "20.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2"
|
||||
integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
@@ -664,10 +664,10 @@ eslint-plugin-es@^4.1.0:
|
||||
eslint-utils "^2.0.0"
|
||||
regexpp "^3.0.0"
|
||||
|
||||
eslint-plugin-import@2.29.0:
|
||||
version "2.29.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155"
|
||||
integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==
|
||||
eslint-plugin-import@2.29.1:
|
||||
version "2.29.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643"
|
||||
integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
|
||||
dependencies:
|
||||
array-includes "^3.1.7"
|
||||
array.prototype.findlastindex "^1.2.3"
|
||||
@@ -685,7 +685,7 @@ eslint-plugin-import@2.29.0:
|
||||
object.groupby "^1.0.1"
|
||||
object.values "^1.1.7"
|
||||
semver "^6.3.1"
|
||||
tsconfig-paths "^3.14.2"
|
||||
tsconfig-paths "^3.15.0"
|
||||
|
||||
eslint-plugin-n@15.7.0:
|
||||
version "15.7.0"
|
||||
@@ -780,15 +780,15 @@ eslint-visitor-keys@^3.4.3:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint@8.53.0:
|
||||
version "8.53.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.53.0.tgz#14f2c8244298fcae1f46945459577413ba2697ce"
|
||||
integrity sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==
|
||||
eslint@8.56.0:
|
||||
version "8.56.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15"
|
||||
integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@eslint-community/regexpp" "^4.6.1"
|
||||
"@eslint/eslintrc" "^2.1.3"
|
||||
"@eslint/js" "8.53.0"
|
||||
"@eslint/eslintrc" "^2.1.4"
|
||||
"@eslint/js" "8.56.0"
|
||||
"@humanwhocodes/config-array" "^0.11.13"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@nodelib/fs.walk" "^1.2.8"
|
||||
@@ -1593,10 +1593,10 @@ prelude-ls@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
prettier@3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643"
|
||||
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
|
||||
prettier@3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848"
|
||||
integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
@@ -1883,10 +1883,10 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tsconfig-paths@^3.14.2:
|
||||
version "3.14.2"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
|
||||
integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
|
||||
tsconfig-paths@^3.15.0:
|
||||
version "3.15.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4"
|
||||
integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
json5 "^1.0.2"
|
||||
@@ -1956,10 +1956,10 @@ typed-array-length@^1.0.4:
|
||||
for-each "^0.3.3"
|
||||
is-typed-array "^1.1.9"
|
||||
|
||||
typescript@5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||
typescript@5.3.3:
|
||||
version "5.3.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
|
||||
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
|
||||
|
||||
unbox-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
|
||||
@@ -19,7 +19,7 @@ exclude = [ "CHANGELOG.md", "/target", "rustfmt.toml" ]
|
||||
[dependencies]
|
||||
tauri-utils = { version = "1.5.2", path = "../../core/tauri-utils", features = [ "resources" ] }
|
||||
image = "0.24.7"
|
||||
libflate = "2.0"
|
||||
flate2 = "1.0"
|
||||
anyhow = "1.0"
|
||||
thiserror = "1.0"
|
||||
serde_json = "1.0"
|
||||
@@ -32,7 +32,7 @@ tempfile = "3.8.1"
|
||||
log = { version = "0.4.20", features = [ "kv_unstable" ] }
|
||||
dirs-next = "2.0"
|
||||
os_pipe = "1"
|
||||
ureq = { version = "2.8", default-features = false }
|
||||
ureq = { version = "2.9.1", default-features = false, features = [ "socks-proxy" ] }
|
||||
native-tls = { version = "0.2", optional = true }
|
||||
hex = "0.4"
|
||||
semver = "1"
|
||||
|
||||
@@ -29,9 +29,9 @@ use anyhow::Context;
|
||||
use handlebars::Handlebars;
|
||||
use heck::AsKebabCase;
|
||||
use image::{self, codecs::png::PngDecoder, ImageDecoder};
|
||||
use libflate::gzip;
|
||||
use log::info;
|
||||
use serde::Serialize;
|
||||
use tar::HeaderMode;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use std::{
|
||||
@@ -39,9 +39,12 @@ use std::{
|
||||
ffi::OsStr,
|
||||
fs::{self, read_to_string, File},
|
||||
io::{self, Write},
|
||||
os::unix::fs::MetadataExt,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use flate2::{write::GzEncoder, Compression};
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct DebIcon {
|
||||
pub width: u32,
|
||||
@@ -132,10 +135,30 @@ pub fn generate_data(
|
||||
let icons =
|
||||
generate_icon_files(settings, &data_dir).with_context(|| "Failed to create icon files")?;
|
||||
generate_desktop_file(settings, &data_dir).with_context(|| "Failed to create desktop file")?;
|
||||
generate_changelog_file(settings, &data_dir)
|
||||
.with_context(|| "Failed to create changelog.gz file")?;
|
||||
|
||||
Ok((data_dir, icons))
|
||||
}
|
||||
|
||||
/// Generate the Changelog file by compressing, to be stored at /usr/share/doc/package-name/changelog.gz. See
|
||||
/// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes
|
||||
fn generate_changelog_file(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
|
||||
if let Some(changelog_src_path) = &settings.deb().changelog {
|
||||
let mut src_file = File::open(changelog_src_path)?;
|
||||
let bin_name = settings.main_binary_name();
|
||||
let dest_path = data_dir.join(format!("usr/share/doc/{}/changelog.gz", bin_name));
|
||||
|
||||
let changelog_file = common::create_file(&dest_path)?;
|
||||
let mut gzip_encoder = GzEncoder::new(changelog_file, Compression::new(9));
|
||||
io::copy(&mut src_file, &mut gzip_encoder)?;
|
||||
|
||||
let mut changelog_file = gzip_encoder.finish()?;
|
||||
changelog_file.flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate the application desktop file and store it under the `data_dir`.
|
||||
fn generate_desktop_file(settings: &Settings, data_dir: &Path) -> crate::Result<()> {
|
||||
let bin_name = settings.main_binary_name();
|
||||
@@ -209,6 +232,14 @@ fn generate_control_file(
|
||||
writeln!(file, "Installed-Size: {}", total_dir_size(data_dir)? / 1024)?;
|
||||
let authors = settings.authors_comma_separated().unwrap_or_default();
|
||||
writeln!(file, "Maintainer: {}", authors)?;
|
||||
if let Some(section) = &settings.deb().section {
|
||||
writeln!(file, "Section: {}", section)?;
|
||||
}
|
||||
if let Some(priority) = &settings.deb().priority {
|
||||
writeln!(file, "Priority: {}", priority)?;
|
||||
} else {
|
||||
writeln!(file, "Priority: optional")?;
|
||||
}
|
||||
if !settings.homepage_url().is_empty() {
|
||||
writeln!(file, "Homepage: {}", settings.homepage_url())?;
|
||||
}
|
||||
@@ -233,7 +264,6 @@ fn generate_control_file(
|
||||
writeln!(file, " {}", line)?;
|
||||
}
|
||||
}
|
||||
writeln!(file, "Priority: optional")?;
|
||||
file.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -366,20 +396,15 @@ fn create_tar_from_dir<P: AsRef<Path>, W: Write>(src_dir: P, dest_file: W) -> cr
|
||||
continue;
|
||||
}
|
||||
let dest_path = src_path.strip_prefix(src_dir)?;
|
||||
let stat = fs::metadata(src_path)?;
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_metadata_in_mode(&stat, HeaderMode::Deterministic);
|
||||
header.set_mtime(stat.mtime() as u64);
|
||||
|
||||
if entry.file_type().is_dir() {
|
||||
let stat = fs::metadata(src_path)?;
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_metadata(&stat);
|
||||
header.set_uid(0);
|
||||
header.set_gid(0);
|
||||
tar_builder.append_data(&mut header, dest_path, &mut io::empty())?;
|
||||
} else {
|
||||
let mut src_file = fs::File::open(src_path)?;
|
||||
let stat = src_file.metadata()?;
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_metadata(&stat);
|
||||
header.set_uid(0);
|
||||
header.set_gid(0);
|
||||
tar_builder.append_data(&mut header, dest_path, &mut src_file)?;
|
||||
}
|
||||
}
|
||||
@@ -394,9 +419,9 @@ fn tar_and_gzip_dir<P: AsRef<Path>>(src_dir: P) -> crate::Result<PathBuf> {
|
||||
let src_dir = src_dir.as_ref();
|
||||
let dest_path = src_dir.with_extension("tar.gz");
|
||||
let dest_file = common::create_file(&dest_path)?;
|
||||
let gzip_encoder = gzip::Encoder::new(dest_file)?;
|
||||
let gzip_encoder = GzEncoder::new(dest_file, Compression::default());
|
||||
let gzip_encoder = create_tar_from_dir(src_dir, gzip_encoder)?;
|
||||
let mut dest_file = gzip_encoder.finish().into_result()?;
|
||||
let mut dest_file = gzip_encoder.finish()?;
|
||||
dest_file.flush()?;
|
||||
Ok(dest_path)
|
||||
}
|
||||
|
||||
@@ -39,6 +39,15 @@ use std::{
|
||||
process::Command,
|
||||
};
|
||||
|
||||
const NESTED_CODE_FOLDER: [&str; 6] = [
|
||||
"MacOS",
|
||||
"Frameworks",
|
||||
"Plugins",
|
||||
"Helpers",
|
||||
"XPCServices",
|
||||
"Libraries",
|
||||
];
|
||||
|
||||
/// Bundles the project.
|
||||
/// Returns a vector of PathBuf that shows where the .app was created.
|
||||
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
@@ -77,18 +86,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
|
||||
let framework_paths = copy_frameworks_to_bundle(&bundle_directory, settings)
|
||||
.with_context(|| "Failed to bundle frameworks")?;
|
||||
sign_paths.extend(
|
||||
framework_paths
|
||||
.into_iter()
|
||||
.filter(|p| {
|
||||
let ext = p.extension();
|
||||
ext == Some(OsStr::new("framework")) || ext == Some(OsStr::new("dylib"))
|
||||
})
|
||||
.map(|path| SignTarget {
|
||||
path,
|
||||
is_an_executable: false,
|
||||
}),
|
||||
);
|
||||
sign_paths.extend(framework_paths);
|
||||
|
||||
settings.copy_resources(&resources_dir)?;
|
||||
|
||||
@@ -141,7 +139,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
|
||||
fn remove_extra_attr(app_bundle_path: &Path) -> crate::Result<()> {
|
||||
Command::new("xattr")
|
||||
.arg("-cr")
|
||||
.arg("-crs")
|
||||
.arg(app_bundle_path)
|
||||
.output_ok()
|
||||
.context("failed to remove extra attributes from app bundle")?;
|
||||
@@ -265,7 +263,7 @@ fn copy_framework_from(dest_dir: &Path, framework: &str, src_dir: &Path) -> crat
|
||||
fn copy_frameworks_to_bundle(
|
||||
bundle_directory: &Path,
|
||||
settings: &Settings,
|
||||
) -> crate::Result<Vec<PathBuf>> {
|
||||
) -> crate::Result<Vec<SignTarget>> {
|
||||
let mut paths = Vec::new();
|
||||
|
||||
let frameworks = settings
|
||||
@@ -288,7 +286,7 @@ fn copy_frameworks_to_bundle(
|
||||
.expect("Couldn't get framework filename");
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
common::copy_dir(&src_path, &dest_path)?;
|
||||
paths.push(dest_path);
|
||||
add_framework_sign_path(&src_path, &dest_path, &mut paths);
|
||||
continue;
|
||||
} else if framework.ends_with(".dylib") {
|
||||
let src_path = PathBuf::from(framework);
|
||||
@@ -301,7 +299,10 @@ fn copy_frameworks_to_bundle(
|
||||
let src_name = src_path.file_name().expect("Couldn't get library filename");
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
common::copy_file(&src_path, &dest_path)?;
|
||||
paths.push(dest_path);
|
||||
paths.push(SignTarget {
|
||||
path: dest_path,
|
||||
is_an_executable: false,
|
||||
});
|
||||
continue;
|
||||
} else if framework.contains('/') {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
@@ -330,3 +331,90 @@ fn copy_frameworks_to_bundle(
|
||||
}
|
||||
Ok(paths)
|
||||
}
|
||||
|
||||
/// Recursively add framework's sign paths.
|
||||
/// If the framework has multiple versions, it will sign "Current" version by default.
|
||||
fn add_framework_sign_path(
|
||||
framework_root: &Path,
|
||||
dest_path: &Path,
|
||||
sign_paths: &mut Vec<SignTarget>,
|
||||
) {
|
||||
if framework_root.join("Versions/Current").exists() {
|
||||
add_nested_code_sign_path(
|
||||
&framework_root.join("Versions/Current"),
|
||||
&dest_path.join("Versions/Current"),
|
||||
sign_paths,
|
||||
);
|
||||
} else {
|
||||
add_nested_code_sign_path(framework_root, dest_path, sign_paths);
|
||||
}
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path.into(),
|
||||
is_an_executable: false,
|
||||
});
|
||||
}
|
||||
|
||||
/// Recursively add executable bundle's sign path (.xpc, .app).
|
||||
fn add_executable_bundle_sign_path(
|
||||
bundle_root: &Path,
|
||||
dest_path: &Path,
|
||||
sign_paths: &mut Vec<SignTarget>,
|
||||
) {
|
||||
if bundle_root.join("Contents").exists() {
|
||||
add_nested_code_sign_path(
|
||||
&bundle_root.join("Contents"),
|
||||
&dest_path.join("Contents"),
|
||||
sign_paths,
|
||||
);
|
||||
} else {
|
||||
add_nested_code_sign_path(bundle_root, dest_path, sign_paths);
|
||||
}
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path.into(),
|
||||
is_an_executable: true,
|
||||
});
|
||||
}
|
||||
|
||||
fn add_nested_code_sign_path(src_path: &Path, dest_path: &Path, sign_paths: &mut Vec<SignTarget>) {
|
||||
for folder_name in NESTED_CODE_FOLDER.iter() {
|
||||
let src_folder_path = src_path.join(folder_name);
|
||||
let dest_folder_path = dest_path.join(folder_name);
|
||||
|
||||
if src_folder_path.exists() {
|
||||
for entry in walkdir::WalkDir::new(src_folder_path)
|
||||
.min_depth(1)
|
||||
.max_depth(1)
|
||||
.into_iter()
|
||||
.filter_map(|e| e.ok())
|
||||
{
|
||||
if entry.path_is_symlink() || entry.file_name().to_string_lossy().starts_with('.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dest_path = dest_folder_path.join(entry.file_name());
|
||||
let ext = entry.path().extension();
|
||||
if entry.path().is_dir() {
|
||||
// Bundles, like .app, .framework, .xpc
|
||||
if ext == Some(OsStr::new("framework")) {
|
||||
add_framework_sign_path(&entry.clone().into_path(), &dest_path, sign_paths);
|
||||
} else if ext == Some(OsStr::new("xpc")) || ext == Some(OsStr::new("app")) {
|
||||
add_executable_bundle_sign_path(&entry.clone().into_path(), &dest_path, sign_paths);
|
||||
}
|
||||
} else if entry.path().is_file() {
|
||||
// Binaries, like .dylib, Mach-O executables
|
||||
if ext == Some(OsStr::new("dylib")) {
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path,
|
||||
is_an_executable: false,
|
||||
});
|
||||
} else if ext.is_none() {
|
||||
sign_paths.push(SignTarget {
|
||||
path: dest_path,
|
||||
is_an_executable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +185,14 @@ pub struct DebianSettings {
|
||||
#[doc = include_str!("./linux/templates/main.desktop")]
|
||||
/// ```
|
||||
pub desktop_template: Option<PathBuf>,
|
||||
/// Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
|
||||
pub section: Option<String>,
|
||||
/// Change the priority of the Debian Package. By default, it is set to `optional`.
|
||||
/// Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`
|
||||
pub priority: Option<String>,
|
||||
/// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
|
||||
/// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes
|
||||
pub changelog: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// The macOS bundle settings.
|
||||
|
||||
@@ -234,12 +234,14 @@ pub fn create_zip(src_file: &Path, dst_file: &Path) -> crate::Result<PathBuf> {
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn create_tar(src_dir: &Path, dest_path: &Path) -> crate::Result<PathBuf> {
|
||||
use flate2::{write::GzEncoder, Compression};
|
||||
|
||||
let dest_file = common::create_file(dest_path)?;
|
||||
let gzip_encoder = libflate::gzip::Encoder::new(dest_file)?;
|
||||
let gzip_encoder = GzEncoder::new(dest_file, Compression::default());
|
||||
|
||||
let gzip_encoder = create_tar_from_src(src_dir, gzip_encoder)?;
|
||||
|
||||
let mut dest_file = gzip_encoder.finish().into_result()?;
|
||||
let mut dest_file = gzip_encoder.finish()?;
|
||||
dest_file.flush()?;
|
||||
Ok(dest_path.to_owned())
|
||||
}
|
||||
|
||||
@@ -606,7 +606,8 @@ Function .onInstSuccess
|
||||
check_r_flag:
|
||||
${GetOptions} $CMDLINE "/R" $R0
|
||||
IfErrors run_done 0
|
||||
Exec '"$INSTDIR\${MAINBINARYNAME}.exe"'
|
||||
${GetOptions} $CMDLINE "/ARGS" $R0
|
||||
Exec '"$INSTDIR\${MAINBINARYNAME}.exe" $R0'
|
||||
run_done:
|
||||
FunctionEnd
|
||||
|
||||
|
||||
74
tooling/cli/Cargo.lock
generated
74
tooling/cli/Cargo.lock
generated
@@ -17,12 +17,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.2"
|
||||
@@ -533,15 +527,6 @@ version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||
|
||||
[[package]]
|
||||
name = "core2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.11"
|
||||
@@ -711,12 +696,6 @@ dependencies = [
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dary_heap"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca"
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.5.0"
|
||||
@@ -1193,15 +1172,6 @@ version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
@@ -1647,30 +1617,6 @@ version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "libflate"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7d5654ae1795afc7ff76f4365c2c8791b0feb18e8996a96adad8ffd7c3b2bf"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"core2",
|
||||
"crc32fast",
|
||||
"dary_heap",
|
||||
"libflate_lz77",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libflate_lz77"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be5f52fb8c451576ec6b79d3f4deb327398bc05bbdbd99021a6e77a4c855d524"
|
||||
dependencies = [
|
||||
"core2",
|
||||
"hashbrown 0.13.2",
|
||||
"rle-decode-fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.1"
|
||||
@@ -2745,12 +2691,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rle-decode-fast"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
|
||||
|
||||
[[package]]
|
||||
name = "rpassword"
|
||||
version = "7.3.1"
|
||||
@@ -3212,6 +3152,17 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socks"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
@@ -3401,12 +3352,12 @@ dependencies = [
|
||||
"ar",
|
||||
"dirs-next",
|
||||
"dunce",
|
||||
"flate2",
|
||||
"glob",
|
||||
"handlebars",
|
||||
"heck",
|
||||
"hex",
|
||||
"image",
|
||||
"libflate",
|
||||
"log",
|
||||
"md5",
|
||||
"native-tls",
|
||||
@@ -3921,6 +3872,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"rustls",
|
||||
"rustls-webpki",
|
||||
"socks",
|
||||
"url",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
@@ -59,7 +59,7 @@ handlebars = "4.4"
|
||||
include_dir = "0.7"
|
||||
minisign = "=0.7.3"
|
||||
base64 = "0.21.5"
|
||||
ureq = { version = "2.8", default-features = false, features = [ "gzip" ] }
|
||||
ureq = { version = "2.9.1", default-features = false, features = [ "gzip" ] }
|
||||
os_info = "3"
|
||||
semver = "1.0"
|
||||
regex = "1.10.2"
|
||||
|
||||
1
tooling/cli/node/index.d.ts
vendored
1
tooling/cli/node/index.d.ts
vendored
@@ -4,4 +4,5 @@
|
||||
/* auto-generated by NAPI-RS */
|
||||
|
||||
export function run(args: Array<string>, binName: string | undefined | null, callback: (...args: any[]) => any): void
|
||||
export function killDevApp(callback: (...args: any[]) => any): void
|
||||
export function logError(error: string): void
|
||||
|
||||
@@ -252,7 +252,8 @@ if (!nativeBinding) {
|
||||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { run, logError } = nativeBinding
|
||||
const { run, killDevApp, logError } = nativeBinding
|
||||
|
||||
module.exports.run = run
|
||||
module.exports.killDevApp = killDevApp
|
||||
module.exports.logError = logError
|
||||
|
||||
1
tooling/cli/node/main.d.ts
vendored
1
tooling/cli/node/main.d.ts
vendored
@@ -6,3 +6,4 @@
|
||||
/* eslint-disable */
|
||||
|
||||
export function run(args: Array<string>, binName: string | undefined | null): Promise<void>
|
||||
export function killDevApp(): Promise<void>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const { run, logError } = require('./index')
|
||||
const { run, killDevApp, logError } = require('./index')
|
||||
|
||||
module.exports.run = (args, binName) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -16,4 +16,16 @@ module.exports.run = (args, binName) => {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.killDevApp = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
killDevApp(res => {
|
||||
if (res instanceof Error) {
|
||||
reject(res)
|
||||
} else {
|
||||
resolve(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.logError = logError
|
||||
|
||||
@@ -25,6 +25,23 @@ pub fn run(args: Vec<String>, bin_name: Option<String>, callback: JsFunction) ->
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[napi_derive::napi]
|
||||
pub fn kill_dev_app(callback: JsFunction) -> Result<()> {
|
||||
let function: ThreadsafeFunction<bool, ErrorStrategy::CalleeHandled> = callback
|
||||
.create_threadsafe_function(0, |ctx| ctx.env.get_boolean(ctx.value).map(|v| vec![v]))?;
|
||||
|
||||
// we need to run in a separate thread so Node.js (e.g. vue-cli-plugin-tauri) consumers
|
||||
// can do work while `tauri dev` is running.
|
||||
std::thread::spawn(move || match tauri_cli::kill_dev_app() {
|
||||
Ok(_) => function.call(Ok(true), ThreadsafeFunctionCallMode::Blocking),
|
||||
Err(e) => function.call(
|
||||
Err(Error::new(Status::GenericFailure, format!("{:#}", e))),
|
||||
ThreadsafeFunctionCallMode::Blocking,
|
||||
),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[napi_derive::napi]
|
||||
pub fn log_error(error: String) {
|
||||
log::error!("{}", error);
|
||||
|
||||
@@ -1320,6 +1320,27 @@
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"section": {
|
||||
"description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"priority": {
|
||||
"description": "Change the priority of the Debian Package. By default, it is set to `optional`. Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"changelog": {
|
||||
"description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
command_env,
|
||||
config::{get as get_config, reload as reload_config, AppUrl, BeforeDevCommand, WindowUrl},
|
||||
},
|
||||
interface::{AppInterface, ExitReason, Interface},
|
||||
interface::{rust::DevChild, AppInterface, ExitReason, Interface},
|
||||
CommandExt, Result,
|
||||
};
|
||||
use clap::{ArgAction, Parser};
|
||||
@@ -27,6 +27,7 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
pub(crate) static DEV_CHILD: OnceCell<Arc<Mutex<DevChild>>> = OnceCell::new();
|
||||
static BEFORE_DEV: OnceCell<Mutex<Arc<SharedChild>>> = OnceCell::new();
|
||||
static KILL_BEFORE_DEV_FLAG: OnceCell<AtomicBool> = OnceCell::new();
|
||||
|
||||
|
||||
@@ -123,11 +123,13 @@ pub fn start_dev_server<P: AsRef<Path>>(path: P, port: Option<u16>) -> crate::Re
|
||||
}
|
||||
|
||||
async fn handler(uri: axum::http::Uri, state: Arc<State>) -> impl IntoResponse {
|
||||
let uri = uri.to_string();
|
||||
// Frontend files should not contain query parameters. This seems to be how vite handles it.
|
||||
let uri = uri.path();
|
||||
|
||||
let uri = if uri == "/" {
|
||||
&uri
|
||||
uri
|
||||
} else {
|
||||
uri.strip_prefix('/').unwrap_or(&uri)
|
||||
uri.strip_prefix('/').unwrap_or(uri)
|
||||
};
|
||||
|
||||
let file = std::fs::read(state.serve_dir.join(uri))
|
||||
|
||||
@@ -92,7 +92,7 @@ pub struct DevChild {
|
||||
}
|
||||
|
||||
impl DevChild {
|
||||
fn kill(&self) -> std::io::Result<()> {
|
||||
pub fn kill(&self) -> std::io::Result<()> {
|
||||
if let Some(child) = &*self.app_child.lock().unwrap() {
|
||||
child.kill()?;
|
||||
} else {
|
||||
@@ -195,11 +195,13 @@ impl Interface for Rust {
|
||||
|
||||
if options.no_watch {
|
||||
let (tx, rx) = sync_channel(1);
|
||||
self.run_dev(options, move |status, reason| {
|
||||
let child = self.run_dev(options, move |status, reason| {
|
||||
tx.send(()).unwrap();
|
||||
on_exit_(status, reason)
|
||||
})?;
|
||||
|
||||
let _ = crate::dev::DEV_CHILD.set(Arc::new(Mutex::new(child)));
|
||||
|
||||
rx.recv().unwrap();
|
||||
Ok(())
|
||||
} else {
|
||||
@@ -207,6 +209,10 @@ impl Interface for Rust {
|
||||
on_exit_(status, reason)
|
||||
})?;
|
||||
|
||||
let child = Arc::new(Mutex::new(child));
|
||||
let child_ = Arc::clone(&child);
|
||||
let _ = crate::dev::DEV_CHILD.set(child_);
|
||||
|
||||
self.run_dev_watcher(child, options, on_exit)
|
||||
}
|
||||
}
|
||||
@@ -347,6 +353,40 @@ fn expand_member_path(path: &Path) -> crate::Result<Vec<PathBuf>> {
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn get_watch_folders() -> crate::Result<Vec<PathBuf>> {
|
||||
let tauri_path = tauri_dir();
|
||||
let workspace_path = get_workspace_dir()?;
|
||||
|
||||
// We always want to watch the main tauri folder.
|
||||
let mut watch_folders = vec![tauri_path.to_path_buf()];
|
||||
|
||||
// We also try to watch workspace members, no matter if the tauri cargo project is the workspace root or a workspace member
|
||||
let cargo_settings = CargoSettings::load(&workspace_path)?;
|
||||
if let Some(members) = cargo_settings.workspace.and_then(|w| w.members) {
|
||||
for p in members {
|
||||
let p = workspace_path.join(p);
|
||||
match expand_member_path(&p) {
|
||||
// Sometimes expand_member_path returns an empty vec, for example if the path contains `[]` as in `C:/[abc]/project/`.
|
||||
// Cargo won't complain unless theres a workspace.members config with glob patterns so we should support it too.
|
||||
Ok(expanded_paths) => {
|
||||
if expanded_paths.is_empty() {
|
||||
watch_folders.push(p);
|
||||
} else {
|
||||
watch_folders.extend(expanded_paths);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
// If this fails cargo itself should fail too. But we still try to keep going with the unexpanded path.
|
||||
error!("Error watching {}: {}", p.display(), err.to_string());
|
||||
watch_folders.push(p);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Ok(watch_folders)
|
||||
}
|
||||
|
||||
impl Rust {
|
||||
fn run_dev<F: Fn(ExitStatus, ExitReason) + Send + Sync + 'static>(
|
||||
&mut self,
|
||||
@@ -405,50 +445,17 @@ impl Rust {
|
||||
|
||||
fn run_dev_watcher<F: Fn(ExitStatus, ExitReason) + Send + Sync + 'static>(
|
||||
&mut self,
|
||||
child: DevChild,
|
||||
process: Arc<Mutex<DevChild>>,
|
||||
options: Options,
|
||||
on_exit: Arc<F>,
|
||||
) -> crate::Result<()> {
|
||||
let process = Arc::new(Mutex::new(child));
|
||||
let (tx, rx) = sync_channel(1);
|
||||
let app_path = app_dir();
|
||||
let tauri_path = tauri_dir();
|
||||
let workspace_path = get_workspace_dir()?;
|
||||
|
||||
let watch_folders = if tauri_path == workspace_path {
|
||||
vec![tauri_path]
|
||||
} else {
|
||||
let cargo_settings = CargoSettings::load(&workspace_path)?;
|
||||
cargo_settings
|
||||
.workspace
|
||||
.as_ref()
|
||||
.map(|w| {
|
||||
w.members
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|p| workspace_path.join(p))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_else(|| vec![tauri_path])
|
||||
};
|
||||
let watch_folders = get_watch_folders()?;
|
||||
|
||||
let watch_folders = watch_folders
|
||||
.into_iter()
|
||||
.flat_map(|p| {
|
||||
match expand_member_path(&p) {
|
||||
Ok(p) => p,
|
||||
Err(err) => {
|
||||
// If this fails cargo itself should fail too. But we still try to keep going with the unexpanded path.
|
||||
error!("Error watching {}: {}", p.display(), err.to_string());
|
||||
vec![p]
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let watch_folders = watch_folders.iter().map(Path::new).collect::<Vec<_>>();
|
||||
|
||||
let common_ancestor = common_path::common_path_all(watch_folders.clone()).unwrap();
|
||||
let common_ancestor = common_path::common_path_all(watch_folders.iter().map(Path::new))
|
||||
.expect("watch_folders should not be empty");
|
||||
let ignore_matcher = build_ignore_matcher(&common_ancestor);
|
||||
|
||||
let mut watcher = new_debouncer(Duration::from_secs(1), move |r| {
|
||||
@@ -458,9 +465,9 @@ impl Rust {
|
||||
})
|
||||
.unwrap();
|
||||
for path in watch_folders {
|
||||
if !ignore_matcher.is_ignore(path, true) {
|
||||
info!("Watching {} for changes...", display_path(path));
|
||||
lookup(path, |file_type, p| {
|
||||
if !ignore_matcher.is_ignore(&path, true) {
|
||||
info!("Watching {} for changes...", display_path(&path));
|
||||
lookup(&path, |file_type, p| {
|
||||
if p != path {
|
||||
debug!("Watching {} for changes...", display_path(&p));
|
||||
let _ = watcher.watcher().watch(
|
||||
@@ -690,7 +697,7 @@ impl AppSettings for RustAppSettings {
|
||||
.expect("Cargo manifest must have the `package.name` field");
|
||||
|
||||
let out_dir = self
|
||||
.out_dir(options.target.clone(), get_profile(options))
|
||||
.out_dir(options.target.clone(), get_profile_dir(options).to_string())
|
||||
.with_context(|| "failed to get project out directory")?;
|
||||
|
||||
let binary_extension: String = if self.target_triple.contains("windows") {
|
||||
@@ -984,13 +991,20 @@ pub fn get_workspace_dir() -> crate::Result<PathBuf> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_profile(options: &Options) -> String {
|
||||
pub fn get_profile(options: &Options) -> &str {
|
||||
options
|
||||
.args
|
||||
.iter()
|
||||
.position(|a| a == "--profile")
|
||||
.map(|i| options.args[i + 1].clone())
|
||||
.unwrap_or_else(|| if options.debug { "debug" } else { "release" }.into())
|
||||
.map(|i| options.args[i + 1].as_str())
|
||||
.unwrap_or_else(|| if options.debug { "debug" } else { "release" })
|
||||
}
|
||||
|
||||
pub fn get_profile_dir(options: &Options) -> &str {
|
||||
match get_profile(options) {
|
||||
"dev" => "debug",
|
||||
profile => profile,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@@ -1099,6 +1113,9 @@ fn tauri_config_to_bundle_settings(
|
||||
},
|
||||
files: config.deb.files,
|
||||
desktop_template: config.deb.desktop_template,
|
||||
section: config.deb.section,
|
||||
priority: config.deb.priority,
|
||||
changelog: config.deb.changelog,
|
||||
},
|
||||
macos: MacOsSettings {
|
||||
frameworks: config.macos.frameworks,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use super::{get_profile, AppSettings, DevChild, ExitReason, Options, RustAppSettings, Target};
|
||||
use super::{get_profile_dir, AppSettings, DevChild, ExitReason, Options, RustAppSettings, Target};
|
||||
use crate::CommandExt;
|
||||
use tauri_utils::display_path;
|
||||
|
||||
@@ -125,7 +125,7 @@ pub fn build(
|
||||
options.target.replace(triple.into());
|
||||
|
||||
let triple_out_dir = app_settings
|
||||
.out_dir(Some(triple.into()), get_profile(&options))
|
||||
.out_dir(Some(triple.into()), get_profile_dir(&options).to_string())
|
||||
.with_context(|| format!("failed to get {triple} out dir"))?;
|
||||
|
||||
build_production_app(options, available_targets, config_features.clone())
|
||||
|
||||
@@ -177,6 +177,14 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn kill_dev_app() -> Result<()> {
|
||||
dev::DEV_CHILD
|
||||
.get()
|
||||
.map(|child| child.lock().unwrap().kill())
|
||||
.unwrap_or(Ok(()))
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// This maps the occurrence of `--verbose` flags to the correct log level
|
||||
fn verbosity_level(num: u8) -> Level {
|
||||
match num {
|
||||
|
||||
Reference in New Issue
Block a user