diff --git a/.forgejo/workflows/dev-bakery.yml b/.forgejo/workflows/dev-bakery.yml deleted file mode 100644 index a7c4bde..0000000 --- a/.forgejo/workflows/dev-bakery.yml +++ /dev/null @@ -1,99 +0,0 @@ -name: dev bakery - -# Publishes a dev-track build on every push to `main` (the trunk branch — -# there is no separate `dev` branch). See docs/release-channels.md for the -# release-track policy this is part of. -on: - push: - branches: ['main'] - paths: - - 'bakery/**' - - 'bread-utils/**' - - 'Cargo.toml' - - 'Cargo.lock' - - '.forgejo/workflows/dev-bakery.yml' - -jobs: - build: - runs-on: [self-hosted, hestia] - steps: - - name: checkout - run: | - set -euo pipefail - rm -rf src && mkdir src - git clone --branch main --depth 1 \ - "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src - - - name: build - run: cd src && cargo build --release --locked -p bakery - - - name: test - run: cd src && cargo test --release --locked -p bakery - - # Auto-bumps the patch version from Cargo.toml and appends a - # timestamp+sha dev suffix — no developer discipline required, and the - # result is visibly "ahead of" the last stable patch release while - # staying valid semver (comparable within the dev track by bakery's - # `is_newer`). - - name: compute dev version - run: | - set -euo pipefail - cd src - # Base the dev version off the latest published stable tag, - # not Cargo.toml — Cargo.toml can go stale relative to the last - # real release (seen in practice: breadbox/breadpad/breadcrumbs/ - # breadpaper), which would make a dev build sort as OLDER than - # what's already installed and bakery would correctly refuse it. - LATEST_TAG="$(git ls-remote --tags --refs \ - "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" 'v*' \ - | awk -F/ '{print $NF}' | sed 's/^v//' | (grep -v -- '-' || true) | sort -V | tail -1)" - if [ -n "${LATEST_TAG}" ]; then - CUR="${LATEST_TAG}" - else - CUR="$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"(.*)".*/\1/')" - fi - IFS='.' read -r MA MI PA <<< "${CUR}" - SHA="$(git rev-parse --short HEAD)" - TS="$(date -u +%Y%m%d%H%M%S)" - echo "VERSION=${MA}.${MI}.$((PA + 1))-dev.${TS}+${SHA}" >> "$GITHUB_ENV" - - - name: prepare artifacts - run: | - set -euo pipefail - PKG_DIR="/srv/breadway-dl/dev/bakery/${VERSION}" - mkdir -p "${PKG_DIR}" - cp "src/target/release/bakery" "${PKG_DIR}/bakery-x86_64" - strip "${PKG_DIR}/bakery-x86_64" - sha256sum "${PKG_DIR}/bakery-x86_64" | awk '{print $1}' \ - > "${PKG_DIR}/bakery-x86_64.sha256" - cp src/bakery.toml "${PKG_DIR}/bakery.toml" - ln -sfn "${VERSION}" "/srv/breadway-dl/dev/bakery/latest" - - - name: sign dev binary - env: - MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} - run: | - set -euo pipefail - PKG_DIR="/srv/breadway-dl/dev/bakery/${VERSION}" - if [ -n "${MINISIGN_SEC_KEY:-}" ]; then - minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/bakery-x86_64" \ - -x "${PKG_DIR}/bakery-x86_64.minisig" > "$GITHUB_ENV" - - - name: prepare artifacts - run: | - set -euo pipefail - PKG_DIR="/srv/breadway-dl/dev/bread-theme/${VERSION}" - mkdir -p "${PKG_DIR}" - cp "src/target/release/bread-theme" "${PKG_DIR}/bread-theme-x86_64" - strip "${PKG_DIR}/bread-theme-x86_64" - sha256sum "${PKG_DIR}/bread-theme-x86_64" | awk '{print $1}' \ - > "${PKG_DIR}/bread-theme-x86_64.sha256" - cp src/bread-theme/bakery.toml "${PKG_DIR}/bakery.toml" - ln -sfn "${VERSION}" "/srv/breadway-dl/dev/bread-theme/latest" - - - name: sign dev binary - env: - MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} - run: | - set -euo pipefail - PKG_DIR="/srv/breadway-dl/dev/bread-theme/${VERSION}" - if [ -n "${MINISIGN_SEC_KEY:-}" ]; then - minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/bread-theme-x86_64" \ - -x "${PKG_DIR}/bread-theme-x86_64.minisig" > "$GITHUB_ENV" - PKG_DIR="/srv/breadway-dl/beta/bakery/${VERSION}" - mkdir -p "${PKG_DIR}" - cp "src/target/release/bakery" "${PKG_DIR}/bakery-x86_64" - strip "${PKG_DIR}/bakery-x86_64" - sha256sum "${PKG_DIR}/bakery-x86_64" | awk '{print $1}' \ - > "${PKG_DIR}/bakery-x86_64.sha256" - cp src/bakery.toml "${PKG_DIR}/bakery.toml" - ln -sfn "${VERSION}" "/srv/breadway-dl/beta/bakery/latest" - - - name: sign beta binary - env: - MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} - run: | - set -euo pipefail - PKG_DIR="/srv/breadway-dl/beta/bakery/${VERSION}" - if [ -n "${MINISIGN_SEC_KEY:-}" ]; then - minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/bakery-x86_64" \ - -x "${PKG_DIR}/bakery-x86_64.minisig" > "$GITHUB_ENV" - PKG_DIR="/srv/breadway-dl/beta/bread-theme/${VERSION}" - mkdir -p "${PKG_DIR}" - cp "src/target/release/bread-theme" "${PKG_DIR}/bread-theme-x86_64" - strip "${PKG_DIR}/bread-theme-x86_64" - sha256sum "${PKG_DIR}/bread-theme-x86_64" | awk '{print $1}' \ - > "${PKG_DIR}/bread-theme-x86_64.sha256" - cp src/bread-theme/bakery.toml "${PKG_DIR}/bakery.toml" - ln -sfn "${VERSION}" "/srv/breadway-dl/beta/bread-theme/latest" - - - name: sign beta binary - env: - MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} - run: | - set -euo pipefail - PKG_DIR="/srv/breadway-dl/beta/bread-theme/${VERSION}" - if [ -n "${MINISIGN_SEC_KEY:-}" ]; then - minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/bread-theme-x86_64" \ - -x "${PKG_DIR}/bread-theme-x86_64.minisig" "${PKG_DIR}/bakery-x86_64.sha256" - cp src/bakery.toml "${PKG_DIR}/bakery.toml" - ln -sfn "${VERSION}" "/srv/breadway-dl/bakery/latest" - - # Signs the bakery binary itself with the shared bakery ecosystem signing - # key (same key that signs index.json and bread-theme — see - # release-bread-theme.yml). BAKERY_MINISIGN_SEC_KEY_PATH is a *path on - # this runner's disk* (hestia has persistent storage), not the key - # contents. Dormant (binary ships unsigned, as today) until that secret - # is provisioned. - - name: sign release binary - env: - MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} - run: | - set -euo pipefail - VERSION="${GITHUB_REF_NAME#v}" - PKG_DIR="/srv/breadway-dl/bakery/${VERSION}" - if [ -n "${MINISIGN_SEC_KEY:-}" ]; then - minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/bakery-x86_64" \ - -x "${PKG_DIR}/bakery-x86_64.minisig" /dev/null || true - ASSETS="${PKG_DIR}/bakery-x86_64 ${PKG_DIR}/bakery-x86_64.sha256" - [ -f "${PKG_DIR}/bakery-x86_64.minisig" ] && ASSETS="${ASSETS} ${PKG_DIR}/bakery-x86_64.minisig" - gh release upload "${GITHUB_REF_NAME}" --repo Breadway/bread-ecosystem ${ASSETS} --clobber diff --git a/.forgejo/workflows/release-bread-theme.yml b/.forgejo/workflows/release-bread-theme.yml deleted file mode 100644 index 2892e14..0000000 --- a/.forgejo/workflows/release-bread-theme.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: release bread-theme - -on: - push: - tags: ['v*'] - -jobs: - build: - if: ${{ !contains(github.ref_name, '-rc.') }} - runs-on: [self-hosted, hestia] - steps: - - name: checkout - run: | - set -euo pipefail - rm -rf src && mkdir src - git clone --branch "${GITHUB_REF_NAME}" --depth 1 \ - "https://git.breadway.dev/${GITHUB_REPOSITORY}.git" src - - - name: build - run: cd src && cargo build --release --locked -p bread-theme --bin bread-theme - - - name: prepare artifacts - run: | - set -euo pipefail - VERSION="${GITHUB_REF_NAME#v}" - PKG_DIR="/srv/breadway-dl/bread-theme/${VERSION}" - mkdir -p "${PKG_DIR}" - cp "src/target/release/bread-theme" "${PKG_DIR}/bread-theme-x86_64" - strip "${PKG_DIR}/bread-theme-x86_64" - sha256sum "${PKG_DIR}/bread-theme-x86_64" | awk '{print $1}' \ - > "${PKG_DIR}/bread-theme-x86_64.sha256" - cp src/bread-theme/bakery.toml "${PKG_DIR}/bakery.toml" - ln -sfn "${VERSION}" "/srv/breadway-dl/bread-theme/latest" - - # Signs the bread-theme binary with the shared bakery ecosystem signing - # key (same key that signs index.json — get.sh / manifest.rs pin the - # matching public key). BAKERY_MINISIGN_SEC_KEY_PATH is a *path on this - # runner's disk* (hestia has persistent storage, unlike a fresh - # GitHub-hosted runner), not the key contents — see the handoff note - # in scripts/gen-index.sh. Dormant (binary ships unsigned, as today) - # until that secret is provisioned. - - name: sign release binary - env: - MINISIGN_SEC_KEY: ${{ secrets.BAKERY_MINISIGN_SEC_KEY_PATH }} - run: | - set -euo pipefail - VERSION="${GITHUB_REF_NAME#v}" - PKG_DIR="/srv/breadway-dl/bread-theme/${VERSION}" - if [ -n "${MINISIGN_SEC_KEY:-}" ]; then - minisign -W -S -s "${MINISIGN_SEC_KEY}" -m "${PKG_DIR}/bread-theme-x86_64" \ - -x "${PKG_DIR}/bread-theme-x86_64.minisig" /dev/null || true - ASSETS="${PKG_DIR}/bread-theme-x86_64 ${PKG_DIR}/bread-theme-x86_64.sha256" - [ -f "${PKG_DIR}/bread-theme-x86_64.minisig" ] && ASSETS="${ASSETS} ${PKG_DIR}/bread-theme-x86_64.minisig" - gh release upload "${GITHUB_REF_NAME}" --repo Breadway/bread-ecosystem ${ASSETS} --clobber diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a977bc2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,53 @@ +name: release + +on: + push: + tags: ["v*"] + +permissions: + contents: write + +env: + DL_DIR: /srv/breadway-dl + +jobs: + build: + runs-on: [self-hosted, hestia] + steps: + - uses: actions/checkout@v4 + + - name: build + run: cargo build --release --locked -p bakery + + - name: test + run: cargo test --locked --workspace + + - name: prepare artifacts + run: | + VERSION="${GITHUB_REF_NAME#v}" + PKG_DIR="${DL_DIR}/bakery/${VERSION}" + mkdir -p "${PKG_DIR}" + + cp target/release/bakery "${PKG_DIR}/bakery-x86_64" + strip "${PKG_DIR}/bakery-x86_64" + sha256sum "${PKG_DIR}/bakery-x86_64" | awk '{print $1}' \ + > "${PKG_DIR}/bakery-x86_64.sha256" + + cp bakery.toml "${PKG_DIR}/bakery.toml" + ln -sfn "${VERSION}" "${DL_DIR}/bakery/latest" + + - name: regenerate index.json + run: bash "${GITHUB_WORKSPACE}/scripts/gen-index.sh" + + - name: upload to GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${GITHUB_REF_NAME#v}" + PKG_DIR="${DL_DIR}/bakery/${VERSION}" + gh release create "${GITHUB_REF_NAME}" \ + --title "bakery v${VERSION}" --generate-notes 2>/dev/null || true + gh release upload "${GITHUB_REF_NAME}" \ + "${PKG_DIR}/bakery-x86_64" \ + "${PKG_DIR}/bakery-x86_64.sha256" \ + --clobber diff --git a/.gitignore b/.gitignore index e96063c..b83d222 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1 @@ /target/ - -# minisign secret keys must never be committed — the bakery/index signing -# key lives outside this repo entirely (see scripts/gen-index.sh / -# scripts/get.sh for how it's consumed via MINISIGN_SEC_KEY). -*.minisign-sec -minisign.key - -# Local tool caches — not build output, never belongs in the repo. -# (breadbar already excludes graphify-out; this repo did not, and 111k lines -# of it were swept in by a `git add -A`.) -graphify-out/ -.grok/ diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index c8819c5..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,24 +0,0 @@ -# AGENTS.md — Repo hygiene - -Scope: this file covers *repo hygiene* — branching, remotes, CI, cleanup. It is not project documentation. - -Follow [`CONTRIBUTING.md`](CONTRIBUTING.md) for any git, branch, or release work. Channel/track policy lives in [`docs/release-channels.md`](docs/release-channels.md). The product list is [`registry/bread-ecosystem.toml`](registry/bread-ecosystem.toml) — regenerate the README table with `scripts/gen-readme-products.sh` after editing it. Don't invent a second long-lived branch; there is only `main`. Bakery's package version **must** match `[workspace.package] version` in the root `Cargo.toml` at tag time (`bakery --version` is compiled from that field; `bakery list` reports the git tag) — never push a `v*` tag without bumping Cargo.toml to the same `X.Y.Z`. - -## Remotes -- `origin` — Forgejo (`git.breadway.dev` via Hestia, SSH) — authoritative. -- `github` — GitHub mirror. Push both when publishing. - -## CI -- `.forgejo/workflows/package.yml`, `release-bakery.yml`, `release-bread-theme.yml` all trigger on `push: tags: ['v*']`, gated to skip any tag containing `-rc.` — pushing to `main` doesn't run these. Tag a release to trigger packaging. -- `dev-bakery.yml` / `dev-bread-theme.yml` trigger on `push: branches: ['main']`; `rc-bakery.yml` / `rc-bread-theme.yml` trigger on `push: tags: ['v*']` gated to *only* run for `-rc.` tags — both auto-publish a signed, auto-versioned build to `dl.breadway.dev/{dev,beta}/`. See `docs/release-channels.md` for the full track (stable/beta/dev) policy. -- No build/lint/test CI runs on ordinary commits or PRs to `main` beyond the dev-track workflow above — there's no separate lint/PR-check pipeline. - -## Cleanup -- Delete feature/fix branches (local + remote) once merged. Check with `git branch --merged main`. -- A `fix/audit-findings` branch and a merged `copilot/create-readme-md` branch (both local and on `origin`/`github`) were found stale and fully merged here on 2026-07-21 and removed. - -## Don't -- Don't embed credentials in remote URLs — SSH or a credential helper only. -- Don't flip bakery's default install prefix. System prefix (`/usr/local` via - `/etc/bakery/config.toml` or `BAKERY_PREFIX`) is for BOS; hermes and - `get.sh` stay on `~/.local`. See [`bakery/README.md`](bakery/README.md). diff --git a/BREAD_DESIGN_SYSTEM.md b/BREAD_DESIGN_SYSTEM.md index ae57901..942f7a2 100644 --- a/BREAD_DESIGN_SYSTEM.md +++ b/BREAD_DESIGN_SYSTEM.md @@ -48,27 +48,16 @@ Establish a visual hierarchy with consistent rounding: ## Color System -All projects use **pywal dynamic theming** for accents, layered on a **fixed BOS -dark base** — background, surface, overlay, and foreground never come from -pywal, only the accent slots (color1–6) track the current wallpaper: +All projects use **pywal dynamic theming** with **Catppuccin Mocha** as the fallback palette: -- **Background**: `#0c0c0c` (fixed) -- **Foreground**: `#e8e8e8` (fixed) -- **Surface**: `#1a1a1a` (fixed, `color0`) -- **Overlay**: `#d8d8d8` (fixed, `color7`) -- **Accent**: Dynamic (from pywal `color4`), with curated bread-toned defaults - before any wallpaper has been set - -Without pinning bg/surface/overlay, a light or muddy-toned wallpaper makes -pywal hand back a light or off-hue background, and every bread GUI's panels -inherit it — see `bread-theme/src/palette.rs` for the implementation. +- **Background**: `#1e1e2e` (Catppuccin) +- **Foreground**: `#cdd6f4` (Catppuccin) +- **Surface**: `#181825` (Catppuccin) +- **Accent**: Dynamic (from pywal) Color palette slots (via wal): -- color0–color7: ANSI colors (0 and 7 fixed, 1–6 pywal-derived) +- color0–color7: ANSI colors - Semantic: red, green, yellow, blue, pink, teal -- Computed ink: `on-bg`, `on-surface`, `on-accent`, `on-red`, `on-overlay` — - black or white text, whichever is legible against that background (see - `bread_theme::ink_on`) ## Component Standards @@ -115,9 +104,8 @@ add only app-specific rules: hardcoded Nord palette; migrated to the shared stylesheet). - **breadcrumbs** — CLI tool; ANSI colours only, no GUI styling. -> Palette note: background/surface/overlay/foreground are a fixed BOS dark -> base, never pywal-derived; only the accent slots (color1–6) track the -> current wallpaper via pywal. +> Palette note: the fallback is Catppuccin Mocha, but installs (e.g. BOS) drive +> the real palette from pywal — BOS ships a black-base palette. ## Future Consistency Checks diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 349d06b..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,120 +0,0 @@ -# Contributing - -This repo is a Cargo workspace. Bakery-channel products shipped from here -are `bakery` (the ecosystem package manager) and `bread-theme` (the shared -theming crate). Shared crates that sibling apps pin — not bakery packages -of their own — are `bread-utils`, `bread-app`, `bread-onnx`, -`bread-screenshots`, and `bread-capture`. `bread-polkit` is an in-tree -session agent: it has `bread-polkit/bakery.toml` so it *can* be published, -but it is not in `registry/bread-ecosystem.toml` (unpublished — not on -the bakery index, not on the BOS ISO). Other ecosystem products -(`bread`, `breadbar`, `breadbox`, …) live in their own repos under -`Breadway/` but follow the same workflow described here. The product list -is `registry/bread-ecosystem.toml`. New GTK tools should depend on -`bread-app` instead of copying another app's bootstrap. - -## Branches - -There is one long-lived branch: **`main`**. All day-to-day work lands here. -Every push to `main` automatically builds and publishes a **dev-track** -build for both products (see Tracks below) — use this to test your change -in a real install before cutting anything more formal. - -New work — features and bug fixes alike — goes on a short-lived branch: - -``` -feature/ -fix/ -``` - -Branch off `main`, open a PR/push back into `main` when ready. Short-lived -branches get deleted on merge — they never accumulate the kind of drift a -second long-lived branch does. - -## The release cycle - -There's no separate `beta` or release branch — "stable" and "beta" are both -just **tags** on `main`, not branches that need to be kept in sync: - -1. Work accumulates on `main` via `feature/x` / `fix/x` branches. Each push - auto-publishes a dev build for both `bakery` and `bread-theme` — install - with `bakery track set dev` and `bakery update --all`, then fix anything - broken with another push. -2. When you want to stabilize before a real release, tag a release - candidate: `git tag vX.Y.Z-rc.1 && git push origin vX.Y.Z-rc.1` (push to - both remotes). That tag alone triggers a beta-track build — - "freezing" is just pausing pushes to `main` while you test it, not a - branch operation. Cut `-rc.2`, `-rc.3`, etc. for further fixes. -3. Once an RC has gone without issues, tag the real release: - `git tag vX.Y.Z && git push origin vX.Y.Z` — that's what triggers the - signed stable release build. - -**Version honesty**: bakery's compiled `--version` is -`[workspace.package] version` in the root `Cargo.toml`. The bakery -package version in the index (what `bakery list` shows) is the git tag. -Those must match at tag time — bump `workspace.package.version` to -`X.Y.Z` *before* pushing `vX.Y.Z` or `vX.Y.Z-rc.N`. Never jump a tag -(e.g. `v0.3.1` → `v0.7.1`) without that Cargo.toml bump; the resulting -binary will report the old workspace version while the index claims the -new tag. - -**Note**: `bakery` and `bread-theme` share the same `v*` tag pattern -(both `release-bakery.yml` and `release-bread-theme.yml` trigger on -`tags: ['v*']`, pre-existing behavior this doc isn't changing) — a single -tag push builds and publishes a release for *both* products at once. If -you ever need to release one independently of the other, that's a real gap -worth fixing in the workflow files themselves, not something to work around -by hand. - -## Tracks, from a user's perspective - -``` -bakery track show # what you're currently on (defaults to stable) -bakery track set dev # or beta, or stable -bakery update --all # pull the latest build on your current track -``` - -| Track | What it is | Published from | -|--------|-----------|-----------------| -| `stable` | The last tagged release | a `vX.Y.Z` tag | -| `beta` | Latest release candidate | a `vX.Y.Z-rc.N` tag | -| `dev` | Bleeding edge | `main`, on every push | - -Dev versions are auto-computed (`X.Y.Z-dev.+`) from the -latest published stable tag, so they always sort as newer than what you -have installed — no manual version bumping needed. Beta versions are just -the RC tag itself (already valid semver, already sorts below the real -release it's a candidate for). - -## Local development - -```sh -cargo build --release -p bakery -cargo test --release -p bakery -``` - -`bakery`, `bread-theme`, `bread-utils`, `bread-app`, `bread-polkit`, -`bread-onnx`, `bread-screenshots`, and `bread-capture` are all workspace -members. Run the same commands with `-p bread-theme --bin bread-theme` -for that crate, `-p bread-utils --features bread-client` for the IPC -client, or `-p bread-app --features bread-client` for the GTK bootstrap -helpers. - -## CI - -- `dev-bakery.yml` / `dev-bread-theme.yml` — triggered on push to `main`. -- `rc-bakery.yml` / `rc-bread-theme.yml` — triggered on any `vX.Y.Z-rc.N` - tag push. -- `release-bakery.yml` / `release-bread-theme.yml` — triggered on any other - `v*` tag push, cuts the actual stable release. -- `package.yml` — publishes `bakery` to the `[breadway]` pacman repo, also - tag-triggered. - -All CI runs on a self-hosted runner; nothing runs automatically on plain -commits or PRs beyond the track builds above. See -[`docs/release-channels.md`](docs/release-channels.md) for the full policy, -including how a new product gets wired onto these tracks. - -## Questions - -Open an issue on this repo's Forgejo tracker. diff --git a/Cargo.lock b/Cargo.lock index a9d191d..36707a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,29 +8,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "serde", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -92,43 +69,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.103" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" - -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "async-trait" -version = "0.1.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "autocfg" @@ -138,18 +81,13 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "bakery" -version = "0.7.5" +version = "0.2.3" dependencies = [ "anyhow", - "bread-utils", "chrono", "clap", - "clap_complete", - "dirs 5.0.1", - "fs4", + "dirs", "hex", - "minisign-verify", - "semver", "serde", "serde_json", "sha2", @@ -158,12 +96,6 @@ dependencies = [ "ureq", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.22.1" @@ -172,9 +104,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "block-buffer" @@ -185,109 +117,14 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bread-app" -version = "0.7.5" -dependencies = [ - "bread-utils", -] - -[[package]] -name = "bread-capture" -version = "0.7.5" -dependencies = [ - "anyhow", - "bread-utils", - "clap", - "image", -] - -[[package]] -name = "bread-launcher" -version = "0.7.5" -dependencies = [ - "bread-utils", - "gtk4", - "serde_json", -] - -[[package]] -name = "bread-onnx" -version = "0.7.5" -dependencies = [ - "anyhow", - "bread-utils", - "hex", - "ort", - "sha2", - "tempfile", - "tokenizers", - "tracing", - "ureq", -] - -[[package]] -name = "bread-polkit" -version = "0.7.5" -dependencies = [ - "anyhow", - "bread-app", - "bread-theme", - "gtk4", - "serde", - "tokio", - "tracing", - "tracing-subscriber", - "zbus", -] - -[[package]] -name = "bread-screenshots" -version = "0.7.5" -dependencies = [ - "anyhow", - "bread-utils", - "tracing", -] - -[[package]] -name = "bread-shared" -version = "0.8.0" -source = "git+https://git.breadway.dev/Breadway/bread?tag=v0.8.0#cdd5de8f58e437b3fc6d9b9087eb7b3d0fd09704" -dependencies = [ - "dirs 6.0.0", - "serde", - "serde_json", - "toml 0.8.23", - "uuid", -] - [[package]] name = "bread-theme" -version = "0.7.5" +version = "0.2.3" dependencies = [ - "anyhow", - "dirs 5.0.1", + "dirs", "gtk4", - "libadwaita", "serde", "serde_json", - "toml 0.8.23", - "tracing", -] - -[[package]] -name = "bread-utils" -version = "0.7.5" -dependencies = [ - "bread-shared", - "dirs 5.0.1", - "gtk4", - "gtk4-layer-shell", - "serde", - "serde_json", - "tempfile", - "toml_edit 0.22.27", ] [[package]] @@ -296,24 +133,6 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" -[[package]] -name = "bytemuck" -version = "1.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" - -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - -[[package]] -name = "bytes" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" - [[package]] name = "cairo-rs" version = "0.22.0" @@ -337,20 +156,11 @@ dependencies = [ "system-deps", ] -[[package]] -name = "castaway" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" -dependencies = [ - "rustversion", -] - [[package]] name = "cc" -version = "1.3.0" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "shlex", @@ -387,9 +197,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.2" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd059f9da4f5c36b3787f65d38ccaab1cc315f07b01f89abc8359ee6a8205011" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -397,9 +207,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.2" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -407,15 +217,6 @@ dependencies = [ "strsim", ] -[[package]] -name = "clap_complete" -version = "4.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f84a88507dbd05c695f2cb5e8558e747179134005e9893882dec964190ed89" -dependencies = [ - "clap", -] - [[package]] name = "clap_derive" version = "4.6.1" @@ -425,7 +226,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] @@ -440,33 +241,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" -[[package]] -name = "compact_str" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "rustversion", - "ryu", - "serde", - "static_assertions", -] - -[[package]] -name = "console" -version = "0.16.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" -dependencies = [ - "encode_unicode", - "libc", - "unicode-width", - "windows-sys 0.61.2", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -491,31 +265,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" - [[package]] name = "crypto-common" version = "0.1.7" @@ -526,87 +275,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "daachorse" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f55d7153ba3b507595872a3874803f07a8a81d1e888abed8e5db7da0597d6e2" - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.119", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "dary_heap" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe" -dependencies = [ - "serde", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn 2.0.119", -] - [[package]] name = "digest" version = "0.10.7" @@ -623,16 +291,7 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys 0.5.0", + "dirs-sys", ] [[package]] @@ -643,22 +302,10 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", - "redox_users 0.4.6", + "redox_users", "windows-sys 0.48.0", ] -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users 0.5.2", - "windows-sys 0.61.2", -] - [[package]] name = "displaydoc" version = "0.2.6" @@ -667,46 +314,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", -] - -[[package]] -name = "either" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" - -[[package]] -name = "encode_unicode" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" - -[[package]] -name = "endi" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" - -[[package]] -name = "enumflags2" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "syn", ] [[package]] @@ -725,50 +333,12 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "esaxx-rs" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" -dependencies = [ - "cc", -] - -[[package]] -name = "event-listener" -version = "5.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" -dependencies = [ - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] - [[package]] name = "fastrand" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - [[package]] name = "field-offset" version = "0.3.6" @@ -796,10 +366,10 @@ dependencies = [ ] [[package]] -name = "fnv" -version = "1.0.7" +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -810,36 +380,26 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs4" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e180ac76c23b45e767bd7ae9579bc0bb458618c4bc71835926e098e61d15f8" -dependencies = [ - "rustix 0.38.44", - "windows-sys 0.52.0", -] - [[package]] name = "futures-channel" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -848,45 +408,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a" - -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] name = "futures-task" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.33" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-core", "futures-macro", @@ -922,15 +469,14 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.11.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d81e2a6c6ecba2aab60633a98df1868b03fa0bfdce8105edc27c1bccf71f0e39" +checksum = "fd42fdbbf48612c6e8f47c65fb92d2e8f39c25aecd6af047e83897c1a22d2a4e" dependencies = [ "cairo-rs", "gdk-pixbuf", "gdk4-sys", "gio", - "gl", "glib", "libc", "pango", @@ -938,9 +484,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.11.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d8f608d8d7d229975c4d0d026f5d3071598c4ddab3c5262b0a31840fec78d13" +checksum = "9d974ac4f15e67472c3a9728daf612590b4a5762a4b33f0edd298df0b80d043c" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -976,32 +522,22 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.4" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi 5.3.0", + "r-efi", "wasip2", -] - -[[package]] -name = "getrandom" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", + "wasip3", ] [[package]] name = "gio" -version = "0.22.8" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b3e1f669909c326b9413bde5a742097b8c90a7d78f45326db13668984769ded" +checksum = "e3848bcba3a35cc0a71df8ba8ecfd799d6bfb862342a53a4a915fb62213aa4e6" dependencies = [ "futures-channel", "futures-core", @@ -1016,9 +552,9 @@ dependencies = [ [[package]] name = "gio-sys" -version = "0.22.8" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353fdc7da7cd16da916104b1e0e4e7de380ec9c8aaa20d4d742d66310ab4b0d5" +checksum = "64729ba2772c080448f9f966dba8f4456beeb100d8c28a865ef8a0f2ef4987e1" dependencies = [ "glib-sys", "gobject-sys", @@ -1027,31 +563,11 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "gl" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a94edab108827d67608095e269cf862e60d920f144a5026d3dbcfd8b877fb404" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - [[package]] name = "glib" -version = "0.22.8" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddbcf514bd1881fc1b960e4e52b4e82873f4da3bceddbd58d42827b508888100" +checksum = "c207e04e51605dcf7b2924c41591b3a10e1438eaac5bcf448fb91f325381104a" dependencies = [ "bitflags", "futures-channel", @@ -1077,14 +593,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] name = "glib-sys" -version = "0.22.8" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030967459f9f676851872c6304adea7825c6d462ec9b72554c733cf0c5952233" +checksum = "5f7fbac234ed5bc2a28359b7bde8e1b9cdf1441cc2d7f068e4824672d7db9445" dependencies = [ "libc", "system-deps", @@ -1103,30 +619,32 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.22.8" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb856b9c558971c3f13ab692358926da710b046932a4e087aedcc35b040d7dff" +checksum = "c7d1b7881f96869f49808b6adfe906a93a57a34204952253444d68c3208d71f1" dependencies = [ "glib", "graphene-sys", + "libc", ] [[package]] name = "graphene-sys" -version = "0.22.8" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ffdfde88f3570d3705e0d8a2433e036d387a1f2930bbf47eafcb5f569fd04" +checksum = "517f062f3fd6b7fd3e57a3f038a74b3c23ca32f51199ff028aa704609943f79c" dependencies = [ "glib-sys", "libc", + "pkg-config", "system-deps", ] [[package]] name = "gsk4" -version = "0.11.4" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b867be1c5f14dcb8f552c0eff6e9a9b1da5f8b43943e8efc3a63c889d84952ff" +checksum = "53c912dfcbd28acace5fc99c40bb9f25e1dcb73efb1f2608327f66a99acdcb62" dependencies = [ "cairo-rs", "gdk4", @@ -1139,9 +657,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.11.4" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7c7eb2e681ee896646cfb8872b431f24d09f53ba9283289d9b10caa6707088" +checksum = "d7d54bbc7a9d8b6ffe4f0c95eede15ccfb365c8bf521275abe6bcfb57b18fb8a" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -1155,9 +673,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.11.4" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a0a0466484f64b07b5b8184d43fa46be78eb0b8e04ae4e179af31d770b76d9" +checksum = "7181b837f04cbe93f79441475f7a00560a92cba7a72e38cc1a68b6f8b78eaae2" dependencies = [ "cairo-rs", "field-offset", @@ -1174,51 +692,23 @@ dependencies = [ "pango", ] -[[package]] -name = "gtk4-layer-shell" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4069987ff4793699511a251028cc336b438e46565b463f111250148d574752a" -dependencies = [ - "bitflags", - "gdk4", - "glib", - "glib-sys", - "gtk4", - "gtk4-layer-shell-sys", - "libc", -] - -[[package]] -name = "gtk4-layer-shell-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f566a5ec5bcc454e7fcf2ab76930887ced5365afce12c1e5201bb296b95f1b9" -dependencies = [ - "gdk4-sys", - "glib-sys", - "gtk4-sys", - "libc", - "system-deps", -] - [[package]] name = "gtk4-macros" -version = "0.11.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac7179400a36a04de039c24206bb841c5596992b907b43b23ee8d5bdc40d00e" +checksum = "3581b242ba62fdff122ebb626ea641582ec326031622bd19d60f85029c804a87" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] name = "gtk4-sys" -version = "0.11.4" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f954786af0b1984425c4446b77f5ff6594346181316be3f850caab1c6f01" +checksum = "20ba8e695e2640455561274e65e45f0a151619e450746007667f4b23ceae4e1b" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1233,6 +723,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -1358,10 +857,10 @@ dependencies = [ ] [[package]] -name = "ident_case" -version = "1.0.1" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "idna" @@ -1384,19 +883,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", -] - [[package]] name = "indexmap" version = "2.14.0" @@ -1404,20 +890,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown", -] - -[[package]] -name = "indicatif" -version = "0.18.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" -dependencies = [ - "console", - "portable-atomic", - "unicode-width", - "unit-prefix", - "web-time", + "hashbrown 0.17.1", + "serde", + "serde_core", ] [[package]] @@ -1426,15 +901,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.18" @@ -1443,56 +909,21 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ "cfg-if", "futures-util", + "once_cell", "wasm-bindgen", ] [[package]] -name = "khronos_api" -version = "3.1.0" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libadwaita" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b9900e67182a4b5b1f157b448d94f0715c8b9770cce21cf000801917f53bfa" -dependencies = [ - "gdk4", - "gio", - "glib", - "gtk4", - "libadwaita-sys", - "pango", -] - -[[package]] -name = "libadwaita-sys" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3c27642b389852aa99341bd4a4c19ec6f8a2b63ebdd7f5ba1952198079ccd" -dependencies = [ - "gdk4-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "gtk4-sys", - "libc", - "pango-sys", - "system-deps", -] +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" @@ -1500,31 +931,15 @@ version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" -[[package]] -name = "libloading" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" -dependencies = [ - "cfg-if", - "windows-link", -] - [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ "libc", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -1539,50 +954,15 @@ checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "log" -version = "0.4.33" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" - -[[package]] -name = "macro_rules_attribute" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520" -dependencies = [ - "macro_rules_attribute-proc_macro", - "paste", -] - -[[package]] -name = "macro_rules_attribute-proc_macro" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matrixmultiply" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f607c237553f086e7043417a51df26b2eb899d3caff94e6a67592ff992fedc7" -dependencies = [ - "autocfg", - "rawpointer", -] +checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" [[package]] name = "memchr" -version = "2.8.3" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memoffset" @@ -1593,18 +973,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "minisign-verify" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f9645cb765ea72b8111f36c522475d2daa0d22c957a9826437e97534bc4e9e" - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1615,92 +983,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "mio" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "monostate" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3341a273f6c9d5bef1908f17b7267bbab0e95c9bf69a0d4dcf8e9e1b2c76ef67" -dependencies = [ - "monostate-impl", - "serde", - "serde_core", -] - -[[package]] -name = "monostate-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "ndarray" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "portable-atomic", - "portable-atomic-util", - "rawpointer", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1722,71 +1004,21 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "onig" -version = "6.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2" -dependencies = [ - "bitflags", - "libc", - "once_cell", - "onig_sys", -] - -[[package]] -name = "onig_sys" -version = "69.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e68317604e77e53b85896388e1a803c1d21b74c899ec9e5e1112db90735edd7" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "ort" -version = "2.0.0-rc.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7de3af33d24a745ffb8fab904b13478438d1cd52868e6f17735ef6e1f8bf133" -dependencies = [ - "libloading", - "ndarray", - "ort-sys", - "smallvec", - "tracing", -] - -[[package]] -name = "ort-sys" -version = "2.0.0-rc.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b497d21a8b6fbb4b5a544f8fadb77e801a09ae0add9e411d31c6f89e3c1e90" - [[package]] name = "pango" -version = "0.22.8" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d800d8d0de2ad5d0fb046f5344dbaba14a003cf3dd27cc21d85893d35ea316c" +checksum = "251bdc6e6487b811be0e406a21e301e07e45c0aa8fa39e00c0c8e12a91752438" dependencies = [ "gio", "glib", + "libc", "pango-sys", ] @@ -1802,18 +1034,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "percent-encoding" version = "2.3.2" @@ -1832,34 +1052,6 @@ version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "portable-atomic" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" - -[[package]] -name = "portable-atomic-util" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" -dependencies = [ - "portable-atomic", -] - [[package]] name = "potential_utf" version = "0.1.5" @@ -1870,12 +1062,13 @@ dependencies = [ ] [[package]] -name = "ppv-lite86" -version = "0.2.21" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "zerocopy", + "proc-macro2", + "syn", ] [[package]] @@ -1884,7 +1077,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.13+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -1896,99 +1089,21 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "pxfm" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" - [[package]] name = "quote" -version = "1.0.46" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" -[[package]] -name = "rand" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-cond" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f" -dependencies = [ - "either", - "itertools", - "rayon", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "redox_users" version = "0.4.6" @@ -1997,49 +1112,9 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 1.0.69", + "thiserror", ] -[[package]] -name = "redox_users" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" -dependencies = [ - "getrandom 0.2.17", - "libredox", - "thiserror 2.0.18", -] - -[[package]] -name = "regex" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" - [[package]] name = "ring" version = "0.17.14" @@ -2063,19 +1138,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", -] - [[package]] name = "rustix" version = "1.1.4" @@ -2085,15 +1147,15 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.12.1", + "linux-raw-sys", "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.42" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "log", "once_cell", @@ -2106,9 +1168,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "zeroize", ] @@ -2126,15 +1188,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.23" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" - -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "semver" @@ -2169,7 +1225,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] @@ -2185,17 +1241,6 @@ dependencies = [ "zmij", ] -[[package]] -name = "serde_repr" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] - [[package]] name = "serde_spanned" version = "0.6.9" @@ -2225,36 +1270,17 @@ dependencies = [ "digest", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - [[package]] name = "simd-adler32" -version = "0.3.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "slab" @@ -2264,31 +1290,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" - -[[package]] -name = "socket2" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "spm_precompiled" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326" -dependencies = [ - "base64 0.13.1", - "nom", - "serde", - "unicode-segmentation", -] +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "stable_deref_trait" @@ -2296,12 +1300,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.11.1" @@ -2316,20 +1314,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.119" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2344,7 +1331,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] @@ -2356,7 +1343,7 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 1.1.3+spec-1.1.0", + "toml 1.1.2+spec-1.1.0", "version-compare", ] @@ -2373,9 +1360,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom 0.4.2", "once_cell", - "rustix 1.1.4", + "rustix", "windows-sys 0.61.2", ] @@ -2385,16 +1372,7 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl", ] [[package]] @@ -2405,27 +1383,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "thread_local" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" -dependencies = [ - "cfg-if", + "syn", ] [[package]] @@ -2438,68 +1396,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tokenizers" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44e5bea67576e04b6ff8564c5d9e09c2ef0cf476502245f2f120e497769d3112" -dependencies = [ - "ahash", - "compact_str", - "daachorse", - "dary_heap", - "derive_builder", - "esaxx-rs", - "getrandom 0.3.4", - "indicatif", - "itertools", - "log", - "macro_rules_attribute", - "monostate", - "onig", - "paste", - "rand", - "rayon", - "rayon-cond", - "regex", - "regex-syntax", - "serde", - "serde_json", - "spm_precompiled", - "thiserror 2.0.18", - "unicode-normalization-alignments", - "unicode-segmentation", - "unicode_categories", -] - -[[package]] -name = "tokio" -version = "1.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" -dependencies = [ - "bytes", - "libc", - "mio", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "tracing", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.3", -] - [[package]] name = "toml" version = "0.8.23" @@ -2514,9 +1410,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.3+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", "serde_core", @@ -2524,7 +1420,7 @@ dependencies = [ "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] @@ -2561,14 +1457,14 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] @@ -2577,7 +1473,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.4", + "winnow 1.0.3", ] [[package]] @@ -2588,55 +1484,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.2+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" -dependencies = [ - "matchers", - "once_cell", - "regex-automata", - "sharded-slab", - "thread_local", - "tracing", - "tracing-core", -] +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "typenum" @@ -2644,17 +1494,6 @@ version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" -[[package]] -name = "uds_windows" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" -dependencies = [ - "memoffset", - "tempfile", - "windows-sys 0.61.2", -] - [[package]] name = "unicode-ident" version = "1.0.24" @@ -2662,37 +1501,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] -name = "unicode-normalization-alignments" -version = "0.1.12" +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de" -dependencies = [ - "smallvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "unit-prefix" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "untrusted" @@ -2706,7 +1518,7 @@ version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ - "base64 0.22.1", + "base64", "flate2", "log", "once_cell", @@ -2742,18 +1554,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "uuid" -version = "1.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9" -dependencies = [ - "getrandom 0.4.3", - "js-sys", - "serde_core", - "wasm-bindgen", -] - [[package]] name = "version-compare" version = "0.2.1" @@ -2774,18 +1574,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.4+wasi-0.2.12" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -2796,9 +1605,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2806,34 +1615,58 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] [[package]] -name = "web-time" -version = "1.1.0" +name = "wasm-encoder" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" dependencies = [ - "js-sys", - "wasm-bindgen", + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", ] [[package]] @@ -2842,14 +1675,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.9", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -2875,7 +1708,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] @@ -2886,7 +1719,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] @@ -3072,31 +1905,113 @@ dependencies = [ [[package]] name = "winnow" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "writeable" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" -[[package]] -name = "xml-rs" -version = "0.8.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" - [[package]] name = "yoke" version = "0.8.3" @@ -3116,95 +2031,10 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", "synstructure", ] -[[package]] -name = "zbus" -version = "5.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db4be7c075cb421e4b7ee645541604239bd243ba7c357511f4ff3a74b555907" -dependencies = [ - "async-broadcast", - "async-recursion", - "async-trait", - "enumflags2", - "event-listener", - "futures-core", - "futures-lite", - "hex", - "libc", - "ordered-stream", - "rustix 1.1.4", - "serde", - "serde_repr", - "tokio", - "tracing", - "uds_windows", - "uuid", - "windows-sys 0.61.2", - "winnow 1.0.4", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "5.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2990635d09ade6df1868f72f8cac69a876a90981e8bd3c40b1be413f8dc88f40" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 3.0.3", - "zbus_names", - "zvariant", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "4.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e" -dependencies = [ - "serde", - "winnow 1.0.4", - "zvariant", -] - -[[package]] -name = "zcheapstr" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1afec51604565183aeb5c54c20aeab286120d4e4460f7f76e3e8bb8c0d99473" -dependencies = [ - "serde", -] - -[[package]] -name = "zerocopy" -version = "0.8.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "zerofrom" version = "0.1.8" @@ -3222,15 +2052,15 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", "synstructure", ] [[package]] name = "zeroize" -version = "1.9.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" @@ -3262,52 +2092,11 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn", ] [[package]] name = "zmij" -version = "1.0.23" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" - -[[package]] -name = "zvariant" -version = "5.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e28c25bd8bb8da5a1f3e7065d0c156b9ee9a7973adf78b0e35eaefdf3b1b5c" -dependencies = [ - "endi", - "enumflags2", - "serde", - "winnow 1.0.4", - "zcheapstr", - "zvariant_derive", - "zvariant_utils", -] - -[[package]] -name = "zvariant_derive" -version = "5.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d496a145685283b67e232bd9e47377f6b60ad9d51e3601b23867f77c42477f96" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 3.0.3", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629d80ece222cad20fe0e8741be493c4ab166acf3b85341bdc2cdbcfd8f3c2d6" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn 3.0.3", - "winnow 1.0.4", -] +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index 183d182..354c58c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [workspace] -members = ["bakery", "bread-theme", "bread-utils", "bread-onnx", "bread-screenshots", "bread-capture", "bread-app", "bread-polkit", "bread-launcher"] +members = ["bakery", "bread-theme"] resolver = "2" [workspace.package] -version = "0.7.5" +version = "0.2.3" edition = "2021" license = "MIT" -authors = ["Breadway "] +authors = ["Breadway "] [workspace.dependencies] anyhow = "1" @@ -19,9 +19,6 @@ sha2 = "0.10" hex = "0.4" clap = { version = "4", features = ["derive", "env"] } chrono = "0.4" -minisign-verify = "0.2" -tracing = "0.1" -semver = "1" [profile.release] lto = "thin" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 373e4ee..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 Breadway - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index 927c629..1ec4cff 100644 --- a/README.md +++ b/README.md @@ -4,36 +4,19 @@ A collection of Rust tools for the Linux desktop (Hyprland / Wayland / Arch). Install any product with a single command — no Rust toolchain required. ```sh -curl -fsSL https://get.breadway.dev | sh +curl https://breadway.dev/get | sh bakery install breadbar ``` ## Products -The table below is generated from [`registry/bread-ecosystem.toml`](registry/bread-ecosystem.toml). Regenerate with `scripts/gen-readme-products.sh`. - - - | Package | Description | |---------|-------------| -| `bakery` | Bread ecosystem package manager | -| `bread-theme` | Shared pywal-accented, fixed-dark-base theming CLI for the bread ecosystem | -| `bread` | Reactive automation daemon and CLI for Linux desktops | -| `breadbar` | Minimal status bar and notification daemon for Hyprland | -| `breadbox` | App launcher for Hyprland / Wayland | -| `breadcrumbs` | Profile-aware Wi-Fi state machine with Tailscale integration | -| `breadpad` | Quick-capture scratchpad and note viewer with AI classification | -| `breadpaper` | Wallpaper manager for the bread desktop | -| `breadmon` | Terminal UI monitor manager for Hyprland | -| `breadsearch` | Semantic system-wide search for BOS | -| `breadclip` | Wayland clipboard history manager for Hyprland | -| `breadshot` | Screenshot utility for the bread ecosystem | -| `bos-settings` | System settings app for Bread OS | -| `breadhelp` | Onboarding and help center for Bread OS | -| `breadcast` | Cast your screen to any Chromecast/Google TV or DLNA renderer — daemon + GTK4 popup — Bakery product; not included in the BOS ISO | -| `breadarr` | Single-daemon Sonarr+Radarr+Prowlarr replacement — release watching, matching, grabbing, importing, and a terminal UI, no web UI — Homelab, not shipped on BOS | - - +| `bread` | Reactive automation daemon (`breadd`) + CLI — Lua scripting over Hyprland, udev, power, network, and Bluetooth events | +| `breadbar` | GTK4 status bar (workspaces, clock, CPU/RAM/battery/WiFi/Bluetooth) and D-Bus notification daemon for Hyprland | +| `breadbox` | GTK4 fuzzy app launcher for Hyprland with context-aware sorting; ships an icon-sync daemon (`breadbox-sync`) | +| `breadcrumbs` | Profile-aware Wi-Fi state machine with Tailscale exit-node management and a self-healing watch daemon | +| `breadpad` | Quick-capture scratchpad popup with AI-powered note classification, reminders, recurrence, and a full note viewer (`breadman`) | ## Recommended keybinds @@ -52,31 +35,17 @@ to keys. ## Theming -All GUI products (breadbar, breadbox, breadpad) share one stylesheet via -`bread-theme`. Background, surface, overlay, and foreground are always BOS's -fixed dark values; only the accent colors are read from the pywal palette in -`~/.cache/wal/colors.json`. When that file is absent, the accents fall back -to BOS's curated bread-toned defaults (not Catppuccin Mocha). The stylesheet -is written to `$XDG_RUNTIME_DIR/bread/theme.css`; running apps watch that -file and recolour live when it changes. Per-app CSS overrides live at -`~/.config//style.css`. +All GUIs share one look via `bread-theme`. The `bread-theme` CLI renders the +component stylesheet from your pywal palette (Catppuccin Mocha fallback) to +`$XDG_RUNTIME_DIR/bread/theme.css`; every app loads that file and **live-reloads** +it, so changing your wallpaper recolours the whole ecosystem with no rebuilds: ```sh wal -i ~/Pictures/wall.png # regenerate pywal palette bread-theme generate # render the shared stylesheet (run from a wal hook) ``` -`bread-theme` subcommands: - -| Subcommand | Description | -|------------|-------------| -| `generate` | Render the current palette and write the shared stylesheet (default) | -| `reload` | Same as `generate`; use after a palette change to trigger live recolour in running apps | -| `path` | Print the stylesheet path | -| `print` | Render the stylesheet to stdout without writing | - -The shared theming logic lives in the `bread-theme` crate in this repo. See -[`BREAD_DESIGN_SYSTEM.md`](BREAD_DESIGN_SYSTEM.md) for the design tokens (fonts, +See [`BREAD_DESIGN_SYSTEM.md`](BREAD_DESIGN_SYSTEM.md) for the tokens (fonts, spacing, radii, colour roles) the stylesheet is built from. ## Installing bakery @@ -84,7 +53,9 @@ spacing, radii, colour roles) the stylesheet is built from. `bakery` is the package manager for the ecosystem. Install it with the bootstrap script: ```sh -curl -fsSL https://get.breadway.dev | sh +curl https://breadway.dev/get | sh +# or +curl -sSfL https://get.breadway.dev | sh ``` The script downloads the prebuilt `bakery` binary to `~/.local/bin/bakery` and prints a note if that directory isn't on your `PATH` yet. @@ -106,26 +77,6 @@ bakery remove # remove a package (data files are never deleted) `bakery install` runs `doctor` first and bails with a clear message if any system dependency is missing. Binaries land in `~/.local/bin` (override with `BAKERY_BIN_DIR`). -## System prefix (BOS) - -Default install root is `~/.local`. BOS sets a system prefix so bakery-managed -desktop apps live on the `@` root subvolume and ride along with -snapper/grub-btrfs snapshots: - -```toml -# /etc/bakery/config.toml -prefix = "/usr/local" -``` - -`BAKERY_PREFIX` overrides the config file. A non-home prefix installs bins to -`$prefix/bin`, share/data/desktop/licenses to `$prefix/share/...`, and systemd -user units to `/usr/lib/systemd/user`. Per-user state (`installed.json`, -update backups) stays in `~/.local/state/bakery`. Writes that need root use -`sudo -n`, then `pkexec`. `bakery doctor` prints the active prefix. - -Hermes and `get.sh` are unchanged — they keep the user-local default. See -[`bakery/README.md`](bakery/README.md). - ## System dependencies by product `bakery doctor` checks these automatically before any install. Required deps block installation; optional deps generate a warning but never block. @@ -141,68 +92,32 @@ Hermes and `get.sh` are unchanged — they keep the user-local default. See Install all required deps with `sudo pacman -S `. Use `pacman -Q ` to check whether any are already present. +## Theming + +All GUI products (breadbar, breadbox, breadpad) read pywal colors from +`~/.cache/wal/colors.json` and fall back to Catppuccin Mocha when that file +is absent. Per-app CSS overrides live at `~/.config//style.css`. + +The shared theming logic lives in the `bread-theme` crate in this repo. + ## Workspace -This repo is a Cargo workspace. Bakery-channel products shipped from here -are `bakery` and `bread-theme`; the other members are shared crates sibling -apps pin, or in-tree tools that are not bakery packages of their own. +This repo is a Cargo workspace: ``` bread-ecosystem/ -├── bakery/ # package manager binary -├── bread-theme/ # shared pywal + fixed-dark-base theming crate -├── bread-utils/ # shared plumbing (Hyprland IPC, singleton, XDG, BreadClient, …) -├── bread-app/ # GTK bootstrap new tools should use (app id, singleton, overlay, command listen) -├── bread-polkit/ # themed PolicyKit agent (bakery.toml present; unpublished) -├── bread-onnx/ # shared ONNX runtime helpers -├── bread-screenshots/ # grim capture primitive used by app `--screenshot` modes -├── bread-capture/ # orchestrator that drives those `--screenshot` modes -├── registry/ # bread-ecosystem.toml — product registry +├── bakery/ # package manager binary +├── bread-theme/ # shared pywal + Catppuccin theming crate +├── registry/ # bread-ecosystem.toml — product registry └── scripts/ - ├── get.sh # curl | sh bootstrap - ├── gen-index.sh # generates dl.breadway.dev/index.json from release artifacts - └── gen-readme-products.sh # rewrites the Products table from the registry -``` - -### New GTK tools - -Do not copy another app's `main.rs`. Depend on `bread-app`: - -- `bread_app::application_id` / `try_acquire` / `toggle_or_kill` for the - `com.breadway.*` application id and single-instance lock -- feature `gtk` re-exports `bread_utils::gtk_popup` (layer-shell overlay) -- feature `bread-client` for `listen_commands` on `bread.command..**` - -See the `bread-app` crate docs. Existing apps are not migrated in this -tree; `bread-polkit` is the first in-tree consumer. - -### bread-polkit - -A session PolicyKit authentication agent (password prompt, cancel, -identity). Not a wrapper around `polkit-gnome`. `bread-polkit/bakery.toml` -exists so it can be published via bakery; it is not in -`registry/bread-ecosystem.toml` and is therefore unpublished — not on the -bakery index and not on the BOS ISO lockfile. - -```sh -cargo run -p bread-polkit -``` - -Autostart — pick one: - -```sh -cp bread-polkit/contrib/bread-polkit.desktop ~/.config/autostart/ -``` - -``` -# hyprland.conf -exec-once = bread-polkit + ├── get.sh # curl | sh bootstrap + └── gen-index.sh # generates dl.breadway.dev/index.json from release artifacts ``` ## Release pipeline -Each product repo (`Breadway/bread`, `Breadway/breadbar`, …) has -`.forgejo/workflows/release-*.yml` that triggers on `v*` tags. The workflow +Each product repo (`Breadway/bread`, `Breadway/breadbar`, …) has a +`.github/workflows/release.yml` that triggers on `v*` tags. The workflow runs on a self-hosted runner on hestia, builds a stripped x86_64 binary, deposits it at `dl.breadway.dev///`, updates `index.json`, and mirrors the binary to GitHub Releases as a fallback. @@ -210,12 +125,6 @@ and mirrors the binary to GitHub Releases as a fallback. `bakery` always tries `dl.breadway.dev` first and transparently falls back to the GitHub Release URL recorded in the manifest. -Beyond stable releases, most products also publish **dev** and **beta** -tracks — continuous builds off `main` (dev) and `vX.Y.Z-rc.N` tags (beta). -See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the branch/release workflow and -[`docs/release-channels.md`](docs/release-channels.md) for the full track -policy. Switch tracks with `bakery track set `. - ### Release artifact contract Each product's `release.yml` **must** upload the following files alongside diff --git a/bakery/Cargo.toml b/bakery/Cargo.toml index 06ca297..df5b7c1 100644 --- a/bakery/Cargo.toml +++ b/bakery/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true description = "Package manager for the bread ecosystem" -repository = "https://git.breadway.dev/Breadway/bread-ecosystem" +repository = "https://github.com/Breadway/bread-ecosystem" [dependencies] anyhow = { workspace = true } @@ -17,10 +17,7 @@ ureq = { workspace = true } sha2 = { workspace = true } hex = { workspace = true } clap = { workspace = true } -clap_complete = "4" chrono = { workspace = true } -minisign-verify = { workspace = true } -semver = { workspace = true } -bread-utils = { path = "../bread-utils" } -fs4 = { version = "0.8", features = ["sync"] } + +[dev-dependencies] tempfile = "3" diff --git a/bakery/README.md b/bakery/README.md deleted file mode 100644 index 21cb2cd..0000000 --- a/bakery/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# bakery - -Package manager for the bread ecosystem. Usage lives in the -[repo README](../README.md). - -## Install prefix - -Default root is `~/.local` (bins in `~/.local/bin`, data in -`~/.local/share`). That is the hermes / `get.sh` path and must stay the -default. - -BOS sets a system prefix so bakery-managed desktop apps live on the `@` -root subvolume and are included in snapper/grub-btrfs snapshots: - -```toml -# /etc/bakery/config.toml -prefix = "/usr/local" -``` - -`BAKERY_PREFIX` overrides the config file. A non-home prefix installs: - -| Thing | Path | -|-------|------| -| bins | `$prefix/bin` | -| share / desktop / licenses / data | `$prefix/share/...` | -| systemd user units | `/usr/lib/systemd/user` | - -Per-user state (`installed.json` and pre-update backups) stays in -`~/.local/state/bakery`. Writes that need root use `sudo -n`, then -`pkexec`. `bakery doctor` prints the active prefix. diff --git a/bakery/src/doctor.rs b/bakery/src/doctor.rs index f4ef71b..0a7194b 100644 --- a/bakery/src/doctor.rs +++ b/bakery/src/doctor.rs @@ -1,4 +1,3 @@ -use crate::ui; use anyhow::Result; use std::process::Command; @@ -11,48 +10,18 @@ pub struct DepReport { pub fn check_deps(required: &[String], optional: &[String]) -> Result { Ok(DepReport { - missing: required - .iter() - .filter(|d| !dep_present(d)) - .cloned() - .collect(), - warnings: optional - .iter() - .filter(|d| !dep_present(d)) - .cloned() - .collect(), + missing: required.iter().filter(|d| !dep_present(d)).cloned().collect(), + warnings: optional.iter().filter(|d| !dep_present(d)).cloned().collect(), }) } -/// Arch package name -> Debian/Ubuntu package name, for the few cases where -/// they differ *and* the Debian package's own binaries don't share a name -/// with either package (so `path_has` can't bridge the gap the way it -/// already does for e.g. `ffmpeg`/`openssl`, whose package name matches -/// their own binary name on both distros). `system_deps` in `bakery.toml` -/// is always written as the Arch name — this is what makes that same -/// declaration also resolve correctly on a Debian-family bakery host like -/// hestia. -const ARCH_TO_DEBIAN_PKG: &[(&str, &str)] = &[("mkvtoolnix-cli", "mkvtoolnix")]; - -fn debian_name(pkg: &str) -> &str { - ARCH_TO_DEBIAN_PKG - .iter() - .find(|(arch, _)| *arch == pkg) - .map(|(_, debian)| *debian) - .unwrap_or(pkg) -} - fn dep_present(pkg: &str) -> bool { // Primary: `pacman -Q` uses the exact Arch package name — no name mapping needed. if pacman_installed(pkg) { return true; } // Fallback for environments without pacman: native PATH search then pkg-config. - if path_has(pkg) || pkg_config_exists(pkg) { - return true; - } - // Further fallback for Debian/Ubuntu hosts: dpkg, via the name map above. - dpkg_installed(debian_name(pkg)) + path_has(pkg) || pkg_config_exists(pkg) } fn pacman_installed(pkg: &str) -> bool { @@ -63,17 +32,6 @@ fn pacman_installed(pkg: &str) -> bool { .unwrap_or(false) } -fn dpkg_installed(pkg: &str) -> bool { - Command::new("dpkg-query") - .args(["-W", "-f=${Status}", pkg]) - .output() - .map(|o| { - o.status.success() - && String::from_utf8_lossy(&o.stdout).contains("install ok installed") - }) - .unwrap_or(false) -} - /// Check PATH without shelling out to `which` (avoids the external dependency). fn path_has(bin: &str) -> bool { std::env::var_os("PATH") @@ -90,75 +48,34 @@ fn pkg_config_exists(lib: &str) -> bool { .unwrap_or(false) } -/// Builds the "install with: ..." hint for a list of missing Arch package -/// names, picking the command for whichever package manager is actually on -/// this host — `sudo pacman -S ...` is meaningless advice on a Debian-family -/// bakery host like hestia, which has neither `pacman` nor the Arch names. -pub fn install_hint(missing: &[String]) -> String { - if path_has("pacman") { - format!("sudo pacman -S {}", missing.join(" ")) - } else if path_has("apt") { - let names: Vec<&str> = missing.iter().map(|p| debian_name(p)).collect(); - format!("sudo apt install {}", names.join(" ")) - } else { - format!("install: {}", missing.join(", ")) - } -} - /// Print a formatted doctor report for a package's system deps. /// Returns true if all *required* deps are satisfied. -pub fn report( - package_name: &str, - required: &[String], - optional: &[String], - name_width: usize, -) -> bool { +pub fn report(package_name: &str, required: &[String], optional: &[String]) -> bool { if required.is_empty() && optional.is_empty() { - ui::check_row(true, package_name, name_width, "no system deps required"); + println!(" {package_name}: no system deps required"); return true; } match check_deps(required, optional) { Err(e) => { - ui::check_row( - false, - package_name, - name_width, - &format!("error running doctor: {e}"), - ); + eprintln!(" error running doctor for {package_name}: {e}"); false } Ok(rep) => { for warn in &rep.warnings { eprintln!( - " {}", - ui::style( - &format!( - "{package_name}: optional dep not found: {warn} \ - (install for full functionality)" - ), - ui::YELLOW - ) + " {package_name}: optional dep not found: {warn} \ + (install for full functionality)" ); } if rep.missing.is_empty() { - ui::check_row( - true, - package_name, - name_width, - "all required system deps satisfied", - ); + println!(" {package_name}: all required system deps satisfied"); true } else { - ui::check_row( - false, - package_name, - name_width, - &format!("missing: {}", rep.missing.join(", ")), - ); eprintln!( - " {}", - ui::dim(&format!("install with: {}", install_hint(&rep.missing))) + " {package_name}: missing system deps: {}", + rep.missing.join(", ") ); + eprintln!(" install with: sudo pacman -S {}", rep.missing.join(" ")); false } } @@ -188,38 +105,24 @@ mod tests { assert!(path_has("sh")); } - #[test] - fn debian_name_maps_known_alias() { - assert_eq!(debian_name("mkvtoolnix-cli"), "mkvtoolnix"); - } - - #[test] - fn debian_name_passes_through_unmapped() { - assert_eq!(debian_name("ffmpeg"), "ffmpeg"); - } - - // This test only runs on systems with dpkg (Debian/Ubuntu). - #[test] - #[ignore] - fn dpkg_finds_dpkg_itself() { - assert!(dpkg_installed("dpkg")); - } - - #[test] - fn dpkg_missing_package_not_present() { - assert!(!dpkg_installed("this-package-does-not-exist-xyzzy42")); - } - #[test] fn missing_required_dep_detected() { - let rep = check_deps(&["this-package-does-not-exist-xyzzy42".to_string()], &[]).unwrap(); + let rep = check_deps( + &["this-package-does-not-exist-xyzzy42".to_string()], + &[], + ) + .unwrap(); assert_eq!(rep.missing.len(), 1); assert!(rep.warnings.is_empty()); } #[test] fn missing_optional_dep_becomes_warning_not_error() { - let rep = check_deps(&[], &["this-package-does-not-exist-xyzzy42".to_string()]).unwrap(); + let rep = check_deps( + &[], + &["this-package-does-not-exist-xyzzy42".to_string()], + ) + .unwrap(); assert!(rep.missing.is_empty()); assert_eq!(rep.warnings.len(), 1); } diff --git a/bakery/src/download.rs b/bakery/src/download.rs index 4d1c1c7..c89744c 100644 --- a/bakery/src/download.rs +++ b/bakery/src/download.rs @@ -3,38 +3,36 @@ use sha2::{Digest, Sha256}; use std::path::Path; use crate::manifest::{fetch_binary, Binary}; -use crate::ui; -/// Download a binary, verify its SHA-256, then atomically write it into -/// place (fsynced, temp-in-same-dir-with-unique-name then rename — see -/// `bread_utils::atomic`). Bails before touching `dest` if the checksum -/// fails. Returns the verified hex sha256 so callers (`install:: -/// install_package`) can record it for `bakery verify` without hashing the -/// bytes a second time — `verify_sha256` already confirmed `bytes` matches -/// `binary.sha256`, so that's the value to return. -pub fn fetch_and_place(binary: &Binary, dest: &Path) -> Result { - ui::step("downloading", &binary.name); +/// Download a binary to a temp path, verify its SHA-256, then atomically move +/// it into place. Bails before touching `dest` if the checksum fails. +pub fn fetch_and_place(binary: &Binary, dest: &Path) -> Result<()> { + println!(" downloading {}…", binary.name); let bytes = fetch_binary(&binary.dl_url, &binary.github_url) .with_context(|| format!("downloading {}", binary.name))?; verify_sha256(&bytes, &binary.sha256) .with_context(|| format!("checksum mismatch for {}", binary.name))?; - crate::prefix::write_bytes(dest, &bytes, 0o755) - .with_context(|| format!("placing binary at {}", dest.display()))?; - ui::step("placed", &dest.display().to_string()); - Ok(binary.sha256.clone()) + if let Some(dir) = dest.parent() { + std::fs::create_dir_all(dir)?; + } + + let tmp = dest.with_extension("tmp"); + std::fs::write(&tmp, &bytes).context("writing binary to tmp")?; + + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + std::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(0o755))?; + } + + std::fs::rename(&tmp, dest).context("placing binary")?; + println!(" installed {}", dest.display()); + Ok(()) } -/// Verify that `bytes` hashes to `expected_hex` under SHA-256. -/// -/// Shared by every artifact download path — binaries (via -/// [`fetch_and_place`]), and config-example / systemd-unit downloads in -/// `install.rs` — so all downloaded artifacts get the same integrity check. -pub fn verify_sha256(bytes: &[u8], expected_hex: &str) -> Result<()> { - if expected_hex.is_empty() { - bail!("index entry has no sha256 recorded — refusing to trust an unverifiable download"); - } +fn verify_sha256(bytes: &[u8], expected_hex: &str) -> Result<()> { let mut hasher = Sha256::new(); hasher.update(bytes); let actual = hex::encode(hasher.finalize()); @@ -77,14 +75,4 @@ mod tests { let hash = sha256_hex(bytes); assert!(verify_sha256(bytes, &hash).is_ok()); } - - #[test] - fn verify_missing_sha256_gives_a_clear_error() { - // gen-index.sh emits an empty sha256 string when a .sha256 sidecar - // is missing — must not fall through to the generic mismatch - // message ("expected: \n actual: "), which is confusing about - // what actually went wrong. - let err = verify_sha256(b"anything", "").unwrap_err(); - assert!(err.to_string().contains("no sha256 recorded")); - } } diff --git a/bakery/src/install.rs b/bakery/src/install.rs index dd31145..03fb65f 100644 --- a/bakery/src/install.rs +++ b/bakery/src/install.rs @@ -1,673 +1,187 @@ -use anyhow::{bail, Context, Result}; -use std::collections::HashMap; -#[cfg(not(test))] -use std::io::IsTerminal; +use anyhow::{Context, Result}; use std::path::{Path, PathBuf}; use std::process::Command; -use crate::download::{fetch_and_place, verify_sha256}; +use crate::download::fetch_and_place; use crate::manifest::{fetch_binary, Package, Service}; -use crate::prefix::{self, Layout}; use crate::state::{InstalledPackage, State}; -use crate::track::Track; -use crate::ui; -/// Rejects a filename that isn't a safe single path component — no `/`, -/// `\`, empty, `.`, or `..`. `bin.name`/`svc.unit`/`cfg.example`/`pkg.name`/ -/// `license_file`/`desktop_file`/`data_archive` all come from the -/// minisign-verified index, so this is defense in depth (not exploitable -/// without a compromised signing key) rather than the primary guard — but -/// closing the path-traversal class is cheap enough to do anyway before any -/// of these are joined onto a fixed base directory. -fn ensure_safe_component(name: &str, what: &str) -> Result<()> { - if name.is_empty() || name == "." || name == ".." || name.contains('/') || name.contains('\\') { - bail!("refusing to install: {what} '{name}' is not a safe filename"); - } - Ok(()) -} +pub fn install_package(pkg: &Package, bin_dir: &Path) -> Result<()> { + println!("installing {}@{}…", pkg.name, pkg.version); -/// Whether stdin should be treated as an interactive terminal. Always -/// `false` in test builds regardless of the real process stdin — running -/// `cargo test` from an actual interactive shell (not CI, not piped) gives -/// the test binary a real tty, which previously made `confirm` block on a -/// `read_line` nobody was there to answer. -fn stdin_is_terminal() -> bool { - #[cfg(test)] - { - false - } - #[cfg(not(test))] - { - std::io::stdin().is_terminal() - } -} - -/// Prompts `prompt [y/N] ` and returns the answer. `assume_yes` (the global -/// `--yes` flag) skips the prompt entirely; otherwise, a non-tty stdin -/// (CI, piped input) answers "no" rather than blocking on a read that will -/// never resolve. -fn confirm(prompt: &str, assume_yes: bool) -> bool { - if assume_yes { - return true; - } - if !stdin_is_terminal() { - return false; - } - use std::io::Write; - print!("{prompt} {} ", ui::dim("[y/N]")); - std::io::stdout().flush().ok(); - let mut buf = String::new(); - std::io::stdin().read_line(&mut buf).ok(); - matches!(buf.trim().to_lowercase().as_str(), "y" | "yes") -} - -/// Installs `pkg`. `previous` is the package's current `InstalledPackage` -/// record when this is an update (looked up by the caller before starting, -/// since it's already loaded elsewhere in the call chain) — `None` for a -/// fresh first-time install. Threading it in rather than reloading `State` -/// here avoids a second load, and lets step 1 tell "update" from "fresh -/// install" for the pre-overwrite backup below. -pub fn install_package( - pkg: &Package, - layout: &Layout, - track: Track, - previous: Option<&InstalledPackage>, - no_hooks: bool, - assume_yes: bool, -) -> Result<()> { - ensure_safe_component(&pkg.name, "package name")?; - - // 1. Download and verify all binaries. On an update (not a fresh - // install), back up the current binary first — best-effort, feeding - // `bakery rollback` — before it's overwritten below. Backups stay - // per-user under ~/.local/state even when the live binary is in - // /usr/local/bin, so a snapper snapshot of `@` plus this local copy - // is enough to roll back; no second snapshot system. - let backup_dir = previous.map(|prev| crate::state::backup_dir(&pkg.name, &prev.version)); + // 1. Download and verify all binaries. let mut binary_names = Vec::new(); - let mut binary_sha256 = HashMap::new(); for bin in &pkg.binaries { - ensure_safe_component(&bin.name, "binary name")?; let install_name = strip_arch_suffix(&bin.name); - let dest = layout.bin_dir.join(install_name); - if let Some(dir) = &backup_dir { - backup_current_binary(dir, install_name, &dest); - } - let sha256 = fetch_and_place(bin, &dest)?; + let dest = bin_dir.join(&install_name); + fetch_and_place(bin, &dest)?; binary_names.push(install_name.to_string()); - binary_sha256.insert(install_name.to_string(), sha256); } - // 2. Scaffold config dir + download example file. Config stays - // per-user (~/.config) regardless of prefix — it's authored content, - // not bakery-placed bits. + // 2. Scaffold config dir + download example file. if let Some(cfg) = &pkg.config { scaffold_config(cfg, pkg)?; } - // 3. Install license file, if declared. - if let Some(license) = &pkg.license_file { - install_license(pkg, license, layout)?; - } - - // 4. Install desktop entry, if declared. - if let Some(desktop) = &pkg.desktop_file { - install_desktop_file(pkg, desktop, layout)?; - } - - // 5. Download + extract data archive, if declared. - if let Some(archive) = &pkg.data_archive { - install_data_archive(pkg, archive, layout)?; - } - - // 6. Install systemd user units. + // 3. Install systemd user units. let mut service_names = Vec::new(); for svc in &pkg.services { - install_service(svc, layout, pkg)?; + install_service(svc, bin_dir, pkg)?; service_names.push(svc.unit.clone()); } - // 7. Run post_install hooks — arbitrary `sh -c` on index-controlled - // strings, so this is gated behind --no-hooks and an interactive - // confirmation rather than running unconditionally. - if !pkg.post_install.is_empty() { - if no_hooks { - eprintln!( - " {}", - ui::note(&format!( - "skipped {} post_install hook(s) for {} (--no-hooks)", - pkg.post_install.len(), - pkg.name - )) - ); - } else if confirm( - &format!( - " run {} post_install hook(s) for {}?", - pkg.post_install.len(), - pkg.name - ), - assume_yes, - ) { - for cmd in &pkg.post_install { - run_hook(cmd, &pkg.name)?; - } - } else { - eprintln!( - " {}", - ui::note(&format!( - "skipped post_install hooks for {} (declined)", - pkg.name - )) - ); - } + // 4. Run post_install hooks. + for cmd in &pkg.post_install { + run_hook(cmd, &pkg.name)?; } - // 8. Record in state, under an exclusive lock so a concurrent `bakery` - // invocation can't clobber this install's record with its own. - State::with_lock(|state| { - state.record(InstalledPackage { - name: pkg.name.clone(), - version: pkg.version.clone(), - binaries: binary_names, - services: service_names, - installed_at: chrono::Utc::now().to_rfc3339(), - track, - previous_version: previous.map(|p| p.version.clone()), - binary_sha256, - }); - Ok(()) - })?; + // 5. Record in state. + let mut state = State::load()?; + state.record(InstalledPackage { + name: pkg.name.clone(), + version: pkg.version.clone(), + binaries: binary_names, + services: service_names, + installed_at: chrono::Utc::now().to_rfc3339(), + }); + state.save()?; - println!(" {}", ui::ok(&format!("{} installed", pkg.name))); - warn_path_if_needed(&layout.bin_dir); + println!(" {} installed successfully", pkg.name); + warn_path_if_needed(bin_dir); Ok(()) } -/// Best-effort copy of the on-disk binary into `backup_dir` before it's -/// overwritten by an update — feeds `bakery rollback`. `backup_dir` is -/// deliberately a local path (ultimately under `~/.local/state/bakery/ -/// backups///`, see `state::backup_dir`) rather than -/// `bakery rollback` re-fetching the old version from `dl.breadway.dev`: -/// `index.json`'s minisign signature only covers the *current* published -/// version's checksums, so verifying an old version pulled fresh from the -/// server would only be checkable against its unsigned per-version -/// `.sha256` sidecar — a materially weaker guarantee than bakery's normal -/// trust model. A local pre-update snapshot sidesteps that gap entirely. -fn backup_current_binary(backup_dir: &Path, binary_name: &str, current_path: &Path) { - if !current_path.exists() { - return; - } - if let Err(e) = std::fs::create_dir_all(backup_dir) { - eprintln!( - " {}", - ui::warn(&format!( - "could not create backup dir {} ({e}) — rollback won't be available for this update", - backup_dir.display() - )) - ); - return; - } - if let Err(e) = std::fs::copy(current_path, backup_dir.join(binary_name)) { - eprintln!( - " {}", - ui::warn(&format!( - "could not back up {binary_name} before update ({e}) — rollback won't be available for this update" - )) - ); - } -} - -pub fn remove_package( - pkg_name: &str, - layout: &Layout, - assume_yes: bool, - purge: bool, -) -> Result<()> { - let installed = State::with_lock(|state| Ok(state.remove(pkg_name)))?; - let installed = match installed { +pub fn remove_package(pkg_name: &str, bin_dir: &Path) -> Result<()> { + let mut state = State::load()?; + let installed = match state.remove(pkg_name) { Some(p) => p, None => { - eprintln!(" {}", ui::fail(&format!("{pkg_name} is not installed"))); + eprintln!("{pkg_name} is not installed"); return Ok(()); } }; - ui::action("Removing", pkg_name, Some(&installed.version)); - // State is already committed by with_lock above — everything from here - // is best-effort file cleanup, and must all run even if part of it fails. + // Commit removal immediately — file cleanup below is best-effort. + state.save()?; - // Remove binaries. Collect failures instead of aborting on the first one - // so a stuck/permission-denied binary doesn't skip service removal and - // the config/data-preserved messages below. - let mut failures = Vec::new(); + // Remove binaries. for bin in &installed.binaries { - let path = layout.bin_dir.join(bin); + let path = bin_dir.join(bin); if path.exists() { - match prefix::remove_file(&path) { - Ok(()) => ui::step("removed", &path.display().to_string()), - Err(e) => failures.push(format!("{}: {e}", path.display())), - } + std::fs::remove_file(&path) + .with_context(|| format!("removing {}", path.display()))?; + println!(" removed {}", path.display()); } } // Prompt for unit removal. if !installed.services.is_empty() { - let service_dir = &layout.systemd_user_dir; + let service_dir = systemd_user_dir(); for unit in &installed.services { let unit_path = service_dir.join(unit); - if confirm_remove_unit(unit, assume_yes) { + if confirm_remove_unit(unit) { let _ = Command::new("systemctl") .args(["--user", "disable", "--now", unit]) .status(); if unit_path.exists() { - let _ = prefix::remove_file(&unit_path); + std::fs::remove_file(&unit_path).ok(); } let _ = Command::new("systemctl") .args(["--user", "daemon-reload"]) .status(); - ui::step("removed", &format!("unit {unit}")); + println!(" removed unit {unit}"); } } } - // Config is never touched, even with --purge: unlike the license/desktop - // /data paths below (all bakery-downloaded or -extracted content, - // reproducible from source), the config dir holds user-authored/edited - // content bakery never wrote — silently destroying it would be a bad - // surprise no flag should cause. + // Never touch config or data dirs. if let Some(cfg_dir) = guess_config_dir(pkg_name) { if cfg_dir.exists() { - ui::step("preserved", &format!("config {}", cfg_dir.display())); + println!(" config preserved at {}", cfg_dir.display()); } } - - let share_dir = &layout.share_dir; - let data_dir = share_dir.join(pkg_name); - - if purge { - let license_dir = share_dir.join("licenses").join(pkg_name); - remove_purged_path(&license_dir, "license dir", true, assume_yes, &mut failures); - - let desktop_file = share_dir - .join("applications") - .join(format!("{pkg_name}.desktop")); - remove_purged_path( - &desktop_file, - "desktop entry", - false, - assume_yes, - &mut failures, - ); - - remove_purged_path(&data_dir, "data dir", true, assume_yes, &mut failures); - } else if data_dir.exists() { - ui::step("preserved", &format!("data {}", data_dir.display())); + let data_dir = dirs::data_dir() + .unwrap_or_else(|| PathBuf::from("~/.local/share")) + .join(pkg_name); + if data_dir.exists() { + println!(" data preserved at {}", data_dir.display()); } - if !failures.is_empty() { - eprintln!( - " {}", - ui::fail(&format!("failed to remove {} item(s):", failures.len())) - ); - for f in &failures { - eprintln!(" {f}"); - } - bail!("{pkg_name} removed from state, but some files could not be deleted"); - } - - println!(" {}", ui::ok(&format!("{pkg_name} removed"))); + println!(" {pkg_name} removed"); Ok(()) } -/// Confirms (via `confirm`, so `--yes` and non-tty stdin behave the same as -/// every other destructive prompt in this file) and removes `path` — a -/// directory when `recursive`, otherwise a single file. Declining leaves it -/// in place and prints the same "preserved at" wording the non-purge path -/// already uses. Shared by `remove_package`'s three `--purge` targets -/// (license dir, desktop entry, data dir). -fn remove_purged_path( - path: &Path, - label: &str, - recursive: bool, - assume_yes: bool, - failures: &mut Vec, -) { - if !path.exists() { - return; - } - if !confirm( - &format!(" remove {label} at {}?", path.display()), - assume_yes, - ) { - ui::step("preserved", &format!("{label} {}", path.display())); - return; - } - let result = if recursive { - prefix::remove_dir_all(path) - } else { - prefix::remove_file(path) - }; - match result { - Ok(()) => ui::step("removed", &path.display().to_string()), - Err(e) => failures.push(format!("{}: {e}", path.display())), - } -} - fn scaffold_config(cfg: &crate::manifest::ConfigScaffold, pkg: &Package) -> Result<()> { let dir = expand_tilde(&cfg.dir); std::fs::create_dir_all(&dir)?; if let Some(example) = &cfg.example { - ensure_safe_component(example, "config.example")?; let dest = dir.join(example); if !dest.exists() { if let Some((primary, fallback)) = pkg.artifact_urls(example) { match fetch_binary(&primary, &fallback) { - Ok(bytes) => match &cfg.example_sha256 { - Some(expected) => match verify_sha256(&bytes, expected) { - Ok(()) => { - std::fs::write(&dest, &bytes) - .with_context(|| format!("writing {}", dest.display()))?; - ui::step("config", &dest.display().to_string()); - } - Err(e) => { - eprintln!( - " {}", - ui::warn(&format!( - "checksum mismatch for example config {example}: {e} — not installed" - )) - ); - ui::step("config", &dir.display().to_string()); - } - }, - None => { - eprintln!( - " {}", - ui::warn(&format!( - "index.json has no sha256 for example config \ - {example} — refusing to install an unverified download" - )) - ); - ui::step("config", &dir.display().to_string()); - } - }, + Ok(bytes) => { + std::fs::write(&dest, &bytes) + .with_context(|| format!("writing {}", dest.display()))?; + println!(" installed example config at {}", dest.display()); + } Err(e) => { - eprintln!( - " {}", - ui::warn(&format!("could not download example config {example}: {e}")) - ); - ui::step("config", &dir.display().to_string()); + eprintln!(" warning: could not download example config {example}: {e}"); + println!(" config dir created at {}", dir.display()); } } } else { - ui::step("config", &dir.display().to_string()); + println!(" config dir created at {}", dir.display()); } } else { - ui::step( - "config", - &format!("{} already exists, skipping", dest.display()), - ); + println!(" config at {} already exists, skipping", dest.display()); } } else { - ui::step("config", &dir.display().to_string()); + println!(" config dir created at {}", dir.display()); } Ok(()) } -/// Download `filename` from `pkg`'s release dir, verify it against `sha256` -/// (refusing an unverified download the same way `scaffold_config` does), -/// and write it to `dest`. Shared by `install_license`/`install_desktop_file` -/// since both are "fetch one small artifact, verify, place" — unlike a config -/// example, these aren't user-editable, so they're always refreshed rather -/// than skipped when already present. -fn fetch_verify_write( - pkg: &Package, - filename: &str, - sha256: &Option, - dest: &Path, - label: &str, -) -> Result<()> { - let Some((primary, fallback)) = pkg.artifact_urls(filename) else { - eprintln!( - " {}", - ui::warn(&format!("no artifact URL to download {label} ({filename})")) - ); - return Ok(()); - }; - let bytes = match fetch_binary(&primary, &fallback) { - Ok(b) => b, - Err(e) => { - eprintln!( - " {}", - ui::warn(&format!("could not download {label} {filename}: {e}")) - ); - return Ok(()); - } - }; - let Some(expected) = sha256 else { - eprintln!( - " {}", - ui::warn(&format!( - "index.json has no sha256 for {label} {filename} — \ - refusing to install an unverified download" - )) - ); - return Ok(()); - }; - if let Err(e) = verify_sha256(&bytes, expected) { - eprintln!( - " {}", - ui::warn(&format!( - "checksum mismatch for {label} {filename}: {e} — not installed" - )) - ); - return Ok(()); - } - prefix::write_bytes(dest, &bytes, 0o644) - .with_context(|| format!("writing {}", dest.display()))?; - ui::step("installed", &format!("{label} {}", dest.display())); - Ok(()) -} - -fn install_license(pkg: &Package, filename: &str, layout: &Layout) -> Result<()> { - ensure_safe_component(filename, "license_file")?; - let dest = layout - .share_dir - .join("licenses") - .join(&pkg.name) - .join("LICENSE"); - fetch_verify_write(pkg, filename, &pkg.license_file_sha256, &dest, "license") -} - -fn install_desktop_file(pkg: &Package, filename: &str, layout: &Layout) -> Result<()> { - ensure_safe_component(filename, "desktop_file")?; - let dest = layout - .share_dir - .join("applications") - .join(format!("{}.desktop", pkg.name)); - fetch_verify_write( - pkg, - filename, - &pkg.desktop_file_sha256, - &dest, - "desktop entry", - ) -} - -fn install_data_archive(pkg: &Package, filename: &str, layout: &Layout) -> Result<()> { - ensure_safe_component(filename, "data_archive")?; - let data_dir = layout.share_dir.join(&pkg.name); - fetch_extract_archive(pkg, filename, &pkg.data_archive_sha256, &data_dir) -} - -/// Downloads + verifies a `.tar.gz` artifact, then extracts it into -/// `dest_dir`. Shells out to `tar` rather than adding an archive-extraction -/// crate dependency — `tar` is universally present on Linux and this file -/// already shells out to `systemctl` for the same "trust the base system -/// has this" reason. Split from `install_data_archive` (which just supplies -/// the real `$prefix/share/` destination) so tests can extract into -/// a tempdir instead. -fn fetch_extract_archive( - pkg: &Package, - filename: &str, - sha256: &Option, - dest_dir: &Path, -) -> Result<()> { - // A securely-named, process-unique temp file — the old - // `std::env::temp_dir().join(format!("bakery-{name}-{filename}"))` was a - // predictable path on a shared /tmp, so another local user could - // pre-plant a symlink there for `fetch_verify_write`'s write to follow. - let tmp_archive = tempfile::Builder::new() - .prefix(&format!("bakery-{}-", pkg.name)) - .tempfile() - .context("creating temp file for archive download")? - .into_temp_path(); - - fetch_verify_write(pkg, filename, sha256, &tmp_archive, "data archive")?; - // `fetch_verify_write` treats a download/checksum/missing-sha failure - // as a soft warning and returns `Ok` *without writing* — but the - // `NamedTempFile` above is already created (0 bytes), so gating on - // mere `exists()` would let an empty file through to `tar tvf`, which - // then bails with a confusing "not in gzip format" error that masks - // the real cause and aborts the whole install. Gate on *non-empty*. - if std::fs::metadata(&tmp_archive) - .map(|m| m.len()) - .unwrap_or(0) - == 0 - { - return Ok(()); - } - - verify_archive_paths(&tmp_archive)?; - - match prefix::extract_tar_gz(&tmp_archive, dest_dir) { - Ok(()) => ui::step( - "extracted", - &format!("{filename} → {}", dest_dir.display()), - ), - Err(e) => { - eprintln!( - " {}", - ui::warn(&format!("could not extract {filename}: {e}")) - ); - } - } - // `tmp_archive` (a `TempPath` guard) deletes the file when it drops here. - Ok(()) -} - -/// Lists `archive_path`'s contents via `tar tvf` and rejects the archive -/// outright (no extraction) if any entry is a symlink or has an unsafe path -/// (`..` component, or absolute). `--no-same-owner --no-same-permissions` on -/// the actual extraction covers ownership/permission escalation, but not a -/// symlink or `../` entry walking the extraction outside `dest_dir` — this -/// closes that gap before `tar` ever touches disk. -fn verify_archive_paths(archive_path: &Path) -> Result<()> { - let output = Command::new("tar") - .arg("tvf") - .arg(archive_path) - .output() - .context("listing archive contents")?; - if !output.status.success() { - bail!( - "tar tvf exited with {} listing archive contents — refusing to extract", - output.status - ); - } - - let listing = String::from_utf8_lossy(&output.stdout); - for line in listing.lines() { - if line.trim().is_empty() { - continue; - } - // tar -tvf: ` /