From b34de5c29ed8181ff362c866f47b79b405fedb9e Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Mon, 14 Sep 2026 21:15:17 -0400 Subject: [PATCH] Replace scheduled AUR imports with direct upstream watches --- .github/workflows/sync-aur.yml | 91 --- .github/workflows/sync-upstream.yml | 15 +- .github/workflows/test.yml | 3 +- .gitignore | 3 + README.md | 140 ++--- bin/add-package | 39 +- bin/import-aur | 62 ++ bin/package-worktree | 12 +- bin/sync-aur | 434 -------------- bin/sync-upstream | 22 + docs/upstream-sources.md | 178 ++++++ helpers/package-metadata.sh | 27 +- helpers/upstream-github.sh | 2 +- helpers/upstream-watch.py | 566 ++++++++++++++++++ .../1password-beta/.omarchy/package.json | 18 +- .../1password-beta/.omarchy/post-sync.sh | 83 --- pkgbuilds/1password-beta/PKGBUILD | 4 +- pkgbuilds/1password-cli/.omarchy/package.json | 13 +- pkgbuilds/aether/.omarchy/package.json | 13 +- pkgbuilds/asusctl/.omarchy/package.json | 13 +- pkgbuilds/basecamp-cli/.omarchy/package.json | 13 +- pkgbuilds/basecamp-cli/PKGBUILD | 6 +- pkgbuilds/bun-bin/.omarchy/package.json | 13 +- pkgbuilds/claude-code/.omarchy/package.json | 13 +- pkgbuilds/cliamp/.omarchy/package.json | 13 +- pkgbuilds/crush-bin/.omarchy/package.json | 13 +- pkgbuilds/cursor-bin/.omarchy/package.json | 19 +- pkgbuilds/cursor-bin/PKGBUILD | 8 +- pkgbuilds/cursor-cli/.omarchy/package.json | 15 +- pkgbuilds/dbxcli-bin/.omarchy/package.json | 13 +- pkgbuilds/dropbox-cli/.omarchy/package.json | 13 +- .../.omarchy/patches/x86-only.patch | 11 - pkgbuilds/dropbox/.omarchy/package.json | 13 +- pkgbuilds/elephant-all/.omarchy/package.json | 13 +- .../.omarchy/package.json | 13 +- .../elephant-bluetooth/.omarchy/package.json | 13 +- pkgbuilds/elephant-calc/.omarchy/package.json | 13 +- .../elephant-clipboard/.omarchy/package.json | 13 +- .../.omarchy/package.json | 13 +- .../elephant-files/.omarchy/package.json | 13 +- .../elephant-menus/.omarchy/package.json | 13 +- .../.omarchy/package.json | 13 +- .../elephant-runner/.omarchy/package.json | 13 +- .../elephant-symbols/.omarchy/package.json | 13 +- pkgbuilds/elephant-todo/.omarchy/package.json | 13 +- .../elephant-unicode/.omarchy/package.json | 13 +- .../elephant-websearch/.omarchy/package.json | 13 +- pkgbuilds/elephant/.omarchy/package.json | 13 +- pkgbuilds/grok-bot/.omarchy/package.json | 7 +- .../.omarchy/package.json | 13 +- pkgbuilds/heroic-games-launcher-bin/PKGBUILD | 9 +- pkgbuilds/hyprshade/.omarchy/package.json | 12 +- .../.omarchy/package.json | 13 +- .../patches/max-zstd-compression.patch | 15 - pkgbuilds/libfprint-git/.omarchy/package.json | 7 +- .../libretro-cap32-git/.omarchy/package.json | 7 +- .../.omarchy/package.json | 7 +- .../libretro-fbneo-git/.omarchy/package.json | 7 +- .../libretro-uae-git/.omarchy/package.json | 7 +- .../libretro-vice-git/.omarchy/package.json | 7 +- .../.omarchy/package.json | 13 +- .../.omarchy/patches/arm-gradle.patch | 48 -- pkgbuilds/limine-mkinitcpio-hook/PKGBUILD | 6 +- .../limine-snapper-sync/.omarchy/package.json | 13 +- .../.omarchy/patches/arm-gradle.patch | 46 -- pkgbuilds/lmstudio-bin/.omarchy/package.json | 19 +- pkgbuilds/lmstudio-bin/PKGBUILD | 5 +- pkgbuilds/localsend-bin/.omarchy/package.json | 13 +- pkgbuilds/localsend/.omarchy/package.json | 13 +- .../.omarchy/package.json | 17 +- pkgbuilds/macbook12-spi-driver-dkms/PKGBUILD | 9 +- pkgbuilds/makima-bin/.omarchy/package.json | 13 +- .../minecraft-launcher/.omarchy/package.json | 17 +- .../nautilus-dropbox/.omarchy/package.json | 13 +- .../.omarchy/package.json | 13 +- pkgbuilds/nordvpn-bin/.omarchy/package.json | 13 +- .../nvidia-580xx-utils/.omarchy/package.json | 13 +- .../patches/max-zstd-compression.patch | 15 - .../.omarchy/package.json | 18 +- pkgbuilds/omarchy-chromium-bin/PKGBUILD | 9 +- pkgbuilds/omarchy-emacs/.omarchy/package.json | 13 +- pkgbuilds/omazed/.omarchy/package.json | 13 +- pkgbuilds/once-bin/.omarchy/package.json | 13 +- .../openai-codex-bin/.omarchy/package.json | 13 +- .../python-mediapipe/.omarchy/package.json | 13 +- .../patches/verify-bazel-source.patch | 42 -- .../python-sounddevice/.omarchy/package.json | 12 +- .../.omarchy/package.json | 12 +- .../quickshell-git/.omarchy/package.json | 7 +- pkgbuilds/rustdesk/.omarchy/package.json | 16 +- pkgbuilds/rustdesk/PKGBUILD | 24 +- pkgbuilds/spotify/.omarchy/package.json | 17 +- pkgbuilds/spotify/PKGBUILD | 16 +- .../sublime-text-4/.omarchy/package.json | 14 +- pkgbuilds/sunshine/.omarchy/package.json | 16 +- .../.omarchy/patches/arm-dependencies.patch | 56 -- .../patches/packager-build-flags.patch | 15 - pkgbuilds/sunshine/PKGBUILD | 6 +- pkgbuilds/supergfxctl/.omarchy/package.json | 8 +- pkgbuilds/ttf-ia-writer/.omarchy/package.json | 17 +- pkgbuilds/ttf-ia-writer/PKGBUILD | 15 +- .../.omarchy/package.json | 18 +- .../PKGBUILD | 7 +- pkgbuilds/typora/.omarchy/package.json | 14 +- pkgbuilds/ufw-docker/.omarchy/package.json | 13 +- pkgbuilds/vi/.omarchy/package.json | 13 +- .../.omarchy/package.json | 13 +- pkgbuilds/walker/.omarchy/package.json | 13 +- .../xdg-terminal-exec/.omarchy/package.json | 13 +- pkgbuilds/xpadneo-dkms/.omarchy/package.json | 13 +- .../.omarchy/patches/arm-kernel-headers.patch | 11 - .../yaru-icon-theme/.omarchy/package.json | 14 +- pkgbuilds/yay/.omarchy/package.json | 13 +- pkgbuilds/yt6801-dkms/.omarchy/package.json | 17 +- tests/upstream-watch.py | 334 +++++++++++ 115 files changed, 2155 insertions(+), 1242 deletions(-) delete mode 100644 .github/workflows/sync-aur.yml create mode 100755 bin/import-aur delete mode 100755 bin/sync-aur create mode 100644 docs/upstream-sources.md create mode 100644 helpers/upstream-watch.py delete mode 100755 pkgbuilds/1password-beta/.omarchy/post-sync.sh delete mode 100644 pkgbuilds/dropbox-cli/.omarchy/patches/x86-only.patch delete mode 100644 pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch delete mode 100644 pkgbuilds/limine-mkinitcpio-hook/.omarchy/patches/arm-gradle.patch delete mode 100644 pkgbuilds/limine-snapper-sync/.omarchy/patches/arm-gradle.patch delete mode 100644 pkgbuilds/nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch delete mode 100644 pkgbuilds/python-mediapipe/.omarchy/patches/verify-bazel-source.patch delete mode 100644 pkgbuilds/sunshine/.omarchy/patches/arm-dependencies.patch delete mode 100644 pkgbuilds/sunshine/.omarchy/patches/packager-build-flags.patch delete mode 100644 pkgbuilds/xpadneo-dkms/.omarchy/patches/arm-kernel-headers.patch create mode 100644 tests/upstream-watch.py diff --git a/.github/workflows/sync-aur.yml b/.github/workflows/sync-aur.yml deleted file mode 100644 index b5d3fd3..0000000 --- a/.github/workflows/sync-aur.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: Sync AUR Packages - -on: - schedule: - # Every 6 hours - - cron: '0 */6 * * *' - workflow_dispatch: - inputs: - packages: - description: 'Specific packages to sync (space-separated, leave empty for all)' - required: false - default: '' - -jobs: - sync: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: Sync AUR packages - run: | - docker run --rm \ - -e PACKAGES="$PACKAGES" \ - -e HOST_UID="$(id -u)" \ - -e HOST_GID="$(id -g)" \ - -v "$PWD/bin:/workspace/bin:ro" \ - -v "$PWD/helpers:/workspace/helpers:ro" \ - -v "$PWD/pkgbuilds:/workspace/pkgbuilds" \ - -w /workspace \ - archlinux:base-devel bash -lc ' - set -euo pipefail - - pacman -Syu --noconfirm git jq - - groupadd -g "$HOST_GID" runner - useradd -m -u "$HOST_UID" -g "$HOST_GID" runner - chown -R runner:runner /workspace/pkgbuilds - - if [[ -n "${PACKAGES:-}" ]]; then - read -r -a package_args <<< "$PACKAGES" - runuser -u runner -- ./bin/sync-aur "${package_args[@]}" - else - runuser -u runner -- ./bin/sync-aur - fi - ' - env: - PACKAGES: ${{ github.event.inputs.packages }} - - - name: Check for changes - id: changes - run: | - if [ -z "$(git status --porcelain)" ]; then - echo "has_changes=false" >> "$GITHUB_OUTPUT" - else - echo "has_changes=true" >> "$GITHUB_OUTPUT" - fi - - - name: Create Pull Request - if: steps.changes.outputs.has_changes == 'true' - uses: peter-evans/create-pull-request@v7 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: 'chore: sync AUR packages' - title: 'chore: sync AUR packages' - body: | - Automated AUR package sync. - - Package sync behavior is controlled by `.omarchy/package.json`. - branch: auto/sync-aur - delete-branch: true - labels: automated - reviewers: ryanrhughes - - - name: Notify Basecamp on failure - if: failure() && env.BASECAMP_CHATBOT_URL != '' - env: - BASECAMP_CHATBOT_URL: ${{ secrets.BASECAMP_CHATBOT_URL }} - run: | - curl -s -o /dev/null \ - -H "Content-Type: application/json" \ - -d "$(jq -n --arg content \ - "🔴 AUR sync failed
View run" \ - '{content: $content}')" \ - "$BASECAMP_CHATBOT_URL" diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index c19c9ae..2e69136 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -27,9 +27,11 @@ jobs: # Runs in an Arch container for vercmp: whether a release is an upgrade has # to be decided by the same comparator pacman will use on users' machines. - name: Update packages from upstream release feeds + id: sync run: | docker run --rm \ -e PACKAGES="$PACKAGES" \ + -e UPSTREAM_GITHUB_TOKEN="$UPSTREAM_GITHUB_TOKEN" \ -e HOST_UID="$(id -u)" \ -e HOST_GID="$(id -g)" \ -v "$PWD/bin:/workspace/bin:ro" \ @@ -39,7 +41,7 @@ jobs: archlinux:base-devel bash -lc ' set -euo pipefail - pacman -Syu --noconfirm git jq + pacman -Syu --noconfirm git jq python libarchive groupadd -g "$HOST_GID" runner useradd -m -u "$HOST_UID" -g "$HOST_GID" runner @@ -54,8 +56,12 @@ jobs: ' env: PACKAGES: ${{ github.event.inputs.packages }} + UPSTREAM_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Failed feeds leave their recipes untouched; completed updates still + # reach review. The failed sync step keeps the workflow red and notifies. - name: Check for changes + if: ${{ !cancelled() && steps.sync.outcome != 'skipped' }} id: changes run: | if [ -z "$(git status --porcelain)" ]; then @@ -65,7 +71,7 @@ jobs: fi - name: Create Pull Request - if: steps.changes.outputs.has_changes == 'true' + if: ${{ !cancelled() && steps.changes.outputs.has_changes == 'true' }} uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -75,8 +81,9 @@ jobs: Automated update of packages that track an upstream vendor release feed rather than the AUR. - Each package reports its newest release through - `.omarchy/upstream.sh`. + Release watches and providers are declared in `.omarchy/package.json`; + exceptional feeds use `.omarchy/upstream.sh`. Failed package updates + are left untouched; check the workflow result for outstanding failures. branch: auto/sync-upstream delete-branch: true labels: automated diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a1a307a..4b64690 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,8 @@ jobs: -w /workspace \ archlinux:base-devel bash -lc ' set -euo pipefail - pacman -Syu --noconfirm git jq + pacman -Syu --noconfirm git jq python libarchive + python tests/upstream-watch.py ./bin/sync-upstream self-test ./bin/sync-rebuilds --self-test ./bin/omarchy-pkgs self-test diff --git a/.gitignore b/.gitignore index 7873a6d..7b1f63b 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ pkgbuilds/yay/yay/ .srcdest/ .repo-host .worktrees/ + +# Python helpers and offline tests +__pycache__/ diff --git a/README.md b/README.md index 2ba3ce5..5ff0edc 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ The filesystem no longer encodes release policy. Instead: (`OMARCHY_RC_PINS=1`, which `omarchy-release rc` sets) may build it for rc — master's shipped pins can never overwrite an in-flight RC. The dev pair (`omarchy-dev`, `omarchy-settings-dev`) is pinned to `edge` -- AUR sync behavior is controlled by `source`, `sync`, `aur`, patches, and hooks in `.omarchy/` +- Omarchy owns every checked-in recipe; upstream watches update release metadata without replacing packaging or architecture support - packages can opt out of unscoped builds with `skip_build`; explicit `--package` builds remain available -- packages that follow a vendor release feed instead of the AUR carry an `.omarchy/upstream.sh` hook +- packages follow direct upstream watches/providers in `.omarchy/package.json`, or a custom `.omarchy/upstream.sh` hook ## Prerequisites ### aarch64 Builds (Optional) @@ -329,14 +329,16 @@ push uploaded, so `push` stops when it finds packages already staged there — usually leftovers from a failed run. Remove them on the host, or pass `--include-staged` to publish them too. -### Sync AUR PKGBUILDs +### Import an initial AUR recipe ```bash -bin/sync-aur # Sync all AUR packages with sync enabled -bin/sync-aur yay v4l2-relayd # Sync specific packages +bin/add-package package-name --source aur ``` -AUR sync is metadata-driven. It preserves `.omarchy/`, replaces the package root with AUR contents, applies `.omarchy/patches/*.patch`, runs `.omarchy/post-sync.sh` when present, applies pkgrel metadata, removes AUR-only `.SRCINFO` and `.gitignore` files, and records `upstream_commit`. +AUR is an optional source for an initial recipe. Imported packages become +Omarchy-owned immediately; subsequent updates use direct upstream releases. +There is no scheduled AUR sync. Edit the checked-in PKGBUILD to maintain +architecture support and packaging behavior. ### Sync Upstream Releases @@ -550,8 +552,8 @@ bin/omarchy-release # Release front door (start / pick / rc / s bin/repo list # List package metadata bin/repo deploy # Build locally, then publish from the host bin/repo push # Upload local builds to the host and publish -bin/add-package # Add an AUR/local package with metadata -bin/package-worktree # Create upstream/patched/current scratch workspace +bin/add-package # Add an Omarchy-owned package with metadata +bin/package-worktree # Inspect historical AUR provenance in a scratch workspace bin/repo remove # Remove package bin/sync-upstream # Update packages that track a vendor release feed bin/sync-rebuilds # Bump pkgrel for packages whose dependencies moved @@ -570,7 +572,7 @@ bin/repo list # Table view of source package metadata bin/repo list --json # Agent/script-friendly JSON bin/repo list --repo --mirror stable # List packages in a published repo database -bin/package-worktree v4l2-relayd # Create upstream/patched/current scratch workspace +bin/package-worktree yay # Compare with the original imported AUR recipe ``` ## Cutting an Omarchy Release @@ -684,9 +686,7 @@ omarchy-pkgs/ │ ├── PKGBUILD │ └── .omarchy/ │ ├── package.json # Source/sync/release metadata -│ ├── patches/ # Omarchy patches reapplied after AUR sync -│ ├── post-sync.sh # Optional dynamic post-sync customization hook -│ └── upstream.sh # Optional vendor release feed hook (non-AUR packages) +│ └── upstream.sh # Optional custom vendor release feed hook ├── build/ ├── build-output/ # Unsigned packages (temporary) │ ├── edge/ # (rc/ and stable/ alongside, each x86_64 + aarch64) @@ -706,45 +706,28 @@ Each source package has Omarchy metadata at `pkgbuilds//.omarchy/packag Minimal examples: -```json -{ "source": "aur" } -``` - -```json -{ "source": "aur", "sync": false } -``` - -```json -{ "source": "aur", "release_ring": "fast" } -``` - ```json { "source": "local" } -``` - -```json +{ "source": "local", "release_ring": "fast" } { "source": "local", "skip_build": true } -``` - -```json -{ "source": "aur", "pkgrel": { "suffix": 1 } } +{ "source": "local", "upstream": { "watch": { "github": "abenz1267/walker", "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" } } } ``` Fields: -- `source`: `aur` or `local`. A `local` package can still follow an upstream release, either declaratively via `upstream` or with an `.omarchy/upstream.sh` hook. -- `upstream`: optional for `local` packages following GitHub releases, git tags, npm dist-tags, or a Debian `Packages` index. GitHub architecture assets may be a string or an ordered array, and can be combined with disjoint versioned `sources` — see [Sync Upstream Releases](#sync-upstream-releases). Mutually exclusive with `.omarchy/upstream.sh`. +- `source`: `local` for maintained packages. The legacy `aur` value is used only during an initial import. A local recipe can follow an upstream watch, provider, or `.omarchy/upstream.sh` hook. +- `upstream`: optional direct release watch (see [Upstream watches](docs/upstream-sources.md)), or an existing GitHub, git-tag, npm, or Debian provider. GitHub architecture assets may be a string or an ordered array, and can be combined with disjoint versioned `sources` — see [Sync Upstream Releases](#sync-upstream-releases). Mutually exclusive with `.omarchy/upstream.sh`. - `min_release_age`: optional quarantine for upstream releases (`"24h"`, `"2d"`, or bare seconds). The newest release older than the window ships; anything younger waits, and a release whose age cannot be proven fails the sync. Bypass deliberately with `BYPASS_MIN_RELEASE_AGE=1 bin/sync-upstream `. -- `sync`: optional for AUR packages; defaults to `true`. Set `false` for AUR-origin packages that Omarchy maintains manually. -- `aur`: optional AUR package name when it differs from the local package directory, usually for split packages. +- `sync`: `false` records an existing manual maintenance hold. Held packages have no upstream watch/provider/hook and are excluded from automatic updates. +- `origin`: optional historical import provenance, with `aur` (package name) and `commit`. It does not control updates. - `release_ring`: optional. `fast` means the package is built directly for stable as well as edge, with the artifacts replicated into rc for parity. Packages without a ring build in edge and reach stable through the pipeline (`bin/repo advance`). - `channels`: optional array bounding where the package may be built (`edge`, `rc`, `stable`). Without the key a package is a member of every channel and follows the default build rules above; `bin/repo advance` refuses to carry a package anywhere it isn't a member. - `pinned`: optional boolean. A pinned package's version is set per release by `omarchy-release` on the `rc` branch, so it is never built for stable (promotion only) and is built for rc only from that branch's worktree (`OMARCHY_RC_PINS=1`). Used by `omarchy` and `omarchy-settings`. - `skip_build`: optional boolean; defaults to `false`. Set `true` to exclude a package from scheduled version checks and unscoped builds. The package can still be built explicitly with `bin/repo release --package `. -- `pkgrel`: optional Omarchy pkgrel suffix for a version-pinned rebuild bump. This emits `.` instead of replacing AUR's pkgrel. `offset` can be used only when preserving monotonic upgrades from old absolute pkgrel bumps. The metadata is removed automatically when AUR sync changes `pkgver`; the current package version is read from the checked-in PKGBUILD, so the version is not duplicated in JSON. +- `pkgrel`: legacy import customization metadata. Maintained recipes keep their complete package release directly in PKGBUILD; rebuilds increment it there. - `rebuild_on`: optional array of package names this package links against closely enough that it must be rebuilt when they change, independent of its own source. Read by `bin/sync-rebuilds`. - `rebuilt_against`: written by `bin/sync-rebuilds`. Maps each published architecture to the versions of its `rebuild_on` packages that the current pkgrel was bumped for. -- `upstream_commit`: set by `bin/sync-aur` for AUR packages. Used by `bin/package-worktree` to recreate the exact raw AUR package that Omarchy last synced. +- `upstream_commit`: legacy AUR metadata, superseded by `origin.commit`. `bin/package-worktree` can use historical provenance to inspect the original recipe. ### Build Matrix @@ -756,78 +739,26 @@ Fields: ## Adding Packages -### From AUR +### Start from an existing recipe ```bash -bin/add-package package-name +bin/add-package package-name --source aur --fast +# Review the imported files, own any architecture/packaging changes directly, +# and declare an upstream watch/provider or hook in .omarchy/. +bin/sync-upstream package-name bin/repo release --package package-name ``` -### From AUR, fast release ring +The import records historical provenance in `origin`. It does not opt a package +into future AUR imports. Upstream watches update only release scalars and source +checksums; downstream build behavior stays in the recipe. Ordinary source-code +patches still belong beside PKGBUILD and are applied by `prepare()` as needed. + +### Custom package ```bash -bin/add-package package-name --fast -bin/repo release --package package-name -bin/repo release --mirror stable --package package-name -``` - -### AUR-origin, manually maintained by Omarchy - -```bash -bin/add-package package-name --no-sync -``` - -### Local Customizations for AUR Packages - -For static changes, create `pkgbuilds/package-name/.omarchy/patches/*.patch` to maintain modifications across AUR syncs. - -The recommended workflow is to use a scratch workspace: - -```bash -bin/package-worktree package-name --dir /tmp/package-name-worktree -``` - -This creates: - -```text -upstream/ # raw AUR package at upstream_commit -patched/ # AUR + existing Omarchy .omarchy customizations -current/ # current checked-in package directory -``` - -Patch-authoring flow: - -```bash -# 1. Make the intended change in pkgbuilds/package-name/ - -# 2. Recreate the scratch workspace -bin/package-worktree package-name --dir /tmp/package-name-worktree - -# 3. Inspect drift from patched -> current -# For multi-file changes, inspect this and split into focused patches. -diff -ruN /tmp/package-name-worktree/patched /tmp/package-name-worktree/current - -# For a single PKGBUILD change, write a patch like this: -mkdir -p pkgbuilds/package-name/.omarchy/patches -( - cd /tmp/package-name-worktree/patched - diff -u --label a/PKGBUILD --label b/PKGBUILD \ - PKGBUILD /tmp/package-name-worktree/current/PKGBUILD || true -) > pkgbuilds/package-name/.omarchy/patches/my-fix.patch - -# 4. Verify the package is reproducible from AUR + .omarchy -bin/sync-aur package-name -bin/package-worktree package-name --dir /tmp/package-name-check -diff -ruN /tmp/package-name-check/patched /tmp/package-name-check/current -``` - -For dynamic changes that depend on the current upstream version, add `pkgbuilds/package-name/.omarchy/post-sync.sh`. The hook runs after the AUR package is copied into a temporary worktree and before the Omarchy pkgrel suffix is applied. After patches/hooks/metadata pkgrel overrides, `bin/sync-aur` removes AUR-only `.SRCINFO` and `.gitignore` files before writing the package back. - -### Custom Package - -```bash -bin/add-package my-package --local --scaffold -# Fill in PKGBUILD and package files +bin/add-package my-package --scaffold +# Fill in PKGBUILD, package files, and upstream metadata bin/repo release --package my-package ``` @@ -910,9 +841,8 @@ The repository includes GitHub workflows and systemd services for automated rele #### GitHub Workflows -1. **sync-aur.yml** (Every 6 hours): Syncs AUR packages according to `.omarchy/package.json` and opens a PR when changes are found. -2. **sync-upstream.yml** (Every 6 hours): Runs `.omarchy/upstream.sh` for packages that track a vendor release feed and opens a PR when a newer version is out. -3. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories and opens a PR. +1. **sync-upstream.yml** (Every 6 hours): Watches direct upstream feeds and updates owned recipes. Successful package updates reach a PR even if another feed fails; failed recipes stay untouched and the workflow remains red. +2. **sync-rebuilds.yml** (Every 6 hours): Bumps pkgrel for packages whose `rebuild_on` dependencies have moved in the official repositories and opens a PR. #### Systemd Services diff --git a/bin/add-package b/bin/add-package index ee18f80..b347b8d 100755 --- a/bin/add-package +++ b/bin/add-package @@ -6,7 +6,7 @@ source "$BUILD_ROOT/helpers/message-helpers.sh" source "$BUILD_ROOT/helpers/paths.sh" PACKAGE="" -SOURCE="aur" +SOURCE="local" SYNC="true" RELEASE_RING="" AUR_PACKAGE="" @@ -17,14 +17,14 @@ usage() { cat < [OPTIONS] -Create pkgbuilds/ with Omarchy metadata. AUR packages are synced -immediately after metadata is written. +Create an Omarchy-owned package. --source aur imports a starting recipe once; +future releases must use an upstream watch, provider, or hook. Options: - --source Package source (default: aur) + --source Initial recipe source (default: local) --local Shortcut for --source local --aur AUR package name when different from local directory - --no-sync For AUR packages, mark sync disabled after initial setup + --no-sync Keep the imported recipe manually maintained --fast Put package in the fast release ring --release-ring Release ring (currently: fast) --scaffold For local packages, create a starter PKGBUILD @@ -32,9 +32,9 @@ Options: -h, --help Show this help message Examples: - $0 yay - $0 spotify --fast - $0 signal-desktop --no-sync + $0 yay --source aur + $0 spotify --source aur --fast + $0 signal-desktop --source aur --no-sync $0 omarchy-zsh --local --scaffold EOF } @@ -97,6 +97,10 @@ if [[ -z "$PACKAGE" ]]; then usage exit 1 fi +if [[ ! $PACKAGE =~ ^[a-zA-Z0-9@_+][a-zA-Z0-9@._+-]*$ ]]; then + print_error "Invalid package name: $PACKAGE" + exit 1 +fi case "$SOURCE" in aur|local) ;; @@ -112,6 +116,11 @@ PACKAGE_DIR="$PKGBUILDS_DIR/$PACKAGE" OMARCHY_DIR="$PACKAGE_DIR/.omarchy" METADATA_FILE="$OMARCHY_DIR/package.json" +if [[ "$SOURCE" == aur && -f "$PACKAGE_DIR/PKGBUILD" ]]; then + print_error "Refusing to replace the maintained recipe for $PACKAGE" + exit 1 +fi + if [[ -f "$METADATA_FILE" && "$FORCE" != true ]]; then print_error "Package metadata already exists: $METADATA_FILE" print_info "Use --force to overwrite it" @@ -146,18 +155,8 @@ jq -n "${jq_args[@]}" "$jq_filter" > "$METADATA_FILE" print_success "Wrote $METADATA_FILE" if [[ "$SOURCE" == "aur" ]]; then - if [[ "$SYNC" == "false" ]]; then - # Temporarily sync once, then restore sync=false so future automated syncs skip it. - tmpfile=$(mktemp) - jq 'del(.sync)' "$METADATA_FILE" > "$tmpfile" - mv "$tmpfile" "$METADATA_FILE" - "$BUILD_ROOT/bin/sync-aur" "$PACKAGE" - jq '. + {sync: false}' "$METADATA_FILE" > "$tmpfile" - mv "$tmpfile" "$METADATA_FILE" - print_info "AUR sync disabled for future runs" - else - "$BUILD_ROOT/bin/sync-aur" "$PACKAGE" - fi + "$BUILD_ROOT/bin/import-aur" "$PACKAGE" + else if [[ "$SCAFFOLD" == true && ! -f "$PACKAGE_DIR/PKGBUILD" ]]; then cat > "$PACKAGE_DIR/PKGBUILD" < --source aur [--aur ]" + exit 0 +fi +if [[ $# != 1 || ! $1 =~ ^[a-zA-Z0-9@_+][a-zA-Z0-9@._+-]*$ ]]; then + print_error "Use bin/add-package --source aur for an initial import" + exit 1 +fi +package=$1 +package_dir="$PKGBUILDS_DIR/$package" +metadata="$package_dir/.omarchy/package.json" +if [[ -f "$package_dir/PKGBUILD" ]]; then + print_error "Refusing to replace the maintained recipe for $package" + exit 1 +fi +if [[ ! -f "$metadata" ]] || [[ $(jq -r .source "$metadata") != aur ]]; then + print_error "Initial import requires metadata created by bin/add-package --source aur" + exit 1 +fi +aur_package=$(jq -r --arg name "$package" '.aur // $name' "$metadata") +if [[ ! $aur_package =~ ^[a-zA-Z0-9@_+][a-zA-Z0-9@._+-]*$ ]]; then + print_error "Invalid AUR package name" + exit 1 +fi +# Refuse unrelated package files: an import only starts from .omarchy metadata. +shopt -s dotglob nullglob +for item in "$package_dir"/*; do + if [[ ${item##*/} != .omarchy ]]; then + print_error "Initial import needs an empty package directory: $package_dir" + exit 1 + fi +done + +work=$(mktemp -d "$PKGBUILDS_DIR/.import-aur.XXXXXX") +trap 'rm -rf "$work"' EXIT +print_info "Importing $package from AUR package $aur_package..." +git clone --quiet "https://aur.archlinux.org/${aur_package}.git" "$work/recipe" +[[ -f "$work/recipe/PKGBUILD" ]] || { print_error "AUR package has no PKGBUILD"; exit 1; } +commit=$(git -C "$work/recipe" rev-parse HEAD) +rm -rf "$work/recipe/.git" "$work/recipe/.omarchy" +rm -f "$work/recipe/.SRCINFO" "$work/recipe/.gitignore" +cp -a "$package_dir/.omarchy" "$work/recipe/.omarchy" +jq --arg name "$aur_package" --arg commit "$commit" ' + .source = "local" | .origin = {aur: $name, commit: $commit} + | del(.aur, .upstream_commit) +' "$metadata" > "$work/recipe/.omarchy/package.json" +# Stage on the same filesystem, restoring the metadata directory on failure. +mv "$package_dir" "$work/original" +if ! mv "$work/recipe" "$package_dir"; then + mv "$work/original" "$package_dir" + exit 1 +fi +print_success "Imported $package; review the recipe and configure its direct upstream watch" diff --git a/bin/package-worktree b/bin/package-worktree index 8deca92..37ca4ed 100755 --- a/bin/package-worktree +++ b/bin/package-worktree @@ -17,13 +17,13 @@ Usage: $0 [OPTIONS] Create a scratch workspace for inspecting an AUR-backed package. The workspace contains: - upstream/ Raw AUR package at .omarchy/package.json upstream_commit, or HEAD + upstream/ Raw AUR package at the recorded origin.commit, or HEAD patched/ Raw AUR package with Omarchy .omarchy patches/hooks/pkgrel applied current/ Current checked-in package directory Options: --dir Workspace directory (default: mktemp under /tmp) - --commit Use a specific AUR commit instead of upstream_commit + --commit Use a specific AUR commit instead of origin.commit -h, --help Show this help message Examples: @@ -75,13 +75,13 @@ if [[ ! -f "$METADATA" ]]; then exit 1 fi -if [[ "$(jq -r '.source // ""' "$METADATA")" != "aur" ]]; then +if [[ "$(jq -r '.origin.aur // .aur // (if .source == "aur" then "legacy" else "" end)' "$METADATA")" == "" ]]; then print_error "package-worktree only supports AUR-backed packages" exit 1 fi -AUR_PACKAGE=$(jq -r --arg package "$PACKAGE" '.aur // $package' "$METADATA") -UPSTREAM_COMMIT=${COMMIT_OVERRIDE:-$(jq -r '.upstream_commit // ""' "$METADATA")} +AUR_PACKAGE=$(jq -r --arg package "$PACKAGE" '.origin.aur // .aur // $package' "$METADATA") +UPSTREAM_COMMIT=${COMMIT_OVERRIDE:-$(jq -r '.origin.commit // .upstream_commit // ""' "$METADATA")} if [[ -z "$DEST_DIR" ]]; then DEST_DIR=$(mktemp -d "${TMPDIR:-/tmp}/omarchy-${PACKAGE}.XXXXXX") @@ -224,7 +224,7 @@ print_info "AUR package: $AUR_PACKAGE" if [[ -n "$UPSTREAM_COMMIT" ]]; then print_info "Upstream commit: $UPSTREAM_COMMIT" else - print_warning "No upstream_commit recorded; using AUR HEAD" + print_warning "No origin.commit recorded; using AUR HEAD" fi rm -rf "$UPSTREAM_DIR" "$PATCHED_DIR" "$CURRENT_DIR" diff --git a/bin/sync-aur b/bin/sync-aur deleted file mode 100755 index 59af6ca..0000000 --- a/bin/sync-aur +++ /dev/null @@ -1,434 +0,0 @@ -#!/bin/bash -set -euo pipefail - -BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") -source "$BUILD_ROOT/helpers/message-helpers.sh" -source "$BUILD_ROOT/helpers/paths.sh" -source "$BUILD_ROOT/helpers/package-metadata.sh" - -TEMP_DIR=$(mktemp -d) -trap 'rm -rf "$TEMP_DIR"' EXIT - -SPECIFIC_PACKAGES=() - -usage() { - cat </. - -Package selection is driven by pkgbuilds//.omarchy/package.json: - { "source": "aur" } # synced from matching AUR package name - { "source": "aur", "aur": "yaru" } # synced from different AUR package name - { "source": "aur", "sync": false } # AUR-origin, but not auto-synced - -Arguments: - PACKAGE One or more package names to sync (optional) - -Examples: - $0 # Sync all AUR packages with sync enabled - $0 yay cursor-bin # Sync specific packages -EOF -} - -while [[ $# -gt 0 ]]; do - case "$1" in - -h|--help) - usage - exit 0 - ;; - --tier) - print_error "--tier is no longer supported; package metadata controls sync behavior" - exit 1 - ;; - --*) - print_error "Unknown option: $1" - exit 1 - ;; - *) - SPECIFIC_PACKAGES+=("$1") - shift - ;; - esac -done - -print_header "AUR Package Sync" -mkdir -p "$PKGBUILDS_DIR" - -SYNCED=0 -SKIPPED=0 -FAILED=0 -SYNCED_PACKAGES=() -SPECIFIC_MODE=false - -get_pkgbuild_field() { - local package_dir="$1" - local field="$2" - local value="" - - if [[ -f "$package_dir/PKGBUILD" ]]; then - value=$(grep -m1 "^${field}=" "$package_dir/PKGBUILD" | cut -d= -f2- | tr -d "\"'") || true - if [[ -n "$value" ]]; then - echo "$value" - return - fi - fi - - if [[ -f "$package_dir/.SRCINFO" ]]; then - awk -F' = ' -v field="$field" '$1 ~ "^[[:space:]]*" field "$" { print $2; exit }' "$package_dir/.SRCINFO" - fi -} - -set_pkgrel() { - local package_dir="$1" - local pkgrel="$2" - local pkgbuild="$package_dir/PKGBUILD" - - if [[ -f "$pkgbuild" ]]; then - sed -i "s/^pkgrel=.*/pkgrel=$pkgrel/" "$pkgbuild" - fi -} - -display_package_name() { - local package_dir="$1" - local name - name=$(basename "$package_dir") - echo "${name%.work}" -} - -remove_aur_only_files() { - local package_dir="$1" - - rm -f "$package_dir/.SRCINFO" "$package_dir/.gitignore" -} - -copy_aur_contents() { - local aur_dir="$1" - local target_dir="$2" - - mkdir -p "$target_dir" - - shopt -s dotglob nullglob - local item base - for item in "$aur_dir"/*; do - base=$(basename "$item") - [[ "$base" == ".git" ]] && continue - cp -a "$item" "$target_dir/" - done - shopt -u dotglob nullglob -} - -commit_synced_worktree() { - local work_dir="$1" - local target_dir="$2" - local parent base staged_dir backup_root backup_dir - - parent=$(dirname "$target_dir") - base=$(basename "$target_dir") - staged_dir=$(mktemp -d "$parent/.${base}.staged.XXXXXX") - backup_root=$(mktemp -d "$parent/.${base}.backup.XXXXXX") - backup_dir="$backup_root/$base" - - # Copy to the package filesystem before swapping. This keeps the original - # package directory intact if copying from /tmp fails or is interrupted. - if ! cp -a "$work_dir/." "$staged_dir/"; then - print_error "Failed to stage synced package for $base" - rm -rf "$staged_dir" "$backup_root" - return 1 - fi - - if [[ -e "$target_dir" ]]; then - if ! mv "$target_dir" "$backup_dir"; then - print_error "Failed to back up existing package directory: $target_dir" - rm -rf "$staged_dir" "$backup_root" - return 1 - fi - fi - - if ! mv "$staged_dir" "$target_dir"; then - print_error "Failed to install synced package directory: $target_dir" - if [[ -e "$backup_dir" ]]; then - mv "$backup_dir" "$target_dir" || true - fi - rm -rf "$staged_dir" "$backup_root" - return 1 - fi - - rm -rf "$backup_root" "$work_dir" -} - -set_upstream_commit() { - local package_dir="$1" - local commit="$2" - local metadata="$package_dir/.omarchy/package.json" - local tmpfile - - tmpfile=$(mktemp) - jq --arg commit "$commit" '.upstream_commit = $commit' "$metadata" > "$tmpfile" - mv "$tmpfile" "$metadata" -} - -apply_omarchy_patches() { - local package_dir="$1" - local patches_dir="$package_dir/.omarchy/patches" - local applied=false - - [[ -d "$patches_dir" ]] || return 1 - - shopt -s nullglob - local patch_files=("$patches_dir"/*.patch) - local patch_dir_files=("$patches_dir"/*) - shopt -u nullglob - - if [[ ${#patch_files[@]} -eq 0 ]]; then - if [[ ${#patch_dir_files[@]} -gt 0 ]]; then - print_warning "No .patch files found in $patches_dir" - fi - return 1 - fi - - print_info "Applying Omarchy patches for $(display_package_name "$package_dir")..." - local patch_file - for patch_file in "${patch_files[@]}"; do - print_info " $(basename "$patch_file")" - if ! (cd "$package_dir" && patch -p1 --forward --batch --no-backup-if-mismatch < "$patch_file"); then - print_error "Failed to apply patch: $patch_file" - return 2 - fi - applied=true - done - - [[ "$applied" == true ]] -} - -run_omarchy_post_sync_hook() { - local package_dir="$1" - local package="$2" - local aur_package="$3" - local aur_pkgrel="$4" - local hook="$package_dir/.omarchy/post-sync.sh" - - [[ -f "$hook" ]] || return 1 - - print_info "Running Omarchy post-sync hook for $(display_package_name "$package_dir")..." - if ! ( - cd "$package_dir" - PACKAGE_NAME="$package" \ - AUR_PACKAGE_NAME="$aur_package" \ - AUR_PKGREL="$aur_pkgrel" \ - bash ".omarchy/post-sync.sh" - ); then - print_error "Failed to run post-sync hook: $hook" - return 2 - fi - - return 0 -} - -apply_pkgrel_suffix_if_customized() { - local package_dir="$1" - local aur_pkgrel="$2" - - [[ -n "$aur_pkgrel" ]] || return 0 - - print_info "Applying Omarchy pkgrel suffix for $(display_package_name "$package_dir"): pkgrel=$aur_pkgrel.1" - set_pkgrel "$package_dir" "$aur_pkgrel.1" -} - -apply_pkgrel_override() { - local package_dir="$1" - local aur_pkgrel="$2" - local previous_pkgver="$3" - local metadata="$package_dir/.omarchy/package.json" - local pkgbuild="$package_dir/PKGBUILD" - - [[ -f "$metadata" ]] || return 1 - jq -e 'has("pkgrel")' "$metadata" >/dev/null || return 1 - - local current_pkgver suffix offset base rel tmpfile - # Read through the same accessor that produced previous_pkgver. Parsing it a - # second time here let a quoted pkgver= compare unequal to itself, which threw - # away the pkgrel metadata of an unchanged package on every sync. - current_pkgver=$(get_pkgbuild_field "$package_dir" pkgver) - - if [[ -n "$previous_pkgver" && "$current_pkgver" != "$previous_pkgver" ]]; then - print_info "Removing stale pkgrel metadata for $(display_package_name "$package_dir") (pkgver changed: $previous_pkgver -> $current_pkgver)" - tmpfile=$(mktemp) - jq 'del(.pkgrel)' "$metadata" > "$tmpfile" - mv "$tmpfile" "$metadata" - return 1 - fi - - suffix=$(jq -r '.pkgrel.suffix // 1' "$metadata") - offset=$(jq -r '.pkgrel.offset // 0' "$metadata") - - if [[ ! "$offset" =~ ^[0-9]+$ || ! "$aur_pkgrel" =~ ^[0-9]+$ ]]; then - print_error "pkgrel offset requires numeric AUR pkgrel for $(display_package_name "$package_dir")" - return 2 - fi - - base=$((aur_pkgrel + offset)) - rel="$base.$suffix" - - print_info "Applying pkgrel suffix for $(display_package_name "$package_dir"): AUR pkgrel=$aur_pkgrel, offset=$offset, suffix=$suffix -> pkgrel=$rel" - set_pkgrel "$package_dir" "$rel" - return 0 -} - -clone_aur_package() { - local aur_package="$1" - local dest="$2" - local clone_log="$TEMP_DIR/clone.log" - local attempt - - for attempt in 1 2 3; do - rm -rf "$dest" - if git clone "https://aur.archlinux.org/${aur_package}.git" "$dest" >"$clone_log" 2>&1; then - return 0 - fi - if [[ $attempt -lt 3 ]]; then - print_warning "Clone of $aur_package failed (attempt $attempt/3), retrying in 10s..." - sleep 10 - fi - done - - print_warning "Failed to clone $aur_package after 3 attempts: $(tail -n 1 "$clone_log")" - return 1 -} - -sync_package() { - local package="$1" - local package_dir="$PKGBUILDS_DIR/$package" - local metadata="$package_dir/.omarchy/package.json" - - if [[ ! -f "$metadata" ]]; then - if [[ "$SPECIFIC_MODE" == true ]]; then - print_error "Package $package is missing .omarchy/package.json" - ((++FAILED)) - else - print_warning "Skipping $package: missing .omarchy/package.json" - ((++SKIPPED)) - fi - return 0 - fi - - if [[ "$(jq -r '.source // ""' "$metadata")" != "aur" ]]; then - print_info "Skipping $package: source is not AUR" - ((++SKIPPED)) - return 0 - fi - - if [[ "$(jq -r 'if has("sync") then .sync else true end' "$metadata")" == "false" ]]; then - print_info "Skipping $package: AUR sync disabled" - ((++SKIPPED)) - return 0 - fi - - local aur_package - aur_package=$(jq -r --arg package "$package" '.aur // $package' "$metadata") - - if [[ "$aur_package" == "$package" ]]; then - print_info "Syncing $package from AUR..." - else - print_info "Syncing $package from AUR package $aur_package..." - fi - - cd "$TEMP_DIR" - - if ! clone_aur_package "$aur_package" "$TEMP_DIR/$aur_package"; then - ((++FAILED)) - return 0 - fi - - if [[ ! -f "$TEMP_DIR/$aur_package/PKGBUILD" ]]; then - print_warning "AUR repository for $aur_package is empty (package does not exist in AUR)" - ((++FAILED)) - return 0 - fi - - local aur_dir="$TEMP_DIR/$aur_package" - local work_dir="$TEMP_DIR/${package}.work" - local aur_pkgrel previous_pkgver upstream_commit - aur_pkgrel=$(get_pkgbuild_field "$aur_dir" pkgrel) - previous_pkgver=$(get_pkgbuild_field "$package_dir" pkgver || true) - upstream_commit=$(git -C "$aur_dir" rev-parse HEAD) - - rm -rf "$work_dir" - copy_aur_contents "$aur_dir" "$work_dir" - rm -rf "$work_dir/.omarchy" - cp -a "$package_dir/.omarchy" "$work_dir/.omarchy" - - local customized=false - - if apply_omarchy_patches "$work_dir"; then - customized=true - else - local patch_status=$? - if [[ $patch_status -eq 2 ]]; then - ((++FAILED)) - return 0 - fi - fi - - if run_omarchy_post_sync_hook "$work_dir" "$package" "$aur_package" "$aur_pkgrel"; then - customized=true - else - local hook_status=$? - if [[ $hook_status -eq 2 ]]; then - ((++FAILED)) - return 0 - fi - fi - - local pkgrel_overridden=false - set +e - apply_pkgrel_override "$work_dir" "$aur_pkgrel" "$previous_pkgver" - local pkgrel_status=$? - set -e - case "$pkgrel_status" in - 0) pkgrel_overridden=true ;; - 1) ;; - *) ((++FAILED)); return 0 ;; - esac - - if [[ "$customized" == true && "$pkgrel_overridden" == false ]]; then - apply_pkgrel_suffix_if_customized "$work_dir" "$aur_pkgrel" - fi - - remove_aur_only_files "$work_dir" - - set_upstream_commit "$work_dir" "$upstream_commit" - if ! commit_synced_worktree "$work_dir" "$package_dir"; then - ((++FAILED)) - return 0 - fi - - SYNCED_PACKAGES+=("$package") - ((++SYNCED)) -} - -if [[ ${#SPECIFIC_PACKAGES[@]} -gt 0 ]]; then - SPECIFIC_MODE=true - for package in "${SPECIFIC_PACKAGES[@]}"; do - sync_package "$package" - done -else - while IFS= read -r package; do - sync_package "$package" - done < <(packages_for_aur_sync) -fi - -echo "" -if [[ $FAILED -gt 0 ]]; then - print_error "Sync completed with failures" -else - print_success "Sync complete!" -fi -echo " Target: $PKGBUILDS_DIR" -echo " Synced: $SYNCED" -echo " Skipped: $SKIPPED" -echo " Failed: $FAILED" - -if [[ $FAILED -gt 0 ]]; then - exit 1 -fi diff --git a/bin/sync-upstream b/bin/sync-upstream index 046a39b..2f84506 100755 --- a/bin/sync-upstream +++ b/bin/sync-upstream @@ -9,6 +9,7 @@ source "$BUILD_ROOT/helpers/upstream-github.sh" TEMP_DIR=$(mktemp -d) trap 'rm -rf "$TEMP_DIR"' EXIT +export UPSTREAM_CACHE_DIR="$TEMP_DIR/watch-cache" SPECIFIC_PACKAGES=() @@ -332,6 +333,12 @@ sync_package() { return 0 fi + if jq -e '.sync == false' "$package_dir/.omarchy/package.json" >/dev/null 2>&1; then + print_info "Skipping $package: upstream updates held by sync=false" + ((++SKIPPED)) + return 0 + fi + local provider has_upstream=false provider=$(package_upstream_provider "$package_dir") if package_has_upstream_provider "$package_dir"; then @@ -372,6 +379,21 @@ sync_package() { print_info "Checking $package for upstream releases..." + if [[ "$provider" == watch ]]; then + local result + if ! result=$(python3 "$BUILD_ROOT/helpers/upstream-watch.py" sync "$package_dir" --min-age "$min_age"); then + print_error "Upstream watch failed for $package" + ((++FAILED)) + elif [[ $(jq -r .status <<<"$result") == updated ]]; then + print_success " $(jq -r '.before + " -> " + .after' <<<"$result")" + ((++UPDATED)) + else + print_info " $(jq -r '.reason' <<<"$result")" + ((++SKIPPED)) + fi + return 0 + fi + local release release_status=0 if [[ -n "$provider" ]]; then case "$provider" in diff --git a/docs/upstream-sources.md b/docs/upstream-sources.md new file mode 100644 index 0000000..9276bd2 --- /dev/null +++ b/docs/upstream-sources.md @@ -0,0 +1,178 @@ +# Direct upstream watches + +Omarchy owns the recipes in `pkgbuilds/`. `bin/sync-upstream` discovers new +releases directly from project/vendor feeds and updates versions, declared +release variables, and the source checksums already used by the recipe. It never +imports upstream PKGBUILDs or runs downloaded build scripts. Architecture support, +root install hooks, dependencies, and build functions remain ours to maintain. + +`upstream.watch` complements the existing declarative providers and custom hooks: + +```json +{ + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/walker", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + } +} +``` + +## Watch fields + +Choose exactly one provider: `github` (owner/repository), `git_tags` (repository +HTTPS URL), `git_branch` (repository URL plus explicit `branch`), `npm` or `pypi` +(package name), `debian` (Packages index plus exact `package`), `json` (URL plus +version `path`), `regex` (text URL), `redirect` (final HTTPS download URL), or +`archive` (inspect archive metadata without extracting/executing code). + +Tag, text, redirect and archive watches use an explicit `pattern` with a named +`version` capture. Tag patterns match the entire tag. `version` optionally formats +those captures into an Arch pkgver; e.g. Sublime uses `4.{version}`. JSON feeds can +expose additional capture values through `fields`, a name-to-JSON-path map. + +`variables` maps recipe scalars such as `_commit` or `_build` to capture templates. +Only explicitly declared underscore-prefixed variables can change. GitHub +`{commit}` resolves the selected tag, not a moving target_commitish branch. +`submodules` can map a recipe variable to a gitlink in the selected GitHub tag; +RustDesk uses this for hbb_common. Downloaded repository code is never evaluated. + +For upstreams that rebuild a release, declare a numeric `revision` template and +its `revision_variable`. With unchanged pkgver, only an increasing revision can +advance that variable, and the downstream pkgrel increments instead of resetting. +Cursor CLI uses `sequence` to preserve its date/counter/hash version convention +when the vendor publishes a second hash on the same day. A new pkgver resets +pkgrel to 1, but the complete epoch:pkgver-pkgrel must still increase. + +GitHub releases exclude drafts and prereleases unless `allow_prerelease` is true. +Existing `min_release_age` policies apply: a feed without a verifiable publication +time cannot bypass a configured hold. Git branch watches derive a commit count +and date from the actual branch history and write an immutable source pin. + +Checksums retain their algorithms (SHA256, SHA512, BLAKE2, etc.) and source order. +Changed git sources are hashed with makepkg's git-archive convention. Unchanged +sources retain their hashes; `mutable_sources` explicitly names entries such as +`source:0` that must be fetched again for a new version despite a stable URL. +Existing `SKIP` entries remain unchanged (including signed metadata verified by +the recipe); new skips are never introduced. Changed URLs are still fetched. +A matching GitHub release asset SHA256 digest avoids downloading large assets. +Missing architecture artifacts or malformed metadata fail the package atomically. +Every declared architecture must read back the same release and checksum values. + +Archive watches use `member` to select a text member, or `filenames: true` to read +versions from archive member names. Debian archives are read through their control +metadata. `unescape_json` handles JSON strings embedded in a vendor's HTML page. + +## Maintenance and validation + +Running watches locally requires Python 3.11+, Bash, curl, git, jq, Arch's +`vercmp`, and `bsdtar`. CI installs these in its Arch container. + +- Edit packaging and architecture changes directly in PKGBUILD. The old AUR + overlays have been folded into these recipes and removed. +- Keep source-code patches and install hooks checked in as ordinary package files. +- Bump pkgrel when changing a recipe at the same version. Removing a dotted AUR + suffix must never lower the complete version. +- Add a watch with each new package. `bin/add-package --source aur` is a one-time + import; it records historical `origin` metadata and leaves an owned recipe. +- `python helpers/upstream-watch.py check pkgbuilds/NAME` checks release discovery + without rewriting the recipe. `bin/sync-upstream NAME` performs the update. +- `python tests/upstream-watch.py` tests update atomicity, architecture coverage, + version ordering, source hashes and hostile metadata using offline fixtures. + +The scheduled workflow continues reviewing completed updates if another package +fails. The failing recipe stays unchanged and the run still reports failure. + +## Migrated package watches + +68 active AUR packages now use direct watches. The nine previously disabled +packages retain manual maintenance holds. Historical AUR provenance is recorded +in `origin` and has no effect on release selection. + +| Package | Provider | Upstream | +|---|---|---| +| `1password-beta` | debian | [https://downloads.1password.com/linux/debian/amd64/dists/beta/main/binary-amd64/Packages](https://downloads.1password.com/linux/debian/amd64/dists/beta/main/binary-amd64/Packages) | +| `1password-cli` | json | [https://app-updates.agilebits.com/check/1/0/CLI2/en/0](https://app-updates.agilebits.com/check/1/0/CLI2/en/0) | +| `aether` | github | [omacom/aether](https://github.com/omacom/aether) | +| `asusctl` | git_tags | [https://github.com/OpenGamingCollective/asusctl.git](https://github.com/OpenGamingCollective/asusctl.git) | +| `basecamp-cli` | github | [basecamp/basecamp-cli](https://github.com/basecamp/basecamp-cli) | +| `bun-bin` | github | [oven-sh/bun](https://github.com/oven-sh/bun) | +| `claude-code` | regex | [https://downloads.claude.ai/claude-code-releases/latest](https://downloads.claude.ai/claude-code-releases/latest) | +| `cliamp` | github | [bjarneo/cliamp](https://github.com/bjarneo/cliamp) | +| `crush-bin` | github | [charmbracelet/crush](https://github.com/charmbracelet/crush) | +| `cursor-bin` | json | [https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable](https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable) | +| `cursor-cli` | regex | [https://cursor.com/install](https://cursor.com/install) | +| `dbxcli-bin` | github | [dropbox/dbxcli](https://github.com/dropbox/dbxcli) | +| `dropbox` | redirect | [https://www.dropbox.com/download?plat=lnx.x86_64](https://www.dropbox.com/download?plat=lnx.x86_64) | +| `dropbox-cli` | regex | [https://linux.dropbox.com/packages/](https://linux.dropbox.com/packages/) | +| `elephant` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-all` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-archlinuxpkgs` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-bluetooth` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-calc` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-clipboard` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-desktopapplications` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-files` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-menus` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-providerlist` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-runner` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-symbols` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-todo` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-unicode` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `elephant-websearch` | github | [abenz1267/elephant](https://github.com/abenz1267/elephant) | +| `heroic-games-launcher-bin` | github | [Heroic-Games-Launcher/HeroicGamesLauncher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) | +| `hyprshade` | pypi | [hyprshade](https://pypi.org/project/hyprshade/) | +| `lib32-nvidia-580xx-utils` | regex | [https://download.nvidia.com/XFree86/Linux-x86_64/](https://download.nvidia.com/XFree86/Linux-x86_64/) | +| `limine-mkinitcpio-hook` | git_tags | [https://gitlab.com/Zesko/limine-entry-tool.git](https://gitlab.com/Zesko/limine-entry-tool.git) | +| `limine-snapper-sync` | git_tags | [https://gitlab.com/Zesko/limine-snapper-sync.git](https://gitlab.com/Zesko/limine-snapper-sync.git) | +| `lmstudio-bin` | regex | [https://lmstudio.ai/download](https://lmstudio.ai/download) | +| `localsend` | github | [localsend/localsend](https://github.com/localsend/localsend) | +| `localsend-bin` | github | [localsend/localsend](https://github.com/localsend/localsend) | +| `macbook12-spi-driver-dkms` | git_branch | [https://github.com/marc-git/macbook12-spi-driver.git](https://github.com/marc-git/macbook12-spi-driver.git) | +| `makima-bin` | github | [cyber-sushi/makima](https://github.com/cyber-sushi/makima) | +| `minecraft-launcher` | archive | [https://launcher.mojang.com/download/Minecraft.deb](https://launcher.mojang.com/download/Minecraft.deb) | +| `nautilus-dropbox` | github | [dropbox/nautilus-dropbox](https://github.com/dropbox/nautilus-dropbox) | +| `nautilus-open-any-terminal` | git_tags | [https://github.com/Stunkymonkey/nautilus-open-any-terminal.git](https://github.com/Stunkymonkey/nautilus-open-any-terminal.git) | +| `nordvpn-bin` | debian | [https://repo.nordvpn.com/deb/nordvpn/debian/dists/stable/main/binary-amd64/Packages](https://repo.nordvpn.com/deb/nordvpn/debian/dists/stable/main/binary-amd64/Packages) | +| `nvidia-580xx-utils` | regex | [https://download.nvidia.com/XFree86/Linux-x86_64/](https://download.nvidia.com/XFree86/Linux-x86_64/) | +| `omarchy-chromium-bin` | github | [omacom/omarchy-chromium](https://github.com/omacom/omarchy-chromium) | +| `omarchy-emacs` | git_tags | [https://github.com/scottjones/omarchy-emacs.git](https://github.com/scottjones/omarchy-emacs.git) | +| `omazed` | git_tags | [https://github.com/aps6/omazed.git](https://github.com/aps6/omazed.git) | +| `once-bin` | github | [basecamp/once](https://github.com/basecamp/once) | +| `openai-codex-bin` | github | [openai/codex](https://github.com/openai/codex) | +| `python-mediapipe` | github | [google-ai-edge/mediapipe](https://github.com/google-ai-edge/mediapipe) | +| `python-sounddevice` | pypi | [sounddevice](https://pypi.org/project/sounddevice/) | +| `python-terminaltexteffects` | pypi | [terminaltexteffects](https://pypi.org/project/terminaltexteffects/) | +| `rustdesk` | github | [rustdesk/rustdesk](https://github.com/rustdesk/rustdesk) | +| `spotify` | debian | [https://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages](https://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages) | +| `sublime-text-4` | json | [https://www.sublimetext.com/updates/4/stable_update_check](https://www.sublimetext.com/updates/4/stable_update_check) | +| `sunshine` | github | [LizardByte/Sunshine](https://github.com/LizardByte/Sunshine) | +| `ttf-ia-writer` | git_branch | [https://github.com/iaolo/iA-Fonts.git](https://github.com/iaolo/iA-Fonts.git) | +| `tuxedo-drivers-nocompatcheck-dkms` | git_tags | [https://gitlab.com/kronerm/tuxedo-drivers-nocompatcheck.git](https://gitlab.com/kronerm/tuxedo-drivers-nocompatcheck.git) | +| `typora` | debian | [https://downloads.typora.io/linux/Packages](https://downloads.typora.io/linux/Packages) | +| `ufw-docker` | git_tags | [https://github.com/chaifeng/ufw-docker.git](https://github.com/chaifeng/ufw-docker.git) | +| `vi` | regex | [https://sources.archlinux.org/other/vi/](https://sources.archlinux.org/other/vi/) | +| `visual-studio-code-bin` | json | [https://update.code.visualstudio.com/api/update/linux-deb-x64/stable/latest](https://update.code.visualstudio.com/api/update/linux-deb-x64/stable/latest) | +| `walker` | github | [abenz1267/walker](https://github.com/abenz1267/walker) | +| `xdg-terminal-exec` | git_tags | [https://gitlab.freedesktop.org/Vladimir-csp/xdg-terminal-exec.git](https://gitlab.freedesktop.org/Vladimir-csp/xdg-terminal-exec.git) | +| `xpadneo-dkms` | github | [atar-axis/xpadneo](https://github.com/atar-axis/xpadneo) | +| `yaru-icon-theme` | git_tags | [https://github.com/ubuntu/yaru.git](https://github.com/ubuntu/yaru.git) | +| `yay` | github | [Jguer/yay](https://github.com/Jguer/yay) | +| `yt6801-dkms` | archive | [https://www.motor-comm.com/Cn/Skippower/downloadFile.html?id=1817](https://www.motor-comm.com/Cn/Skippower/downloadFile.html?id=1817) | + +## Existing manual holds + +`grok-bot`, `libfprint-git`, `libretro-cap32-git`, `libretro-database-git`, `libretro-fbneo-git`, `libretro-uae-git`, `libretro-vice-git`, `quickshell-git`, `supergfxctl`. + +These packages were already excluded from automatic AUR updates. The migration preserves that policy. + +## Package-specific boundaries + +- NVIDIA watches remain on the 580 driver branch. +- Hardware-specific packages keep their declared architectures; this migration does not invent ARM binaries for x86-only upstreams. +- iA Duospace was deleted upstream. Its four legacy font files retain their original immutable pin while the other families track the current repository. +- RustDesk reads hbb_common from the release gitlink; its existing build-time dependency/toolchain checks remain in force. +- Spotify uses HTTPS and retains its signed Release/Packages verification. +- Source and build compatibility still need review when upstream code changes. Direct watches remove AUR recipe churn, not the need to maintain packaging. diff --git a/helpers/package-metadata.sh b/helpers/package-metadata.sh index c66aef1..a3ad047 100644 --- a/helpers/package-metadata.sh +++ b/helpers/package-metadata.sh @@ -3,15 +3,13 @@ # Expects package directories in $PKGBUILDS_DIR, each with: # .omarchy/package.json # -# Minimal schema: -# { "source": "aur" } -# { "source": "aur", "sync": false } -# { "source": "aur", "aur": "different-aur-name" } -# { "source": "aur", "release_ring": "fast" } -# { "source": "aur", "skip_build": true } -# { "source": "aur", "pkgrel": { "suffix": 1, "offset": 1 } } -# { "source": "aur", "rebuild_on": ["qt6-base"] } +# Minimal schema (legacy source:aur remains readable for initial imports): # { "source": "local" } +# { "source": "local", "sync": false } +# { "source": "local", "release_ring": "fast" } +# { "source": "local", "skip_build": true } +# { "source": "local", "rebuild_on": ["qt6-base"] } +# { "source": "local", "upstream": { "watch": { "github": "owner/repo", "pattern": "v(?P[0-9.]+)" } } } # { "source": "local", "channels": ["edge"] } # { "source": "local", "channels": ["edge", "rc", "stable"] } # { "source": "local", "min_release_age": "24h" } @@ -21,7 +19,7 @@ # { "source": "local", "upstream": { "npm": "@scope/package", "sources": { "any": ["{npm_tarball}"] } } } # { "source": "local", "upstream": { "debian": "https://example/debian/dists/stable/main/binary-amd64/Packages", "package": "example", "sources": { "any": ["https://example/releases/{pkgver}.tar.gz"] } } } # -# bin/sync-aur also writes upstream_commit for AUR-backed packages, and +# bin/import-aur records historical origin.aur and origin.commit; # bin/sync-rebuilds writes rebuilt_against for packages declaring rebuild_on. if [[ -z "${PKGBUILDS_DIR:-}" ]]; then @@ -523,8 +521,9 @@ validate_package_metadata() { if has("upstream") | not then true elif (.upstream | type) != "object" then false else .upstream | - ([has("github"), has("git_tags"), has("npm"), has("debian")] | map(select(.)) | length) == 1 - and if has("github") then + ([has("github"), has("git_tags"), has("npm"), has("debian"), has("watch")] | map(select(.)) | length) == 1 + and if has("watch") then (.watch | type == "object") + elif has("github") then (.github | type == "string" and test("\\A[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+\\z")) and (if has("checksums") then (.checksums | type == "string" and length > 0) else true end) and (if has("digests") then (.digests | type == "boolean") else true end) @@ -550,10 +549,14 @@ validate_package_metadata() { end end ' "$metadata" >/dev/null; then - echo "invalid upstream for $(basename "$pkgdir"): configure exactly one valid github, git_tags, npm, or debian provider" + echo "invalid upstream for $(basename "$pkgdir"): configure exactly one valid github, git_tags, npm, debian, or watch provider" return 1 fi + if jq -e '.upstream? | objects | has("watch")' "$metadata" >/dev/null; then + python3 "${BASH_SOURCE[0]%/*}/upstream-watch.py" validate "$pkgdir" || return 1 + fi + pkgrel_type=$(jq -r 'if has("pkgrel") then .pkgrel | type else "missing" end' "$metadata") case "$pkgrel_type" in object|missing) ;; diff --git a/helpers/upstream-github.sh b/helpers/upstream-github.sh index 6c7e1ba..f19da78 100644 --- a/helpers/upstream-github.sh +++ b/helpers/upstream-github.sh @@ -31,7 +31,7 @@ package_upstream_provider() { metadata=$(metadata_file_for_dir "$pkgdir") jq -r ' (.upstream? | objects) as $u - | [$u | keys[] | select(. == "github" or . == "git_tags" or . == "npm" or . == "debian")] + | [$u | keys[] | select(. == "github" or . == "git_tags" or . == "npm" or . == "debian" or . == "watch")] | if length == 1 then .[0] else "" end ' "$metadata" } diff --git a/helpers/upstream-watch.py b/helpers/upstream-watch.py new file mode 100644 index 0000000..6e17b97 --- /dev/null +++ b/helpers/upstream-watch.py @@ -0,0 +1,566 @@ +#!/usr/bin/env python3 +"""Discover releases and update our own recipes; never import upstream build code. + +The watch selects release metadata. Sources, supported architectures, integrity +algorithms and packaging behavior stay in the checked-in PKGBUILD. Only release +scalars and checksum arrays are replaced, atomically, after every source passes. +""" +import argparse +import datetime as dt +import gzip +import hashlib +import io +import json +import os +from pathlib import Path +import re +import subprocess +import sys +import tarfile +import tempfile +from urllib.parse import quote, urlsplit +import zipfile + +PROVIDERS = {"github", "git_tags", "git_branch", "npm", "pypi", "debian", "json", "regex", "archive", "redirect"} +VERSION = re.compile(r"[A-Za-z0-9][A-Za-z0-9._+]*\Z") +SCALAR = re.compile(r"[A-Za-z0-9._+/-]+\Z") +SUM = re.compile(r"(md5|sha1|sha224|sha256|sha384|sha512|b2)sums(_[a-z0-9_]+)?\Z") +HASHES = {"b2": "blake2b"} + + +def run(args, **kwargs): + return subprocess.check_output(args, **kwargs) + + +def vercmp(a, b): + return int(run(["vercmp", a, b], text=True).strip()) + + +def https(url): + parts = urlsplit(url) + if parts.scheme != "https" or not parts.hostname or parts.username or parts.password or re.search(r"[\s\x00-\x1f]", url): + raise ValueError(f"expected an HTTPS upstream URL: {url!r}") + return url + + +class Fetcher: + def __init__(self, cache): + self.cache = Path(cache) + self.cache.mkdir(parents=True, exist_ok=True) + + def file(self, url): + https(url) + dest = self.cache / hashlib.sha256(url.encode()).hexdigest() + if not dest.exists(): + scratch = dest.with_suffix(f".{os.getpid()}.tmp") + command = ["curl", "--proto", "=https", "--proto-redir", "=https", "-fsSL", + "--connect-timeout", "20", "--max-time", "300", "--retry", "2", "-o", str(scratch), url] + # Credentials only go to GitHub's API, never to release assets or vendors. + token = os.environ.get("UPSTREAM_GITHUB_TOKEN") + if token and urlsplit(url).hostname == "api.github.com": + command[1:1] = ["--config", "-"] + subprocess.run(command, input=f'header = "Authorization: Bearer {token}"\n', text=True, check=True) + else: + subprocess.run(command, check=True) + scratch.replace(dest) + return dest + + def text(self, url): + data = self.file(url).read_bytes() + if data.startswith(b"\x1f\x8b"): + data = gzip.decompress(data) + return data.decode() + + def json(self, url): + return json.loads(self.text(url)) + + +def validate(watch): + if not isinstance(watch, dict) or len(PROVIDERS & watch.keys()) != 1: + raise ValueError("watch must select exactly one release provider") + provider = next(iter(PROVIDERS & watch.keys())) + allowed = PROVIDERS | {"pattern", "path", "package", "branch", "variables", "fields", + "submodules", "allow_prerelease", "unescape_json", "filenames", + "sequence", "version", "revision", "revision_variable", + "mutable_sources", "member", "dist_tag"} + if watch.keys() - allowed: + raise ValueError(f"unknown watch fields: {sorted(watch.keys() - allowed)}") + value = watch[provider] + if not isinstance(value, str) or not value: + raise ValueError(f"invalid watch.{provider}") + if provider == "github": + if not re.fullmatch(r"[\w.-]+/[\w.-]+", value): + raise ValueError("invalid GitHub repository") + elif provider in {"npm", "pypi"}: + if not re.fullmatch(r"(?:@[\w.-]+/)?[\w.-]+", value): + raise ValueError("invalid registry package") + else: + https(value) + if "pattern" in watch or provider in {"github", "git_tags", "regex", "archive", "redirect"}: + if not isinstance(watch.get("pattern"), str): + raise ValueError("watch needs an explicit release pattern") + pattern = re.compile(watch["pattern"]) + if "version" not in pattern.groupindex: + raise ValueError("release pattern needs a named version group") + if provider == "json" and (not isinstance(watch.get("path"), str) or not watch["path"]): + raise ValueError("JSON watch needs a version path") + if provider == "debian": + name = watch.get("package", "") + if not isinstance(name, str) or not re.fullmatch(r"[a-z0-9][a-z0-9+.-]*", name): + raise ValueError("Debian watch needs an exact package name") + if provider == "git_branch": + branch = watch.get("branch", "") + if not isinstance(branch, str) or not branch or branch.startswith("-"): + raise ValueError("git branch watch needs an explicit branch") + run(["git", "check-ref-format", "refs/heads/" + branch]) + for field in ("variables", "submodules", "fields"): + mapping = watch.get(field, {}) + if not isinstance(mapping, dict): + raise ValueError(f"watch.{field} must be a string mapping") + for name, value in mapping.items(): + pattern = r"[a-z][a-z0-9_]*" if field == "fields" else r"_[a-z][a-z0-9_]*" + if not re.fullmatch(pattern, name) or not isinstance(value, str) or not value: + raise ValueError(f"invalid watch.{field} mapping") + if "submodules" in watch and provider != "github": + raise ValueError("submodules require a GitHub watch") + if watch.get("variables", {}).keys() & watch.get("submodules", {}).keys(): + raise ValueError("a release variable cannot also be a submodule") + for path in watch.get("submodules", {}).values(): + if path.startswith("/") or any(part in {"", ".", ".."} for part in path.split("/")): + raise ValueError("submodule path must be relative to the release repository") + for field in ("allow_prerelease", "unescape_json", "filenames", "sequence"): + if field in watch and not isinstance(watch[field], bool): + raise ValueError(f"watch.{field} must be boolean") + for field in ("version", "revision", "member", "dist_tag"): + if field in watch and (not isinstance(watch[field], str) or not watch[field]): + raise ValueError(f"watch.{field} must be a string template") + if "revision_variable" in watch: + name = watch["revision_variable"] + if not isinstance(name, str) or name not in watch.get("variables", {}) or not watch.get("revision"): + raise ValueError("revision_variable requires a declared variable and revision template") + for field in ("mutable_sources",): + entries = watch.get(field, []) + if not isinstance(entries, list) or any(not isinstance(v, str) or not re.fullmatch(r"source(?:_[a-z0-9_]+)?:[0-9]+", v) for v in entries): + raise ValueError(f"watch.{field} must name source-array:index entries") + return provider + + +def json_path(data, path): + for key in path.split("."): + data = data[int(key)] if isinstance(data, list) else data[key] + return data + + +def candidate(watch, values): + values = {k: str(v) for k, v in values.items() if v is not None} + version = watch.get("version", "{version}").format_map(values) + if not VERSION.fullmatch(version): + raise ValueError(f"unusable upstream version: {version!r}") + revision = watch.get("revision", "").format_map(values) + if revision and not re.fullmatch(r"[0-9]+", revision): + raise ValueError("upstream release revision must be numeric") + return {"pkgver": version, "values": values, + "published_at": values.get("published_at"), + "revision": revision} + + +def matches(watch, text, extra=None, full=False): + pattern = re.compile(watch["pattern"]) + found = [pattern.fullmatch(text)] if full else pattern.finditer(text) + for match in found: + if match: + yield candidate(watch, {**(extra or {}), **match.groupdict()}) + + +def discover(watch, fetch): + provider = validate(watch) + feed = watch[provider] + results = [] + if provider == "github": + releases = fetch.json(f"https://api.github.com/repos/{feed}/releases?per_page=100") + if not isinstance(releases, list): + raise ValueError("GitHub did not return a release list") + for release in releases: + if release.get("draft") or (release.get("prerelease") and not watch.get("allow_prerelease")): + continue + for item in matches(watch, release["tag_name"], {"tag": release["tag_name"], "published_at": release["published_at"]}, full=True): + item["assets"] = release.get("assets", []) + results.append(item) + elif provider == "git_tags": + refs = run(["git", "ls-remote", "--tags", feed], text=True) + tags = {} + for line in refs.splitlines(): + commit, ref = line.split() + tag = ref.removeprefix("refs/tags/") + if tag.endswith("^{}"): + tags[tag[:-3]] = commit + else: + tags.setdefault(tag, commit) + for tag, commit in tags.items(): + results.extend(matches(watch, tag, {"tag": tag, "commit": commit}, full=True)) + elif provider == "git_branch": + with tempfile.TemporaryDirectory(prefix="upstream-git-") as work: + subprocess.run(["git", "clone", "--quiet", "--bare", "--filter=blob:none", "--single-branch", "--branch", watch["branch"], feed, work], check=True) + commit = run(["git", "-C", work, "rev-parse", "HEAD"], text=True).strip() + count = run(["git", "-C", work, "rev-list", "--count", "HEAD"], text=True).strip() + date = run(["git", "-C", work, "show", "-s", "--format=%cs", "HEAD"], text=True).strip().replace("-", "") + timestamp = run(["git", "-C", work, "show", "-s", "--format=%cI", "HEAD"], text=True).strip() + results.append(candidate(watch, {"version": date, "date": date, "count": count, "commit": commit, "published_at": timestamp})) + elif provider == "npm": + data = fetch.json("https://registry.npmjs.org/" + quote(feed, safe="")) + version = data["dist-tags"][watch.get("dist_tag", "latest")] + results.append(candidate(watch, {"version": version, "published_at": data.get("time", {}).get(version)})) + elif provider == "pypi": + data = fetch.json(f"https://pypi.org/pypi/{feed}/json") + version = data["info"]["version"] + dates = [r["upload_time_iso_8601"] for r in data["releases"].get(version, []) if not r.get("yanked")] + if not dates: + raise ValueError("PyPI release has no unyanked files") + results.append(candidate(watch, {"version": version, "published_at": max(dates)})) + elif provider == "debian": + for stanza in re.split(r"\n\s*\n", fetch.text(feed).replace("\r", "")): + fields = dict(re.findall(r"^([A-Za-z0-9-]+): (.*)$", stanza, re.M)) + if fields.get("Package") != watch["package"]: + continue + if "pattern" in watch: + results.extend(matches(watch, fields["Version"], full=True)) + else: + results.append(candidate(watch, {"version": fields["Version"]})) + elif provider == "json": + data = fetch.json(feed) + values = {"version": json_path(data, watch["path"])} + values.update({name: json_path(data, path) for name, path in watch.get("fields", {}).items()}) + results.append(candidate(watch, values)) + elif provider == "redirect": + final_url = run(["curl", "--proto", "=https", "--proto-redir", "=https", "-fsSLI", "--max-time", "60", "-o", "/dev/null", "-w", "%{url_effective}", feed], text=True) + results.extend(matches(watch, final_url)) + elif provider == "regex": + text = fetch.text(feed) + if watch.get("unescape_json"): + text = text.replace('\\"', '"') + results.extend(matches(watch, text)) + elif provider == "archive": + file = fetch.file(feed) + if zipfile.is_zipfile(file): + with zipfile.ZipFile(file) as archive: + names = archive.namelist() + if watch.get("filenames"): + results.extend(matches(watch, "\n".join(names))) + for name in ([] if watch.get("filenames") else names): + if re.fullmatch(watch.get("member", ".*"), name): + results.extend(matches(watch, archive.read(name).decode())) + elif file.read_bytes()[:8] == b"!\n": + names = run(["bsdtar", "-tf", str(file)], text=True).splitlines() + controls = [name for name in names if name.startswith("control.tar")] + if len(controls) != 1: + raise ValueError("deb does not contain exactly one control archive") + data = run(["bsdtar", "-xOf", str(file), controls[0]]) + with tarfile.open(fileobj=io.BytesIO(data)) as archive: + members = [m for m in archive if m.name.removeprefix("./") == "control"] + if len(members) != 1: + raise ValueError("deb control file is missing or ambiguous") + results.extend(matches(watch, archive.extractfile(members[0]).read().decode())) + else: + with tarfile.open(file) as archive: + for member in archive: + if member.isfile() and re.fullmatch(watch.get("member", ".*"), member.name): + results.extend(matches(watch, archive.extractfile(member).read().decode())) + if not results: + raise ValueError(f"no matching releases in {feed}") + return results + + +def select_release(releases, min_age=0, now=None, bypass=False): + now = now or dt.datetime.now(dt.timezone.utc) + best = None + for release in releases: + if min_age and not bypass: + value = release.get("published_at") + if not value or not re.fullmatch(r"\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?(?:Z|[+-]\d\d:?\d\d)", value): + raise ValueError("release age cannot be established") + if (now - dt.datetime.fromisoformat(value.replace("Z", "+00:00"))).total_seconds() < min_age: + continue + order = vercmp(release["pkgver"], best["pkgver"]) if best else 1 + if best and order == 0: + order = vercmp(release["revision"] or "0", best["revision"] or "0") + if order > 0: + best = release + return best + + +DUMP = r''' +source "$1" >/dev/null || exit 1 +set +u +for __watch_name in pkgver pkgrel epoch arch $(compgen -A variable | LC_ALL=C sort); do + case "$__watch_name" in + pkgver|pkgrel|epoch|arch|source|source_*|md5sums*|sha1sums*|sha224sums*|sha256sums*|sha384sums*|sha512sums*|b2sums*|_*) + [[ $__watch_name == __watch_* ]] && continue + declare -n __watch_value="$__watch_name" + printf '%s\0' "$__watch_name" "${#__watch_value[@]}" "${__watch_value[@]}" + unset -n __watch_value + ;; + esac +done +''' + + +def read_recipe(path, arch="x86_64"): + with tempfile.TemporaryDirectory(prefix="recipe-read-") as work: + env = {**os.environ, "CARCH": arch, "SRCDEST": work, "srcdir": work, "pkgdir": work} + data = run(["bash", "-c", DUMP, "_", str(path.resolve())], cwd=path.parent, env=env).decode().split("\0") + result = {} + index = 0 + while index < len(data) - 1: + name, size = data[index:index + 2] + index += 2 + size = int(size) + result[name] = data[index:index + size] + index += size + return result + + +def scalar(recipe, name, default=""): + return recipe.get(name, [default])[0] if recipe.get(name) else default + + +def replace_scalar(text, name, value): + if not SCALAR.fullmatch(value): + raise ValueError(f"unsafe {name} value") + pattern = re.compile(r"^" + re.escape(name) + r"=.*$", re.M) + if len(pattern.findall(text)) != 1: + raise ValueError(f"expected one top-level {name}= assignment") + return pattern.sub(lambda _: f"{name}={value}", text) + + +def replace_array(text, name, values): + starts = list(re.finditer(r"^" + re.escape(name) + r"=\(", text, re.M)) + if len(starts) != 1: + raise ValueError(f"expected one top-level {name}= array") + start = starts[0] + depth, quote_char, escaped, comment = 1, None, False, False + for index in range(start.end(), len(text)): + char = text[index] + if comment: + if char == "\n": comment = False + elif escaped: + escaped = False + elif char == "\\" and quote_char != "'": + escaped = True + elif quote_char: + if char == quote_char: quote_char = None + elif char in "\"'": quote_char = char + elif char == "#" and (index == 0 or text[index - 1].isspace()): comment = True + elif char == "(": depth += 1 + elif char == ")": + depth -= 1 + if depth == 0: + replacement = name + "=(" + " ".join("'" + value + "'" for value in values) + ")" + return text[:start.start()] + replacement + text[index + 1:] + raise ValueError(f"unclosed {name} array") + + +def bump_pkgrel(value): + if not re.fullmatch(r"[0-9]+(?:\.[0-9]+)?", value): + raise ValueError(f"invalid pkgrel: {value}") + components = value.split(".") + components[-1] = str(int(components[-1]) + 1) + return ".".join(components) + + +def complete_version(recipe): + return f"{scalar(recipe, 'epoch', '0')}:{scalar(recipe, 'pkgver')}-{scalar(recipe, 'pkgrel')}" + + +def hash_file(path, algorithm): + with path.open("rb") as stream: + return hashlib.file_digest(stream, HASHES.get(algorithm, algorithm)).hexdigest() + + +def source_url(source): + return source.split("::", 1)[-1] + + +def git_source_file(url, cache): + base, fragment = url.removeprefix("git+").split("#", 1) + kind, ref = fragment.split("=", 1) + https(base) + if kind not in {"tag", "commit"} or (kind == "commit" and not re.fullmatch(r"[0-9a-f]{40}", ref)): + raise ValueError("VCS sources must name an immutable commit or a checksummed tag") + if kind == "tag": + run(["git", "check-ref-format", "refs/tags/" + ref]) + dest = cache / (hashlib.sha256(url.encode()).hexdigest() + ".git.tar") + if not dest.exists(): + with tempfile.TemporaryDirectory(prefix="upstream-source-", dir=cache) as work: + subprocess.run(["git", "init", "--quiet", "--bare", work], check=True) + subprocess.run(["git", "-C", work, "fetch", "--quiet", "--depth=1", base, "refs/tags/" + ref if kind == "tag" else ref], check=True) + scratch = Path(work) / "source.tar" + with scratch.open("wb") as output: + subprocess.run(["git", "-c", "core.abbrev=no", "-C", work, "archive", "--format", "tar", "FETCH_HEAD"], stdout=output, check=True) + # The cache must never retain partial archives after a git failure. + scratch.replace(dest) + return dest + + +def updated_checksums(before, after, package, fetch, release, watch): + arrays = {} + source_names = {key for key in before if key == "source" or key.startswith("source_")} + if source_names != {key for key in after if key == "source" or key.startswith("source_")}: + raise ValueError("release changed the set of source architectures") + for source_name in sorted(source_names): + old_sources, sources = before[source_name], after[source_name] + suffix = source_name.removeprefix("source") + names = [name for name in before if SUM.fullmatch(name) and (SUM.fullmatch(name)[2] or "") == suffix] + if not sources: + continue + if len(sources) != len(old_sources) or not names: + raise ValueError(f"{source_name}: sources changed shape or have no checksums") + for name in names: + if len(before[name]) != len(sources): + raise ValueError(f"{name}: source/checksum count mismatch") + values = [] + algorithm = SUM.fullmatch(name)[1] + for index, source in enumerate(sources): + old = before[name][index] + if source == old_sources[index] and f"{source_name}:{index}" not in watch.get("mutable_sources", []): + values.append(old) + continue + url = source_url(source) + # A release API digest can supply SHA256 without downloading a + # large asset, but only when its exact declared URL matches. + assets = [a for a in release.get("assets", []) if a.get("browser_download_url") == url] + if algorithm == "sha256" and len(assets) == 1 and re.fullmatch(r"sha256:[0-9a-f]{64}", assets[0].get("digest") or ""): + values.append("SKIP" if old == "SKIP" else assets[0]["digest"][7:]) + continue + if url.startswith("git+https://"): + file = git_source_file(url, fetch.cache) + elif url.startswith("https://"): + file = fetch.file(url) + elif "://" not in url: + file = (package / url).resolve() + if not file.is_relative_to(package.resolve()) or not file.is_file(): + raise ValueError(f"unsafe local source: {url}") + else: + raise ValueError(f"unsupported source transport: {url}") + # Preserve existing signature/prepare()-verified sources. Never + # introduce SKIP; still fetch changed URLs to verify availability. + values.append("SKIP" if old == "SKIP" else hash_file(file, algorithm)) + if values != before[name]: + arrays[name] = values + return arrays + + +def resolve_release_fields(watch, release, fetch): + values = release["values"].copy() + if "github" in watch and any("{commit}" in value for value in watch.get("variables", {}).values()): + ref = fetch.json(f"https://api.github.com/repos/{watch['github']}/git/ref/tags/{quote(values['tag'], safe='')}")['object'] + if ref['type'] == 'tag': + ref = fetch.json(f"https://api.github.com/repos/{watch['github']}/git/tags/{ref['sha']}")['object'] + if ref['type'] != 'commit' or not re.fullmatch(r"[0-9a-f]{40}", ref['sha']): + raise ValueError("release tag does not resolve to a commit") + values['commit'] = ref['sha'] + variables = {k: template.format_map(values) for k, template in watch.get('variables', {}).items()} + for name, path in watch.get('submodules', {}).items(): + entry = fetch.json(f"https://api.github.com/repos/{watch['github']}/contents/{quote(path, safe='/')}?ref={quote(values['tag'], safe='')}") + if not entry.get('submodule_git_url') or not re.fullmatch(r"[0-9a-f]{40}", entry.get('sha', '')): + raise ValueError(f"release does not contain submodule {path}") + variables[name] = entry['sha'] + if any(not SCALAR.fullmatch(value) for value in variables.values()): + raise ValueError("unsafe release variable value") + release['variables'] = variables + return release + + +def sync(package, fetch, min_age=0, check=False): + metadata = json.loads((package / ".omarchy/package.json").read_text()) + if metadata.get("sync") is False: + return {"status": "skipped", "reason": "upstream updates held by sync=false"} + watch = metadata["upstream"]["watch"] + validate(watch) + path = package / "PKGBUILD" + original = path.read_text() + before = read_recipe(path) + release = select_release(discover(watch, fetch), min_age, bypass=os.environ.get("BYPASS_MIN_RELEASE_AGE") == "1") + if release is None: + return {"status": "skipped", "reason": "minimum release age"} + current = scalar(before, "pkgver") + if watch.get('sequence'): + prefix, counter, identity = current.rsplit('.', 2) + new_prefix, new_identity = release['values']['version'], release['values']['hash'] + if new_prefix == prefix: + release['pkgver'] = current if new_identity == identity else f"{prefix}.{int(counter) + 1}.{new_identity}" + order = vercmp(release["pkgver"], current) + if order < 0: + return {"status": "skipped", "current": current, "available": release["pkgver"], "reason": "upstream is older"} + if order == 0 and not watch.get("revision_variable"): + return {"status": "skipped", "current": current, "reason": "already current"} + release = resolve_release_fields(watch, release, fetch) + changed_variables = {k: v for k, v in release["variables"].items() if scalar(before, k) != v} + if order == 0 and not changed_variables: + return {"status": "skipped", "current": current, "reason": "already current"} + if order == 0 and changed_variables: + # Only a declared, forward-moving release revision can rebuild the same + # version. A changed hash/commit alone is an immutable-release violation. + revision_field = watch.get("revision_variable") + if revision_field not in changed_variables or vercmp(changed_variables[revision_field], scalar(before, revision_field, "0")) <= 0: + raise ValueError("release metadata changed without a newer version/revision") + new_pkgrel = "1" if order > 0 else bump_pkgrel(scalar(before, "pkgrel")) + text = replace_scalar(original, "pkgver", release["pkgver"]) + text = replace_scalar(text, "pkgrel", new_pkgrel) + for name, value in release["variables"].items(): + text = replace_scalar(text, name, value) + if check: + return {"status": "available", "current": current, "release": release} + scratch = path.with_name("PKGBUILD.sync-upstream") + try: + scratch.write_text(text) + after = read_recipe(scratch) + if scalar(after, "pkgver") != release["pkgver"] or scalar(after, "pkgrel") != new_pkgrel: + raise ValueError("recipe did not retain the release version") + if vercmp(complete_version(after), complete_version(before)) <= 0: + raise ValueError("complete package version must increase") + if before["arch"] != after["arch"]: + raise ValueError("release changed supported architectures") + arrays = updated_checksums(before, after, package, fetch, release, watch) + for name, values in arrays.items(): + text = replace_array(text, name, values) + scratch.write_text(text) + subprocess.run(["bash", "-n", str(scratch)], check=True) + for arch in before["arch"]: + result = read_recipe(scratch, "x86_64" if arch == "any" else arch) + if complete_version(result) != complete_version(after): + raise ValueError(f"{arch}: inconsistent release version") + for name, values in arrays.items(): + if result.get(name) != values: + raise ValueError(f"{arch}: rewritten {name} differs from the checked source hashes") + for name in after: + if name == "source" or name.startswith("source_"): + if result.get(name) != after[name]: + raise ValueError(f"{arch}: conditional {name} differs from the checked sources; use source_ arrays") + scratch.chmod(path.stat().st_mode) + scratch.replace(path) + return {"status": "updated", "before": complete_version(before), "after": complete_version(after)} + finally: + scratch.unlink(missing_ok=True) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("command", choices=["sync", "check", "validate"]) + parser.add_argument("package", type=Path) + parser.add_argument("--min-age", type=int, default=0) + args = parser.parse_args() + package = args.package.resolve() + if args.command == "validate": + validate(json.loads((package / ".omarchy/package.json").read_text())["upstream"]["watch"]) + return + with tempfile.TemporaryDirectory(prefix="upstream-watch-") as cache: + fetch = Fetcher(os.environ.get("UPSTREAM_CACHE_DIR", cache)) + print(json.dumps(sync(package, fetch, args.min_age, check=args.command == "check"))) + + +if __name__ == "__main__": + try: + main() + except (ValueError, KeyError, TypeError, IndexError, re.error, OSError, subprocess.CalledProcessError) as error: + print(f"upstream watch failed: {error}", file=sys.stderr) + sys.exit(1) diff --git a/pkgbuilds/1password-beta/.omarchy/package.json b/pkgbuilds/1password-beta/.omarchy/package.json index 6954e98..61c481a 100644 --- a/pkgbuilds/1password-beta/.omarchy/package.json +++ b/pkgbuilds/1password-beta/.omarchy/package.json @@ -1,5 +1,19 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "18d2de51dc01c9a58c1e8e96262f7afadcbf0648" + "upstream": { + "watch": { + "debian": "https://downloads.1password.com/linux/debian/amd64/dists/beta/main/binary-amd64/Packages", + "package": "1password", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)~(?P[0-9]+)\\.BETA", + "version": "{version}_{build}.BETA", + "variables": { + "_tarver": "{version}-{build}.BETA" + } + } + }, + "origin": { + "aur": "1password-beta", + "commit": "18d2de51dc01c9a58c1e8e96262f7afadcbf0648" + } } diff --git a/pkgbuilds/1password-beta/.omarchy/post-sync.sh b/pkgbuilds/1password-beta/.omarchy/post-sync.sh deleted file mode 100755 index 40bf26a..0000000 --- a/pkgbuilds/1password-beta/.omarchy/post-sync.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/bash -set -euo pipefail - -# Keep the AUR x86_64 checksums and add aarch64 sources. The aarch64 -# artifacts are signed by 1Password's validpgpkeys, so we skip checksums there -# instead of baking version-specific hashes into Omarchy metadata. -set +u -CARCH=x86_64 source PKGBUILD -set -u - -if declare -p sha256sums >/dev/null 2>&1 && [[ ${#sha256sums[@]} -ge 2 ]]; then - x86_sums=("${sha256sums[@]}") -elif declare -p sha256sums_x86_64 >/dev/null 2>&1 && [[ ${#sha256sums_x86_64[@]} -ge 2 ]]; then - x86_sums=("${sha256sums_x86_64[@]}") -else - echo "Unable to read x86_64 checksums from PKGBUILD" >&2 - exit 1 -fi - -sha256_from_url() { - curl -fsSL "$1" | sha256sum | awk '{ print $1 }' -} - -arm_url="https://downloads.1password.com/linux/tar/beta/aarch64/1password-${_tarver}.arm64.tar.gz" -arm_tar_sum=$(sha256_from_url "$arm_url") -arm_sig_sum=$(sha256_from_url "$arm_url.sig") - -emit_archdir() { - cat <<'EOF' -case "${CARCH}" in - x86_64) - _archdir="x64" - ;; - aarch64) - _archdir="arm64" - ;; -esac -EOF -} - -emit_sources() { - cat <> "$tmpfile" - ;; - "arch=('x86_64')") - echo "arch=('x86_64' 'aarch64')" >> "$tmpfile" - ;; - source=\(*) - emit_sources >> "$tmpfile" - ;; - sha256sums=\(*) - [[ "$line" == *")" ]] || skip_checksums=true - ;; - *) - line=${line//1password-\$\{_tarver\}.x64/1password-\$\{_tarver\}.\$\{_archdir\}} - printf '%s\n' "$line" >> "$tmpfile" - ;; - esac -done < PKGBUILD - -mv "$tmpfile" PKGBUILD diff --git a/pkgbuilds/1password-beta/PKGBUILD b/pkgbuilds/1password-beta/PKGBUILD index b556322..f351980 100644 --- a/pkgbuilds/1password-beta/PKGBUILD +++ b/pkgbuilds/1password-beta/PKGBUILD @@ -9,8 +9,8 @@ case "${CARCH}" in _archdir="arm64" ;; esac -pkgver=${_tarver//-/_} -pkgrel=25.1 +pkgver=8.12.38_25.BETA +pkgrel=25.2 conflicts=('1password' '1password-beta-bin') pkgdesc="Password manager and secure wallet" arch=('x86_64' 'aarch64') diff --git a/pkgbuilds/1password-cli/.omarchy/package.json b/pkgbuilds/1password-cli/.omarchy/package.json index f879ccc..70b0c87 100644 --- a/pkgbuilds/1password-cli/.omarchy/package.json +++ b/pkgbuilds/1password-cli/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "b0d208821677a5dbb883a8b92f06a5c92b9e861a" + "upstream": { + "watch": { + "json": "https://app-updates.agilebits.com/check/1/0/CLI2/en/0", + "path": "version" + } + }, + "origin": { + "aur": "1password-cli", + "commit": "b0d208821677a5dbb883a8b92f06a5c92b9e861a" + } } diff --git a/pkgbuilds/aether/.omarchy/package.json b/pkgbuilds/aether/.omarchy/package.json index 153a088..3664d9b 100644 --- a/pkgbuilds/aether/.omarchy/package.json +++ b/pkgbuilds/aether/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "0f047f40a200121075ca3cedce59ddf226f2a0f1" + "upstream": { + "watch": { + "github": "omacom/aether", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "aether", + "commit": "0f047f40a200121075ca3cedce59ddf226f2a0f1" + } } diff --git a/pkgbuilds/asusctl/.omarchy/package.json b/pkgbuilds/asusctl/.omarchy/package.json index 1b2f22a..19004c8 100644 --- a/pkgbuilds/asusctl/.omarchy/package.json +++ b/pkgbuilds/asusctl/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "b0ec6ca495eb331a684db91b0fe12085a868b632" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://github.com/OpenGamingCollective/asusctl.git", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "asusctl", + "commit": "b0ec6ca495eb331a684db91b0fe12085a868b632" + } } diff --git a/pkgbuilds/basecamp-cli/.omarchy/package.json b/pkgbuilds/basecamp-cli/.omarchy/package.json index 9dce3d6..37b7a70 100644 --- a/pkgbuilds/basecamp-cli/.omarchy/package.json +++ b/pkgbuilds/basecamp-cli/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "89c4eb5a0ac9ffe98aecd4ea8b789cf1fee42bf1" + "upstream": { + "watch": { + "github": "basecamp/basecamp-cli", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "basecamp-cli", + "commit": "89c4eb5a0ac9ffe98aecd4ea8b789cf1fee42bf1" + } } diff --git a/pkgbuilds/basecamp-cli/PKGBUILD b/pkgbuilds/basecamp-cli/PKGBUILD index d7a1f7c..b0bd117 100644 --- a/pkgbuilds/basecamp-cli/PKGBUILD +++ b/pkgbuilds/basecamp-cli/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Basecamp pkgname=basecamp-cli pkgver=0.11.0 -pkgrel=1 +pkgrel=2 pkgdesc="CLI for Basecamp project management" arch=('x86_64' 'aarch64') url="https://github.com/basecamp/basecamp-cli" @@ -13,8 +13,8 @@ optdepends=( 'zsh: for zsh shell completions' 'fish: for fish shell completions' ) -source_x86_64=("https://github.com/basecamp/basecamp-cli/releases/download/v0.11.0/basecamp_${pkgver}_linux_amd64.tar.gz") -source_aarch64=("https://github.com/basecamp/basecamp-cli/releases/download/v0.11.0/basecamp_${pkgver}_linux_arm64.tar.gz") +source_x86_64=("https://github.com/basecamp/basecamp-cli/releases/download/v${pkgver}/basecamp_${pkgver}_linux_amd64.tar.gz") +source_aarch64=("https://github.com/basecamp/basecamp-cli/releases/download/v${pkgver}/basecamp_${pkgver}_linux_arm64.tar.gz") sha256sums_x86_64=('425ffab1251c4315c5f731f8367c3c8c37b54b6b1050eafdbe369e11e1a1ce51') sha256sums_aarch64=('9c433b12a704402a98b238abb3128a0844a0bc682064adb260b11bc228b3595e') diff --git a/pkgbuilds/bun-bin/.omarchy/package.json b/pkgbuilds/bun-bin/.omarchy/package.json index dd5909b..ddb8163 100644 --- a/pkgbuilds/bun-bin/.omarchy/package.json +++ b/pkgbuilds/bun-bin/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "195b828d52ce9a181215f753927123e7ef2af252" + "upstream": { + "watch": { + "github": "oven-sh/bun", + "pattern": "bun-v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "bun-bin", + "commit": "195b828d52ce9a181215f753927123e7ef2af252" + } } diff --git a/pkgbuilds/claude-code/.omarchy/package.json b/pkgbuilds/claude-code/.omarchy/package.json index b9e1212..7a2b0a1 100644 --- a/pkgbuilds/claude-code/.omarchy/package.json +++ b/pkgbuilds/claude-code/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "27f61daa48ebdca87c9b2c7c83c162100d233ccc" + "upstream": { + "watch": { + "regex": "https://downloads.claude.ai/claude-code-releases/latest", + "pattern": "^(?P[0-9]+(?:\\.[0-9]+)*)\\s*$" + } + }, + "origin": { + "aur": "claude-code", + "commit": "27f61daa48ebdca87c9b2c7c83c162100d233ccc" + } } diff --git a/pkgbuilds/cliamp/.omarchy/package.json b/pkgbuilds/cliamp/.omarchy/package.json index 665cb10..94f9d65 100644 --- a/pkgbuilds/cliamp/.omarchy/package.json +++ b/pkgbuilds/cliamp/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "92fb021a1c78f75043cbbd402aca8b515af069ec" + "source": "local", + "upstream": { + "watch": { + "github": "bjarneo/cliamp", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "cliamp", + "commit": "92fb021a1c78f75043cbbd402aca8b515af069ec" + } } diff --git a/pkgbuilds/crush-bin/.omarchy/package.json b/pkgbuilds/crush-bin/.omarchy/package.json index c3eb109..857d5c1 100644 --- a/pkgbuilds/crush-bin/.omarchy/package.json +++ b/pkgbuilds/crush-bin/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "9c63847ccd3650646141f84384545c8fe2d68bb7" + "upstream": { + "watch": { + "github": "charmbracelet/crush", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "crush-bin", + "commit": "9c63847ccd3650646141f84384545c8fe2d68bb7" + } } diff --git a/pkgbuilds/cursor-bin/.omarchy/package.json b/pkgbuilds/cursor-bin/.omarchy/package.json index 21d7469..7c63fb1 100644 --- a/pkgbuilds/cursor-bin/.omarchy/package.json +++ b/pkgbuilds/cursor-bin/.omarchy/package.json @@ -1,5 +1,20 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "a87a0de17b0d8176ee4f046499b1e6e4b37cc422" + "upstream": { + "watch": { + "json": "https://www.cursor.com/api/download?platform=linux-x64&releaseTrack=stable", + "path": "version", + "fields": { + "commit": "commitSha" + }, + "variables": { + "_commit": "{commit}" + } + } + }, + "origin": { + "aur": "cursor-bin", + "commit": "a87a0de17b0d8176ee4f046499b1e6e4b37cc422" + } } diff --git a/pkgbuilds/cursor-bin/PKGBUILD b/pkgbuilds/cursor-bin/PKGBUILD index 24b94e9..d0a3e32 100644 --- a/pkgbuilds/cursor-bin/PKGBUILD +++ b/pkgbuilds/cursor-bin/PKGBUILD @@ -2,7 +2,7 @@ pkgname=cursor-bin pkgver=3.20.21 -pkgrel=1 +pkgrel=2 pkgdesc='AI-first coding environment' arch=('x86_64') url="https://www.cursor.com" @@ -16,11 +16,7 @@ _commit=f09fca384ceca23f7bf21f9c23655b162641d747 source=("https://downloads.cursor.com/production/${_commit}/linux/x64/deb/amd64/deb/cursor_${pkgver}_amd64.deb" "https://gitlab.archlinux.org/archlinux/packaging/packages/code/-/raw/main/code."{sh,mjs} rg.sh) -sha512sums=('SKIP' - '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' - '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' - 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a') -sha512sums[0]=8329138d207309d16410f1cb58da18eea1a034a35f2bdd022ef9b373bb8f1b3d80e489e65256b7283c40e10da77962d158bfa3a64e742337a942633810d80dbe +sha512sums=('8329138d207309d16410f1cb58da18eea1a034a35f2bdd022ef9b373bb8f1b3d80e489e65256b7283c40e10da77962d158bfa3a64e742337a942633810d80dbe' '937299c6cb6be2f8d25f7dbc95cf77423875c5f8353b8bd6cd7cc8e5603cbf8405b14dbf8bd615db2e3b36ed680fc8e1909410815f7f8587b7267a699e00ab37' '793f9ff6306e3992ac89802d98110cba288ea1181a901467333293b7d76182ef9792c2a39ff49d9347a18a174b1f42bc58862091dff583f4146c2704eea28033' 'e79fe7659f59d1ae02fc68816399bfd31587315df6cdb6ccf1d0ca76f7cdc692c2a42b30591c0091147bd97ef14b1c7745dc26bd7cb3ea6bba45698e5044fa2a') noextract=(cursor_${pkgver}_amd64.deb) # avoid double tarball _app=usr/share/cursor/resources/app package() { diff --git a/pkgbuilds/cursor-cli/.omarchy/package.json b/pkgbuilds/cursor-cli/.omarchy/package.json index 3d6de68..bc8c3d2 100644 --- a/pkgbuilds/cursor-cli/.omarchy/package.json +++ b/pkgbuilds/cursor-cli/.omarchy/package.json @@ -1,5 +1,16 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "954e5556aa88f2309b86992b231c8b76f273cfb0" + "upstream": { + "watch": { + "regex": "https://cursor.com/install", + "pattern": "https://downloads\\.cursor\\.com/lab/(?P[0-9]{4}\\.[0-9]{2}\\.[0-9]{2})-(?P[a-f0-9]+)/", + "version": "{version}.1.{hash}", + "sequence": true + } + }, + "origin": { + "aur": "cursor-cli", + "commit": "954e5556aa88f2309b86992b231c8b76f273cfb0" + } } diff --git a/pkgbuilds/dbxcli-bin/.omarchy/package.json b/pkgbuilds/dbxcli-bin/.omarchy/package.json index e8d76bc..53217cb 100644 --- a/pkgbuilds/dbxcli-bin/.omarchy/package.json +++ b/pkgbuilds/dbxcli-bin/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "80626b9efefc215d55eede4330d56c017a522682" + "source": "local", + "upstream": { + "watch": { + "github": "dropbox/dbxcli", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "dbxcli-bin", + "commit": "80626b9efefc215d55eede4330d56c017a522682" + } } diff --git a/pkgbuilds/dropbox-cli/.omarchy/package.json b/pkgbuilds/dropbox-cli/.omarchy/package.json index 407efd8..aaeee66 100644 --- a/pkgbuilds/dropbox-cli/.omarchy/package.json +++ b/pkgbuilds/dropbox-cli/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "b67e475d16f4e061a16af53dae212a46d9bc3ea9" + "upstream": { + "watch": { + "regex": "https://linux.dropbox.com/packages/", + "pattern": "nautilus-dropbox-(?P[0-9]{4}\\.[0-9]{2}\\.[0-9]{2})\\.tar\\.bz2" + } + }, + "origin": { + "aur": "dropbox-cli", + "commit": "b67e475d16f4e061a16af53dae212a46d9bc3ea9" + } } diff --git a/pkgbuilds/dropbox-cli/.omarchy/patches/x86-only.patch b/pkgbuilds/dropbox-cli/.omarchy/patches/x86-only.patch deleted file mode 100644 index 2448ae4..0000000 --- a/pkgbuilds/dropbox-cli/.omarchy/patches/x86-only.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -11,7 +11,7 @@ pkgname=dropbox-cli - pkgver=2024.04.17 - pkgrel=2 - pkgdesc="Command line interface for Dropbox" --arch=("any") -+arch=("x86_64") - url="https://www.dropbox.com" - license=("GPL-3.0-or-later") - makedepends=("gdk-pixbuf2") diff --git a/pkgbuilds/dropbox/.omarchy/package.json b/pkgbuilds/dropbox/.omarchy/package.json index fba5030..9250abe 100644 --- a/pkgbuilds/dropbox/.omarchy/package.json +++ b/pkgbuilds/dropbox/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "6379feda6f36bbbd496c97f040e4f71c5a1dcec7" + "upstream": { + "watch": { + "redirect": "https://www.dropbox.com/download?plat=lnx.x86_64", + "pattern": "dropbox-lnx\\.x86_64-(?P[0-9]+\\.4\\.[0-9]+)\\.tar\\.gz" + } + }, + "origin": { + "aur": "dropbox", + "commit": "6379feda6f36bbbd496c97f040e4f71c5a1dcec7" + } } diff --git a/pkgbuilds/elephant-all/.omarchy/package.json b/pkgbuilds/elephant-all/.omarchy/package.json index b45dcf3..0b3c0a1 100644 --- a/pkgbuilds/elephant-all/.omarchy/package.json +++ b/pkgbuilds/elephant-all/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "5614a0a61616643e448fb7c68d58237715ce2739" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-all", + "commit": "5614a0a61616643e448fb7c68d58237715ce2739" + } } diff --git a/pkgbuilds/elephant-archlinuxpkgs/.omarchy/package.json b/pkgbuilds/elephant-archlinuxpkgs/.omarchy/package.json index f886656..a020358 100644 --- a/pkgbuilds/elephant-archlinuxpkgs/.omarchy/package.json +++ b/pkgbuilds/elephant-archlinuxpkgs/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "659b81f1aa74a13fd2ebec222e19da2046d8e977" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-archlinuxpkgs", + "commit": "659b81f1aa74a13fd2ebec222e19da2046d8e977" + } } diff --git a/pkgbuilds/elephant-bluetooth/.omarchy/package.json b/pkgbuilds/elephant-bluetooth/.omarchy/package.json index e3a0f17..d08f83f 100644 --- a/pkgbuilds/elephant-bluetooth/.omarchy/package.json +++ b/pkgbuilds/elephant-bluetooth/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "42d9dd5424884c51b8fe6bf7692caf0a31007f05" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-bluetooth", + "commit": "42d9dd5424884c51b8fe6bf7692caf0a31007f05" + } } diff --git a/pkgbuilds/elephant-calc/.omarchy/package.json b/pkgbuilds/elephant-calc/.omarchy/package.json index b5f3ca0..94f4a46 100644 --- a/pkgbuilds/elephant-calc/.omarchy/package.json +++ b/pkgbuilds/elephant-calc/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "84aba9e90bbd65af45f83168cd6c7bce6ec4322e" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-calc", + "commit": "84aba9e90bbd65af45f83168cd6c7bce6ec4322e" + } } diff --git a/pkgbuilds/elephant-clipboard/.omarchy/package.json b/pkgbuilds/elephant-clipboard/.omarchy/package.json index f7e54fa..1634055 100644 --- a/pkgbuilds/elephant-clipboard/.omarchy/package.json +++ b/pkgbuilds/elephant-clipboard/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "3176f9de1445e7115009383f9cdac116729fc7be" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-clipboard", + "commit": "3176f9de1445e7115009383f9cdac116729fc7be" + } } diff --git a/pkgbuilds/elephant-desktopapplications/.omarchy/package.json b/pkgbuilds/elephant-desktopapplications/.omarchy/package.json index 3800fd9..e83c756 100644 --- a/pkgbuilds/elephant-desktopapplications/.omarchy/package.json +++ b/pkgbuilds/elephant-desktopapplications/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "c30e33db5fef912dec9aa157773b10ffab1e0307" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-desktopapplications", + "commit": "c30e33db5fef912dec9aa157773b10ffab1e0307" + } } diff --git a/pkgbuilds/elephant-files/.omarchy/package.json b/pkgbuilds/elephant-files/.omarchy/package.json index 851441c..b7f4bb9 100644 --- a/pkgbuilds/elephant-files/.omarchy/package.json +++ b/pkgbuilds/elephant-files/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "2d16502b7a905e7d7a03e0026c5519c3b3c4abf2" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-files", + "commit": "2d16502b7a905e7d7a03e0026c5519c3b3c4abf2" + } } diff --git a/pkgbuilds/elephant-menus/.omarchy/package.json b/pkgbuilds/elephant-menus/.omarchy/package.json index f33dba7..81b6353 100644 --- a/pkgbuilds/elephant-menus/.omarchy/package.json +++ b/pkgbuilds/elephant-menus/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "5ab583fee6ba3e387d49ffe4e409bb84bc60ea24" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-menus", + "commit": "5ab583fee6ba3e387d49ffe4e409bb84bc60ea24" + } } diff --git a/pkgbuilds/elephant-providerlist/.omarchy/package.json b/pkgbuilds/elephant-providerlist/.omarchy/package.json index eb32c10..5646aba 100644 --- a/pkgbuilds/elephant-providerlist/.omarchy/package.json +++ b/pkgbuilds/elephant-providerlist/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "1d756a138e926a81b9d33265f0197b8661168845" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-providerlist", + "commit": "1d756a138e926a81b9d33265f0197b8661168845" + } } diff --git a/pkgbuilds/elephant-runner/.omarchy/package.json b/pkgbuilds/elephant-runner/.omarchy/package.json index 9d14cb3..f8d45c4 100644 --- a/pkgbuilds/elephant-runner/.omarchy/package.json +++ b/pkgbuilds/elephant-runner/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "e47641530d912199372204cf8780ef37f99f0b37" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-runner", + "commit": "e47641530d912199372204cf8780ef37f99f0b37" + } } diff --git a/pkgbuilds/elephant-symbols/.omarchy/package.json b/pkgbuilds/elephant-symbols/.omarchy/package.json index c0525b3..2b2eeec 100644 --- a/pkgbuilds/elephant-symbols/.omarchy/package.json +++ b/pkgbuilds/elephant-symbols/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "32263e8b71390ab38b8aa1fd82fc2595b41a5157" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-symbols", + "commit": "32263e8b71390ab38b8aa1fd82fc2595b41a5157" + } } diff --git a/pkgbuilds/elephant-todo/.omarchy/package.json b/pkgbuilds/elephant-todo/.omarchy/package.json index 134635f..4a63e04 100644 --- a/pkgbuilds/elephant-todo/.omarchy/package.json +++ b/pkgbuilds/elephant-todo/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "447978df5ea3afd1e10959d7973c0b35367724c3" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-todo", + "commit": "447978df5ea3afd1e10959d7973c0b35367724c3" + } } diff --git a/pkgbuilds/elephant-unicode/.omarchy/package.json b/pkgbuilds/elephant-unicode/.omarchy/package.json index ed0012a..8b9efa1 100644 --- a/pkgbuilds/elephant-unicode/.omarchy/package.json +++ b/pkgbuilds/elephant-unicode/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "23222b0d304a234c74f630c5b9176d58c6c6e0b3" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-unicode", + "commit": "23222b0d304a234c74f630c5b9176d58c6c6e0b3" + } } diff --git a/pkgbuilds/elephant-websearch/.omarchy/package.json b/pkgbuilds/elephant-websearch/.omarchy/package.json index 2d9ea6f..e5f3fe6 100644 --- a/pkgbuilds/elephant-websearch/.omarchy/package.json +++ b/pkgbuilds/elephant-websearch/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "6b5da831da33e3533593823826a8ffb1a008a299" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant-websearch", + "commit": "6b5da831da33e3533593823826a8ffb1a008a299" + } } diff --git a/pkgbuilds/elephant/.omarchy/package.json b/pkgbuilds/elephant/.omarchy/package.json index 4f1debd..13506dc 100644 --- a/pkgbuilds/elephant/.omarchy/package.json +++ b/pkgbuilds/elephant/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "6dd02e6987a7a91be6a33e9600147523efa7fa5a" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/elephant", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "elephant", + "commit": "6dd02e6987a7a91be6a33e9600147523efa7fa5a" + } } diff --git a/pkgbuilds/grok-bot/.omarchy/package.json b/pkgbuilds/grok-bot/.omarchy/package.json index a2a26fe..2e8b089 100644 --- a/pkgbuilds/grok-bot/.omarchy/package.json +++ b/pkgbuilds/grok-bot/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "05eb78fca06b482affda28b26223cbf249d4bbcd" + "origin": { + "aur": "grok-bot", + "commit": "05eb78fca06b482affda28b26223cbf249d4bbcd" + } } diff --git a/pkgbuilds/heroic-games-launcher-bin/.omarchy/package.json b/pkgbuilds/heroic-games-launcher-bin/.omarchy/package.json index 119be00..e245991 100644 --- a/pkgbuilds/heroic-games-launcher-bin/.omarchy/package.json +++ b/pkgbuilds/heroic-games-launcher-bin/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "44b4e963c69541700088a5719855d34f5cf16c85" + "source": "local", + "upstream": { + "watch": { + "github": "Heroic-Games-Launcher/HeroicGamesLauncher", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "heroic-games-launcher-bin", + "commit": "44b4e963c69541700088a5719855d34f5cf16c85" + } } diff --git a/pkgbuilds/heroic-games-launcher-bin/PKGBUILD b/pkgbuilds/heroic-games-launcher-bin/PKGBUILD index 18d37bb..2bc7604 100755 --- a/pkgbuilds/heroic-games-launcher-bin/PKGBUILD +++ b/pkgbuilds/heroic-games-launcher-bin/PKGBUILD @@ -3,14 +3,14 @@ pkgname=heroic-games-launcher-bin pkgver=2.22.1 -pkgrel=1 +pkgrel=2 pkgdesc="An Open source Launcher for Epic, Amazon and GOG Games" arch=('x86_64') url="https://heroicgameslauncher.com/" license=('GPL-3.0-only') -_filename=Heroic-2.22.1-linux-x64.pacman -source=("https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v2.22.1/Heroic-2.22.1-linux-x64.pacman") -noextract=("Heroic-2.22.1-linux-x64.pacman") +_filename=Heroic-${pkgver}-linux-x64.pacman +source=("https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v${pkgver}/${_filename}") +noextract=("${_filename}") sha256sums=(66ed041a93ac2817b744d3d0985194adfa408c8d35f64d9a8967fa5e2a58f2c1) options=(!strip) depends=( @@ -27,4 +27,3 @@ package() { } # vim:set ts=2 sw=2 et: syntax=sh - diff --git a/pkgbuilds/hyprshade/.omarchy/package.json b/pkgbuilds/hyprshade/.omarchy/package.json index 56463ec..bdd892b 100644 --- a/pkgbuilds/hyprshade/.omarchy/package.json +++ b/pkgbuilds/hyprshade/.omarchy/package.json @@ -1,5 +1,13 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "89c710019789541e4cf972ee847f266534d6a96d" + "upstream": { + "watch": { + "pypi": "hyprshade" + } + }, + "origin": { + "aur": "hyprshade", + "commit": "89c710019789541e4cf972ee847f266534d6a96d" + } } diff --git a/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/package.json b/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/package.json index 8fa7c05..93ef7eb 100644 --- a/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/package.json +++ b/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "bbe7b771c897f78e518ab4453b0bc9210ef2f201" + "source": "local", + "upstream": { + "watch": { + "regex": "https://download.nvidia.com/XFree86/Linux-x86_64/", + "pattern": "href=[\\'\"](?P580\\.[0-9]+\\.[0-9]+)/[\\'\"]" + } + }, + "origin": { + "aur": "lib32-nvidia-580xx-utils", + "commit": "bbe7b771c897f78e518ab4453b0bc9210ef2f201" + } } diff --git a/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch b/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch deleted file mode 100644 index 10f90eb..0000000 --- a/pkgbuilds/lib32-nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -12,6 +12,12 @@ - #makedepends=('nvidia-libgl') # To avoid conflict during installation in the build chroot - license=('custom') - options=('!strip') -+ -+# Omarchy: the build image compresses with zstd at its default level, which -+# leaves these unstripped driver blobs far larger than they need to be. Maximum -+# zstd saves 25 MB here, most of it on the ISO's offline mirror. -+COMPRESSZST=(zstd -c -z -q --ultra -22 --threads=0 -) -+ - _pkg="NVIDIA-Linux-x86_64-${pkgver}" - source=("https://download.nvidia.com/XFree86/Linux-x86_64/${pkgver}/${_pkg}.run") - sha512sums=('ca394b1e3f6c3403dc7ffe5d5fd7301bb06607fdbf75c9ffd338d7641c06d1878790c629108162adf4289ae829568973a48b7557183dbf7588e668f6d8edf3b3') diff --git a/pkgbuilds/libfprint-git/.omarchy/package.json b/pkgbuilds/libfprint-git/.omarchy/package.json index 48065ee..eed18f7 100644 --- a/pkgbuilds/libfprint-git/.omarchy/package.json +++ b/pkgbuilds/libfprint-git/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "d225acd677e4a2af8f99698ea11386d8ad3af1bf" + "origin": { + "aur": "libfprint-git", + "commit": "d225acd677e4a2af8f99698ea11386d8ad3af1bf" + } } diff --git a/pkgbuilds/libretro-cap32-git/.omarchy/package.json b/pkgbuilds/libretro-cap32-git/.omarchy/package.json index 42986be..41c7005 100644 --- a/pkgbuilds/libretro-cap32-git/.omarchy/package.json +++ b/pkgbuilds/libretro-cap32-git/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "2dbe3348fb970d34155e652ce4a84fe4fbb42ecf" + "origin": { + "aur": "libretro-cap32-git", + "commit": "2dbe3348fb970d34155e652ce4a84fe4fbb42ecf" + } } diff --git a/pkgbuilds/libretro-database-git/.omarchy/package.json b/pkgbuilds/libretro-database-git/.omarchy/package.json index 9031029..7fcb920 100644 --- a/pkgbuilds/libretro-database-git/.omarchy/package.json +++ b/pkgbuilds/libretro-database-git/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "11ff3d3d1fc62f44a35a813f818235b7313ff7e0" + "origin": { + "aur": "libretro-database-git", + "commit": "11ff3d3d1fc62f44a35a813f818235b7313ff7e0" + } } diff --git a/pkgbuilds/libretro-fbneo-git/.omarchy/package.json b/pkgbuilds/libretro-fbneo-git/.omarchy/package.json index 88a2b8a..07b490f 100644 --- a/pkgbuilds/libretro-fbneo-git/.omarchy/package.json +++ b/pkgbuilds/libretro-fbneo-git/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "c33a5ce38a6a493fe88f092561d5197db1f97a1d" + "origin": { + "aur": "libretro-fbneo-git", + "commit": "c33a5ce38a6a493fe88f092561d5197db1f97a1d" + } } diff --git a/pkgbuilds/libretro-uae-git/.omarchy/package.json b/pkgbuilds/libretro-uae-git/.omarchy/package.json index 6a6a5db..479ac60 100644 --- a/pkgbuilds/libretro-uae-git/.omarchy/package.json +++ b/pkgbuilds/libretro-uae-git/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "f1bbed73caf47bfcb07a2c15f18485b42cb58584" + "origin": { + "aur": "libretro-uae-git", + "commit": "f1bbed73caf47bfcb07a2c15f18485b42cb58584" + } } diff --git a/pkgbuilds/libretro-vice-git/.omarchy/package.json b/pkgbuilds/libretro-vice-git/.omarchy/package.json index c141b36..664ce23 100644 --- a/pkgbuilds/libretro-vice-git/.omarchy/package.json +++ b/pkgbuilds/libretro-vice-git/.omarchy/package.json @@ -1,5 +1,8 @@ { - "source": "aur", + "source": "local", "sync": false, - "upstream_commit": "6b1839b0a1154ef29ddb2b67910f6d4c90bc1edd" + "origin": { + "aur": "libretro-vice-git", + "commit": "6b1839b0a1154ef29ddb2b67910f6d4c90bc1edd" + } } diff --git a/pkgbuilds/limine-mkinitcpio-hook/.omarchy/package.json b/pkgbuilds/limine-mkinitcpio-hook/.omarchy/package.json index e8b8b64..86036c2 100644 --- a/pkgbuilds/limine-mkinitcpio-hook/.omarchy/package.json +++ b/pkgbuilds/limine-mkinitcpio-hook/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "0c6f3a88d5928907d79c58bb67c9cb018774f60d" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://gitlab.com/Zesko/limine-entry-tool.git", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "limine-mkinitcpio-hook", + "commit": "0c6f3a88d5928907d79c58bb67c9cb018774f60d" + } } diff --git a/pkgbuilds/limine-mkinitcpio-hook/.omarchy/patches/arm-gradle.patch b/pkgbuilds/limine-mkinitcpio-hook/.omarchy/patches/arm-gradle.patch deleted file mode 100644 index d7af3e8..0000000 --- a/pkgbuilds/limine-mkinitcpio-hook/.omarchy/patches/arm-gradle.patch +++ /dev/null @@ -1,48 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -3,6 +3,7 @@ - pkgname="limine-mkinitcpio-hook" - _pkgver=1.38.0 - _extver="" -+_gradle_version=9.7.1 - pkgver="${_pkgver}${_extver}" - pkgrel=1 - pkgdesc="Install kernels for the Limine bootloader." -@@ -10,7 +11,8 @@ - url="https://gitlab.com/Zesko/limine-entry-tool" - source=("${_pkgname}::git+${url}.git#tag=${pkgver}") - source_x86_64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-x64_bin.tar.gz") --source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz") -+source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-25.2.4/graalvm-community-jdk-25i2-25.0.4_linux-aarch64_bin.tar.gz" -+ "https://services.gradle.org/distributions/gradle-${_gradle_version}-bin.zip") - license=("GPL3") - provides=('limine-entry-tool') - options=(!debug !strip) -@@ -27,12 +29,14 @@ - 'sbctl: Signs UEFI boot files for Secure Boot when enabled' - 'journalctl-desktop-notification: Sends desktop notifications when errors occur' - ) --makedepends=('git' 'gradle') -+makedepends=('git') -+makedepends_x86_64=('gradle') - backup=(etc/limine-entry-tool.conf) - conflicts=('limine-entry-tool') - sha256sums=('11dd8211898585f79d8361d97606965bb2ca214dccace5b133dc5121e4bb4d01') - sha256sums_x86_64=('3f4a89de8eaa96f2ed677f09957c7e872cd8467aad3537f8b5394c1b8c4b942e') --sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7') -+sha256sums_aarch64=('22286f7ecd21b9aedb3226b9bf797469e1bd3eefc491e12ef3dd49b452d230b7' -+ 'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a') - - prepare() { - [[ -d "${_graalvm_version}" ]] && rm -rf "${_graalvm_version}" -@@ -48,7 +52,9 @@ - export GRAALVM_HOME="$srcdir/${_graalvm_version}" - export JAVA_HOME="${GRAALVM_HOME}" - export NATIVE_IMAGE_OPTIONS="-march=compatibility --future-defaults=all" -- /usr/bin/gradle clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}" -+ local gradle=/usr/bin/gradle -+ [[ $CARCH == aarch64 ]] && gradle="$srcdir/gradle-${_gradle_version}/bin/gradle" -+ "$gradle" clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}" - } - - package() { diff --git a/pkgbuilds/limine-mkinitcpio-hook/PKGBUILD b/pkgbuilds/limine-mkinitcpio-hook/PKGBUILD index b2e63c8..21b3165 100644 --- a/pkgbuilds/limine-mkinitcpio-hook/PKGBUILD +++ b/pkgbuilds/limine-mkinitcpio-hook/PKGBUILD @@ -1,11 +1,9 @@ # Maintainer: Zesko _pkgname="limine-entry-tool" pkgname="limine-mkinitcpio-hook" -_pkgver=1.38.0 -_extver="" _gradle_version=9.7.1 -pkgver="${_pkgver}${_extver}" -pkgrel=1.1 +pkgver=1.38.0 +pkgrel=1.2 pkgdesc="Install kernels for the Limine bootloader." arch=('x86_64' 'aarch64') url="https://gitlab.com/Zesko/limine-entry-tool" diff --git a/pkgbuilds/limine-snapper-sync/.omarchy/package.json b/pkgbuilds/limine-snapper-sync/.omarchy/package.json index 24ae4dd..76ad41c 100644 --- a/pkgbuilds/limine-snapper-sync/.omarchy/package.json +++ b/pkgbuilds/limine-snapper-sync/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "35aff513bf1f0284380c8592d3de213f00bb6a7b" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://gitlab.com/Zesko/limine-snapper-sync.git", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "limine-snapper-sync", + "commit": "35aff513bf1f0284380c8592d3de213f00bb6a7b" + } } diff --git a/pkgbuilds/limine-snapper-sync/.omarchy/patches/arm-gradle.patch b/pkgbuilds/limine-snapper-sync/.omarchy/patches/arm-gradle.patch deleted file mode 100644 index 76ad31a..0000000 --- a/pkgbuilds/limine-snapper-sync/.omarchy/patches/arm-gradle.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -2,12 +2,14 @@ - pkgname="limine-snapper-sync" - pkgver=1.31.0 - pkgrel=1 -+_gradle_version=9.7.1 - pkgdesc="Integrates Limine boot entries with Snapper snapshots." - arch=('x86_64' 'aarch64') - url="https://gitlab.com/Zesko/limine-snapper-sync" - source=("${pkgname}::git+${url}.git#tag=${pkgver}") - source_x86_64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-x64_bin.tar.gz") --source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-aarch64_bin.tar.gz") -+source_aarch64=("https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-25.0.2/graalvm-community-jdk-25.0.2_linux-aarch64_bin.tar.gz" -+ "https://services.gradle.org/distributions/gradle-${_gradle_version}-bin.zip") - license=("GPL3") - options=(!debug !strip) - _graalvm_version=graalvm_ce_jdk25 -@@ -25,12 +27,14 @@ - 'b3sum: Fast Blake3 hash function to prevent duplication.' - 'xxhash: Fast hashing utility for deduplication with shorter hashes.' - ) --makedepends=('git' 'gradle') -+makedepends=('git') -+makedepends_x86_64=('gradle') - backup=(etc/limine-snapper-sync.conf) - conflicts=('limine-snapper-cli' 'limine-snapper-sync-git') - sha256sums=('ed236f1bbab966950bf11ba5a7958e97a76e66db7fd647b7737bab4b48c9fc40') - sha256sums_x86_64=('e0be791c8fda4d03b6b0a0cb824fef3149736170057b3a515252b44419606af0') --sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71') -+sha256sums_aarch64=('b4580d9f223d0a4b3a1757e58b18ff4c1db950e67e105fc5cb741457d2384a71' -+ 'acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a') - - prepare() { - [[ -d "${_graalvm_version}" ]] && rm -rf "${_graalvm_version}" -@@ -46,7 +50,9 @@ - export GRAALVM_HOME="$srcdir/${_graalvm_version}" - export JAVA_HOME="${GRAALVM_HOME}" - export NATIVE_IMAGE_OPTIONS="-march=compatibility" -- /usr/bin/gradle clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}" -+ local gradle=/usr/bin/gradle -+ [[ $CARCH == aarch64 ]] && gradle="$srcdir/gradle-${_gradle_version}/bin/gradle" -+ "$gradle" clean nativeCompile -Dorg.gradle.java.home="${JAVA_HOME}" - } - - package() { diff --git a/pkgbuilds/lmstudio-bin/.omarchy/package.json b/pkgbuilds/lmstudio-bin/.omarchy/package.json index f59a78f..995d65c 100644 --- a/pkgbuilds/lmstudio-bin/.omarchy/package.json +++ b/pkgbuilds/lmstudio-bin/.omarchy/package.json @@ -1,5 +1,20 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "8e97652a62a284b0c3436688bed6dfae0b54c669" + "upstream": { + "watch": { + "regex": "https://lmstudio.ai/download", + "unescape_json": true, + "pattern": "\"linux\":\\{\"x64\":\\{\"version\":\"(?P[0-9]+(?:\\.[0-9]+)*)\",\"build\":\"(?P[0-9]+)\"", + "variables": { + "_build": "{build}" + }, + "revision": "{build}", + "revision_variable": "_build" + } + }, + "origin": { + "aur": "lmstudio-bin", + "commit": "8e97652a62a284b0c3436688bed6dfae0b54c669" + } } diff --git a/pkgbuilds/lmstudio-bin/PKGBUILD b/pkgbuilds/lmstudio-bin/PKGBUILD index f130710..48b1a59 100644 --- a/pkgbuilds/lmstudio-bin/PKGBUILD +++ b/pkgbuilds/lmstudio-bin/PKGBUILD @@ -1,8 +1,9 @@ # Maintainer: noureddinex pkgname=lmstudio-bin pkgver=0.4.24 -pkgrel=1 -_pkgver=${pkgver}-${pkgrel} +pkgrel=2 +_build=1 +_pkgver=${pkgver}-${_build} pkgdesc="LM Studio - A desktop app for exploring and running large language models locally" arch=('x86_64') url="https://lmstudio.ai" diff --git a/pkgbuilds/localsend-bin/.omarchy/package.json b/pkgbuilds/localsend-bin/.omarchy/package.json index f6408c4..6e350be 100644 --- a/pkgbuilds/localsend-bin/.omarchy/package.json +++ b/pkgbuilds/localsend-bin/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "8dc54e7bdcbf24653b9247ec8af07aa012713b1c" + "upstream": { + "watch": { + "github": "localsend/localsend", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "localsend-bin", + "commit": "8dc54e7bdcbf24653b9247ec8af07aa012713b1c" + } } diff --git a/pkgbuilds/localsend/.omarchy/package.json b/pkgbuilds/localsend/.omarchy/package.json index dc5e190..5e3c138 100644 --- a/pkgbuilds/localsend/.omarchy/package.json +++ b/pkgbuilds/localsend/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "11788eb33c9298d611382884e8775fc34f874703" + "upstream": { + "watch": { + "github": "localsend/localsend", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "localsend", + "commit": "11788eb33c9298d611382884e8775fc34f874703" + } } diff --git a/pkgbuilds/macbook12-spi-driver-dkms/.omarchy/package.json b/pkgbuilds/macbook12-spi-driver-dkms/.omarchy/package.json index d49dd70..811c326 100644 --- a/pkgbuilds/macbook12-spi-driver-dkms/.omarchy/package.json +++ b/pkgbuilds/macbook12-spi-driver-dkms/.omarchy/package.json @@ -1,4 +1,17 @@ { - "source": "aur", - "upstream_commit": "38f085c6470eee409c22a4753eaf58d58b4759fd" + "source": "local", + "upstream": { + "watch": { + "git_branch": "https://github.com/marc-git/macbook12-spi-driver.git", + "branch": "touchbar-driver-hid-driver", + "version": "0+git.{count}", + "variables": { + "_commit": "{commit}" + } + } + }, + "origin": { + "aur": "macbook12-spi-driver-dkms", + "commit": "38f085c6470eee409c22a4753eaf58d58b4759fd" + } } diff --git a/pkgbuilds/macbook12-spi-driver-dkms/PKGBUILD b/pkgbuilds/macbook12-spi-driver-dkms/PKGBUILD index 3254326..a462dcb 100644 --- a/pkgbuilds/macbook12-spi-driver-dkms/PKGBUILD +++ b/pkgbuilds/macbook12-spi-driver-dkms/PKGBUILD @@ -3,7 +3,8 @@ _pkgbase=macbook12-spi-driver pkgname=(${_pkgbase}-dkms) pkgver=0+git.315 -pkgrel=1 +pkgrel=2 +_commit=807b65b6d9d7c29bd7ff633fbb80596a343e9eb9 pkgdesc="Driver for the keyboard, touchpad and touchbar found in newer MacBook (Pro) models" arch=('i686' 'x86_64') url="https://github.com/marc-git/macbook12-spi-driver" @@ -11,15 +12,11 @@ license=('GPL2') depends=('dkms') makedepends=('git') optdepends=() -source=(git+https://github.com/marc-git/macbook12-spi-driver.git#branch=touchbar-driver-hid-driver +source=(git+https://github.com/marc-git/macbook12-spi-driver.git#commit=${_commit} dkms.conf) sha256sums=('SKIP' 'e42243352d015a78e5d13260361d3052d0b84c4105bcb89191a319f2249cc47b') -pkgver() { - cd $_pkgbase - echo "0+git.$(git rev-list HEAD --count)" -} package() { install -dm755 "${pkgdir}"/usr/src/${_pkgbase}-${pkgver} diff --git a/pkgbuilds/makima-bin/.omarchy/package.json b/pkgbuilds/makima-bin/.omarchy/package.json index d3f3a01..46b6b10 100644 --- a/pkgbuilds/makima-bin/.omarchy/package.json +++ b/pkgbuilds/makima-bin/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "b91ad74a6e85ab1c3697a0c0a7d7bd9cf17a802c" + "source": "local", + "upstream": { + "watch": { + "github": "cyber-sushi/makima", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "makima-bin", + "commit": "b91ad74a6e85ab1c3697a0c0a7d7bd9cf17a802c" + } } diff --git a/pkgbuilds/minecraft-launcher/.omarchy/package.json b/pkgbuilds/minecraft-launcher/.omarchy/package.json index dbde2a6..1bd6241 100644 --- a/pkgbuilds/minecraft-launcher/.omarchy/package.json +++ b/pkgbuilds/minecraft-launcher/.omarchy/package.json @@ -1,5 +1,18 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "c6cac125f8cfc5d9a45e93b7f3ac9b01385dae23" + "upstream": { + "watch": { + "archive": "https://launcher.mojang.com/download/Minecraft.deb", + "pattern": "(?m)^Version: (?P[0-9]+(?:\\.[0-9]+)*)$", + "mutable_sources": [ + "source:0", + "source:1" + ] + } + }, + "origin": { + "aur": "minecraft-launcher", + "commit": "c6cac125f8cfc5d9a45e93b7f3ac9b01385dae23" + } } diff --git a/pkgbuilds/nautilus-dropbox/.omarchy/package.json b/pkgbuilds/nautilus-dropbox/.omarchy/package.json index a9b635d..d7046be 100644 --- a/pkgbuilds/nautilus-dropbox/.omarchy/package.json +++ b/pkgbuilds/nautilus-dropbox/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "f7907953200ffd14f1260691f4ff1b7290fcd887" + "upstream": { + "watch": { + "github": "dropbox/nautilus-dropbox", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "nautilus-dropbox", + "commit": "f7907953200ffd14f1260691f4ff1b7290fcd887" + } } diff --git a/pkgbuilds/nautilus-open-any-terminal/.omarchy/package.json b/pkgbuilds/nautilus-open-any-terminal/.omarchy/package.json index 667476e..8a36764 100644 --- a/pkgbuilds/nautilus-open-any-terminal/.omarchy/package.json +++ b/pkgbuilds/nautilus-open-any-terminal/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "b4bcde82a43129c09e22fd57351e61d5593a3d8f" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://github.com/Stunkymonkey/nautilus-open-any-terminal.git", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "nautilus-open-any-terminal", + "commit": "b4bcde82a43129c09e22fd57351e61d5593a3d8f" + } } diff --git a/pkgbuilds/nordvpn-bin/.omarchy/package.json b/pkgbuilds/nordvpn-bin/.omarchy/package.json index 8038e15..2edd578 100644 --- a/pkgbuilds/nordvpn-bin/.omarchy/package.json +++ b/pkgbuilds/nordvpn-bin/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "8d4c074f4b0a373c04c6f41baba83d3bd7d6d97b" + "upstream": { + "watch": { + "debian": "https://repo.nordvpn.com/deb/nordvpn/debian/dists/stable/main/binary-amd64/Packages", + "package": "nordvpn" + } + }, + "origin": { + "aur": "nordvpn-bin", + "commit": "8d4c074f4b0a373c04c6f41baba83d3bd7d6d97b" + } } diff --git a/pkgbuilds/nvidia-580xx-utils/.omarchy/package.json b/pkgbuilds/nvidia-580xx-utils/.omarchy/package.json index ae8781e..9439b28 100644 --- a/pkgbuilds/nvidia-580xx-utils/.omarchy/package.json +++ b/pkgbuilds/nvidia-580xx-utils/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "85c38619ce2267787d0515baa443739cb9d2883c" + "source": "local", + "upstream": { + "watch": { + "regex": "https://download.nvidia.com/XFree86/Linux-x86_64/", + "pattern": "href=[\\'\"](?P580\\.[0-9]+\\.[0-9]+)/[\\'\"]" + } + }, + "origin": { + "aur": "nvidia-580xx-utils", + "commit": "85c38619ce2267787d0515baa443739cb9d2883c" + } } diff --git a/pkgbuilds/nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch b/pkgbuilds/nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch deleted file mode 100644 index deb2e8f..0000000 --- a/pkgbuilds/nvidia-580xx-utils/.omarchy/patches/max-zstd-compression.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -13,6 +13,12 @@ - url="http://www.nvidia.com/" - license=('custom') - options=('!strip') -+ -+# Omarchy: the build image compresses with zstd at its default level, which -+# leaves these unstripped driver blobs far larger than they need to be. Maximum -+# zstd saves 89 MB across this pkgbase, most of it on the ISO's offline mirror. -+COMPRESSZST=(zstd -c -z -q --ultra -22 --threads=0 -) -+ - _pkg="NVIDIA-Linux-x86_64-${pkgver}" - _pkg_open="NVIDIA-kernel-module-source-${pkgver}" - source=('nvidia-drm-outputclass.conf' diff --git a/pkgbuilds/omarchy-chromium-bin/.omarchy/package.json b/pkgbuilds/omarchy-chromium-bin/.omarchy/package.json index ef66e39..1cd84ba 100644 --- a/pkgbuilds/omarchy-chromium-bin/.omarchy/package.json +++ b/pkgbuilds/omarchy-chromium-bin/.omarchy/package.json @@ -1,5 +1,19 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "344d4e2b006988df7f3a11952c7776d37891fb7a" + "upstream": { + "watch": { + "github": "omacom/omarchy-chromium", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)-(?P[0-9]+)", + "variables": { + "_build": "{build}" + }, + "revision": "{build}", + "revision_variable": "_build" + } + }, + "origin": { + "aur": "omarchy-chromium-bin", + "commit": "344d4e2b006988df7f3a11952c7776d37891fb7a" + } } diff --git a/pkgbuilds/omarchy-chromium-bin/PKGBUILD b/pkgbuilds/omarchy-chromium-bin/PKGBUILD index 5f634d1..7711a41 100644 --- a/pkgbuilds/omarchy-chromium-bin/PKGBUILD +++ b/pkgbuilds/omarchy-chromium-bin/PKGBUILD @@ -2,7 +2,8 @@ pkgname=omarchy-chromium-bin pkgver=148.0.7778.96 -pkgrel=21 +pkgrel=22 +_build=21 pkgdesc="A web browser built for speed, simplicity, and security, with patches for Omarchy (binary package)" arch=('x86_64' 'aarch64') url="https://www.chromium.org/Home" @@ -14,8 +15,8 @@ provides=('chromium') conflicts=('chromium' 'omarchy-chromium') # Architecture-specific sources -source_x86_64=("https://github.com/omacom-io/omarchy-chromium/releases/download/v148.0.7778.96-21/omarchy-chromium-148.0.7778.96-21-x86_64.pkg.tar.zst") -source_aarch64=("https://github.com/omacom-io/omarchy-chromium/releases/download/v148.0.7778.96-21/omarchy-chromium-148.0.7778.96-21-aarch64.pkg.tar.zst") +source_x86_64=("https://github.com/omacom-io/omarchy-chromium/releases/download/v${pkgver}-${_build}/omarchy-chromium-${pkgver}-${_build}-x86_64.pkg.tar.zst") +source_aarch64=("https://github.com/omacom-io/omarchy-chromium/releases/download/v${pkgver}-${_build}/omarchy-chromium-${pkgver}-${_build}-aarch64.pkg.tar.zst") sha256sums_x86_64=('f3f65950edb50722bbc99dde3beffa65a23e06593dcbe8ed7f17e92cc2613259') sha256sums_aarch64=('30aa14f35a06f03eae5442e845245614c374ffa13dc7a3c367ed4c65e68b7856') @@ -23,7 +24,7 @@ package() { cd "$srcdir" # Extract the package (filename varies by architecture) - tar -xf omarchy-chromium-148.0.7778.96-21-${CARCH}.pkg.tar.zst + tar -xf omarchy-chromium-${pkgver}-${_build}-${CARCH}.pkg.tar.zst # Copy everything to the target directory cp -r usr "$pkgdir/" diff --git a/pkgbuilds/omarchy-emacs/.omarchy/package.json b/pkgbuilds/omarchy-emacs/.omarchy/package.json index 5a35fc1..5d0b9fc 100644 --- a/pkgbuilds/omarchy-emacs/.omarchy/package.json +++ b/pkgbuilds/omarchy-emacs/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "c79a5ad3d523ad9a22fa57274d8b3fab8e87e5b2" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://github.com/scottjones/omarchy-emacs.git", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "omarchy-emacs", + "commit": "c79a5ad3d523ad9a22fa57274d8b3fab8e87e5b2" + } } diff --git a/pkgbuilds/omazed/.omarchy/package.json b/pkgbuilds/omazed/.omarchy/package.json index 4d2f659..84d820b 100644 --- a/pkgbuilds/omazed/.omarchy/package.json +++ b/pkgbuilds/omazed/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "cbc25a60a791ccda07ed5e8300e8acb267d23007" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://github.com/aps6/omazed.git", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "omazed", + "commit": "cbc25a60a791ccda07ed5e8300e8acb267d23007" + } } diff --git a/pkgbuilds/once-bin/.omarchy/package.json b/pkgbuilds/once-bin/.omarchy/package.json index 55a25c1..a8dbd34 100644 --- a/pkgbuilds/once-bin/.omarchy/package.json +++ b/pkgbuilds/once-bin/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "24d97ea4671538cec0b827fc40b01a3f3fc8ff49" + "source": "local", + "upstream": { + "watch": { + "github": "basecamp/once", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "once-bin", + "commit": "24d97ea4671538cec0b827fc40b01a3f3fc8ff49" + } } diff --git a/pkgbuilds/openai-codex-bin/.omarchy/package.json b/pkgbuilds/openai-codex-bin/.omarchy/package.json index 9a120f1..8acb222 100644 --- a/pkgbuilds/openai-codex-bin/.omarchy/package.json +++ b/pkgbuilds/openai-codex-bin/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "f72ee6f702ebc825c1680241dd599fb890c5a66a" + "upstream": { + "watch": { + "github": "openai/codex", + "pattern": "rust-v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "openai-codex-bin", + "commit": "f72ee6f702ebc825c1680241dd599fb890c5a66a" + } } diff --git a/pkgbuilds/python-mediapipe/.omarchy/package.json b/pkgbuilds/python-mediapipe/.omarchy/package.json index 6300a69..144d408 100644 --- a/pkgbuilds/python-mediapipe/.omarchy/package.json +++ b/pkgbuilds/python-mediapipe/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "99700efde7dc0200719dfed1a1147ace2cd7b0c0" + "upstream": { + "watch": { + "github": "google-ai-edge/mediapipe", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "python-mediapipe", + "commit": "99700efde7dc0200719dfed1a1147ace2cd7b0c0" + } } diff --git a/pkgbuilds/python-mediapipe/.omarchy/patches/verify-bazel-source.patch b/pkgbuilds/python-mediapipe/.omarchy/patches/verify-bazel-source.patch deleted file mode 100644 index 6cd9fb3..0000000 --- a/pkgbuilds/python-mediapipe/.omarchy/patches/verify-bazel-source.patch +++ /dev/null @@ -1,42 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -2,6 +2,7 @@ - # Maintainer: Hu Butui - - _pkgname=mediapipe -+_bazel_version=7.4.1 - pkgname=python-mediapipe - pkgver=1.0.0 - pkgrel=2 -@@ -27,10 +28,10 @@ makedepends=( - python-installer - python-setuptools - python-wheel -- wget - ) - - source=("${_pkgname}-${pkgver}.tar.gz::https://github.com/google-ai-edge/mediapipe/archive/refs/tags/v${pkgver}.tar.gz" -+ "bazel-${_bazel_version}-linux-x86_64::https://github.com/bazelbuild/bazel/releases/download/${_bazel_version}/bazel-${_bazel_version}-linux-x86_64" - "0004-use-opencv-headers.patch" - "0005-set-hermetic-python-version-and-disable-odml-converter.patch" - "0006-opencv5-geometry-header.patch" -@@ -38,6 +39,7 @@ source=("${_pkgname}-${pkgver}.tar.gz::https://github.com/google-ai-edge/medi - "0007-bump-rules-java.patch" - ) - sha256sums=('6343314dad0f4112610807ca723eee63feea00711dc2be9360928b6f0a5eba12' -+ 'c97f02133adce63f0c28678ac1f21d65fa8255c80429b588aeeba8a1fac6202b' - 'd18e88a217a00dc77cf2bfaa1d33b5fbc912deed5df686b0d2455fb0db75a677' - '62cbd43346e7a7705127656a74bec44852e5bbfc006c4723005fdd23af5258db' - 'fb082d88d9cca47534ae01fca676a3afdb909bfc82d52c97cf0eaedf34571d5f' -@@ -47,9 +49,8 @@ sha256sums=('6343314dad0f4112610807ca723eee63feea00711dc2be9360928b6f0a5eba12' - prepare() { - # bazel in the ArchLinux is not working - mkdir -p ${srcdir}/bin -- bazel_version=$(cat ${srcdir}/${_pkgname}-${pkgver}/.bazelversion) -- wget https://github.com/bazelbuild/bazel/releases/download/${bazel_version}/bazel-${bazel_version}-linux-x86_64 -O ${srcdir}/bin/bazel -- chmod +x ${srcdir}/bin/bazel -+ install -Dm755 "${srcdir}/bazel-${_bazel_version}-linux-x86_64" \ -+ "${srcdir}/bin/bazel" - export PATH=${srcdir}/bin:${PATH} - cd "${srcdir}/${_pkgname}-${pkgver}" - patch -p1 -i "${srcdir}/0004-use-opencv-headers.patch" diff --git a/pkgbuilds/python-sounddevice/.omarchy/package.json b/pkgbuilds/python-sounddevice/.omarchy/package.json index e50ad7b..a7353c7 100644 --- a/pkgbuilds/python-sounddevice/.omarchy/package.json +++ b/pkgbuilds/python-sounddevice/.omarchy/package.json @@ -1,5 +1,13 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "c3a5320f95ada9ccebd629b5722276e645388ced" + "upstream": { + "watch": { + "pypi": "sounddevice" + } + }, + "origin": { + "aur": "python-sounddevice", + "commit": "c3a5320f95ada9ccebd629b5722276e645388ced" + } } diff --git a/pkgbuilds/python-terminaltexteffects/.omarchy/package.json b/pkgbuilds/python-terminaltexteffects/.omarchy/package.json index f305a7c..808589a 100644 --- a/pkgbuilds/python-terminaltexteffects/.omarchy/package.json +++ b/pkgbuilds/python-terminaltexteffects/.omarchy/package.json @@ -1,4 +1,12 @@ { - "source": "aur", - "upstream_commit": "efbe1ae0019e7c44c9e1c7e22904f9fc77150b6a" + "source": "local", + "upstream": { + "watch": { + "pypi": "terminaltexteffects" + } + }, + "origin": { + "aur": "python-terminaltexteffects", + "commit": "efbe1ae0019e7c44c9e1c7e22904f9fc77150b6a" + } } diff --git a/pkgbuilds/quickshell-git/.omarchy/package.json b/pkgbuilds/quickshell-git/.omarchy/package.json index 2bb526a..457456e 100644 --- a/pkgbuilds/quickshell-git/.omarchy/package.json +++ b/pkgbuilds/quickshell-git/.omarchy/package.json @@ -1,6 +1,5 @@ { - "source": "aur", - "upstream_commit": "2494139bce7b7fc71372da00b68fb745a2c72d90", + "source": "local", "sync": false, "rebuild_on": [ "qt6-base", @@ -11,5 +10,9 @@ "qt6-base": "6.11.2-3", "qt6-declarative": "6.11.2-1", "qt6-wayland": "6.11.2-1" + }, + "origin": { + "aur": "quickshell-git", + "commit": "2494139bce7b7fc71372da00b68fb745a2c72d90" } } diff --git a/pkgbuilds/rustdesk/.omarchy/package.json b/pkgbuilds/rustdesk/.omarchy/package.json index 6fd38a8..ec5cb2b 100644 --- a/pkgbuilds/rustdesk/.omarchy/package.json +++ b/pkgbuilds/rustdesk/.omarchy/package.json @@ -1,4 +1,16 @@ { - "source": "aur", - "upstream_commit": "b19996732fccf6c9d436afccb704d65b320cf837" + "source": "local", + "upstream": { + "watch": { + "github": "rustdesk/rustdesk", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)", + "submodules": { + "_hbb_commit": "libs/hbb_common" + } + } + }, + "origin": { + "aur": "rustdesk", + "commit": "b19996732fccf6c9d436afccb704d65b320cf837" + } } diff --git a/pkgbuilds/rustdesk/PKGBUILD b/pkgbuilds/rustdesk/PKGBUILD index d5839fa..27fb9fb 100644 --- a/pkgbuilds/rustdesk/PKGBUILD +++ b/pkgbuilds/rustdesk/PKGBUILD @@ -149,27 +149,13 @@ DLAGENTS="${DLAGENTS[@]/curl /curl -L}" set -u _pkgname='rustdesk' pkgname="${_pkgname}" -_pkgver='1.4.9' -pkgver="${_pkgver//-/.}" -pkgrel=1 +pkgver=1.4.9 +_pkgver=$pkgver +pkgrel=2 _sfx='' #_sfx='-pr1-998b758' -_HBB=( # dates are retrieved from git fetch; tig. Every version gets a specific hbb. - '1.3.7:20250120-49c6b24a7a8c39d4448e07b743007ef1a3febd43' - '1.3.8:20250223-7cf11f7b771e27ecbd14fd1dd0ced55a64f40eb5' - '1.3.9:20250328-81b932b7bfa2ff8bc60189625fd6538db2fa9ea1' - '1.4.0:20250509-6e556f7e1751a3a709cd5cca0df7268ba3cb1c48' - '1.4.1:20250718-f91459c4ab80fc3cfdef0882b2af51f984bc914c' - '1.4.2:20250904-9e7696c7d4e346508ba68e801a53c6d1f1748fb5' - '1.4.3:20251008-5ed0afde0841659e2fb37ae7acaddc005fa1a8d3' - '1.4.4:20251117-a86eda749e6fa33c282bab680e6b504d3ad87539' - '1.4.5:20251117-073403edbf1fffcb3acfe8cbe7582ee873b23398' - '1.4.6:20260302-48c37de3e6c4e399af6f51ca20e8e3e1fd037976' - '1.4.7:20260601-df6badca5bf81b4e9836256cf8e31c993ad70dd1' - '1.4.8:20260604-387603f47cbb15c0d3dc3d67ae3396d3eb707daf' - '1.4.9:20260702-7e1c392c62d39c364127307cd408421dd5f8cfb0' -) -_pkgverhbb="$(_fn_VCL "${_pkgver}" -eq "${_HBB[@]}")"; unset _HBB; test "$(_vercmp "${_pkgver}" '1.3.7')" -lt 0 -o ! -z "${_pkgverhbb}" || exit 1 +_hbb_commit=7e1c392c62d39c364127307cd408421dd5f8cfb0 +_pkgverhbb=${_hbb_commit} pkgdesc='Yet another remote desktop software, written in Rust. Works out of the box, no configuration required. Great alternative to TeamViewer and AnyDesk!' arch=('x86_64') url='https://rustdesk.com/' diff --git a/pkgbuilds/spotify/.omarchy/package.json b/pkgbuilds/spotify/.omarchy/package.json index 78e3705..b3bac26 100644 --- a/pkgbuilds/spotify/.omarchy/package.json +++ b/pkgbuilds/spotify/.omarchy/package.json @@ -1,5 +1,18 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "0af779c21295d2875d06b07f8760a0e98256f3e4" + "upstream": { + "watch": { + "debian": "https://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages", + "package": "spotify-client", + "pattern": "1:(?P[0-9]+(?:\\.[0-9]+)*)\\.(?Pg[0-9a-f]+)", + "variables": { + "_commit": "{commit}" + } + } + }, + "origin": { + "aur": "spotify", + "commit": "0af779c21295d2875d06b07f8760a0e98256f3e4" + } } diff --git a/pkgbuilds/spotify/PKGBUILD b/pkgbuilds/spotify/PKGBUILD index 1255bb1..3594aa5 100644 --- a/pkgbuilds/spotify/PKGBUILD +++ b/pkgbuilds/spotify/PKGBUILD @@ -9,7 +9,7 @@ pkgname=spotify pkgver='1.2.96.518' epoch=1 _commit=g366879e1 -pkgrel=2 +pkgrel=3 pkgdesc='A proprietary music streaming service' arch=('x86_64') license=('custom') @@ -23,17 +23,17 @@ options=('!strip') # NOTE: We switched from stable to testing on 18th march, as the spotify # stable repository is always outdated. Testing seems to be in sync with snap: # https://snapcraft.io/spotify -# http://repository.spotify.com/dists/testing/Release -# http://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages -# http://repository.spotify.com/dists/testing/Release.gpg -source=("${pkgname}-${pkgver}-${_commit}-x86_64.deb::http://repository.spotify.com/pool/non-free/s/spotify-client/spotify-client_${pkgver}.${_commit}_amd64.deb" +# https://repository.spotify.com/dists/testing/Release +# https://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages +# https://repository.spotify.com/dists/testing/Release.gpg +source=("${pkgname}-${pkgver}-${_commit}-x86_64.deb::https://repository.spotify.com/pool/non-free/s/spotify-client/spotify-client_${pkgver}.${_commit}_amd64.deb" "spotify.sh" "spotify.protocol" "LICENSE" # GPG signature check - "${pkgname}-${pkgver}-${pkgrel}-Release::http://repository.spotify.com/dists/testing/Release" - "${pkgname}-${pkgver}-${pkgrel}-Release.sig::http://repository.spotify.com/dists/testing/Release.gpg" - "${pkgname}-${pkgver}-${pkgrel}-x86_64-Packages::http://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages") + "${pkgname}-${pkgver}-${pkgrel}-Release::https://repository.spotify.com/dists/testing/Release" + "${pkgname}-${pkgver}-${pkgrel}-Release.sig::https://repository.spotify.com/dists/testing/Release.gpg" + "${pkgname}-${pkgver}-${pkgrel}-x86_64-Packages::https://repository.spotify.com/dists/testing/non-free/binary-amd64/Packages") sha512sums=('98d25bd748258ca8b8357313cd35c7188bb0b26ed2d4390b0208473aa9fa3491a095559762f8ba06ec0828d73e05ee8fb488f0f357340191da4c65dd1f93c519' 'da48b628a4ea925dd8521133ebf364b261b11aed252d264dde6605d915cdb631919ffe672c58534bcdb60869e5d87a49a60a8198780b99517123f0031e83fdb1' '999abe46766a4101e27477f5c9f69394a4bb5c097e2e048ec2c6cb93dfa1743eb436bde3768af6ba1b90eaac78ea8589d82e621f9cbe7d9ab3f41acee6e8ca20' diff --git a/pkgbuilds/sublime-text-4/.omarchy/package.json b/pkgbuilds/sublime-text-4/.omarchy/package.json index 40e745c..94bd8c6 100644 --- a/pkgbuilds/sublime-text-4/.omarchy/package.json +++ b/pkgbuilds/sublime-text-4/.omarchy/package.json @@ -1,5 +1,15 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "a00e0a71a6e923093b855e5fd9ee10441b362271" + "upstream": { + "watch": { + "json": "https://www.sublimetext.com/updates/4/stable_update_check", + "path": "latest_version", + "version": "4.{version}" + } + }, + "origin": { + "aur": "sublime-text-4", + "commit": "a00e0a71a6e923093b855e5fd9ee10441b362271" + } } diff --git a/pkgbuilds/sunshine/.omarchy/package.json b/pkgbuilds/sunshine/.omarchy/package.json index 74758a6..fa0de1a 100644 --- a/pkgbuilds/sunshine/.omarchy/package.json +++ b/pkgbuilds/sunshine/.omarchy/package.json @@ -1,4 +1,16 @@ { - "source": "aur", - "upstream_commit": "42bc63ecad9478b35338d34ed923887bdbd81b29" + "source": "local", + "upstream": { + "watch": { + "github": "LizardByte/Sunshine", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)", + "variables": { + "_commit": "{commit}" + } + } + }, + "origin": { + "aur": "sunshine", + "commit": "42bc63ecad9478b35338d34ed923887bdbd81b29" + } } diff --git a/pkgbuilds/sunshine/.omarchy/patches/arm-dependencies.patch b/pkgbuilds/sunshine/.omarchy/patches/arm-dependencies.patch deleted file mode 100644 index 7b40c4c..0000000 --- a/pkgbuilds/sunshine/.omarchy/patches/arm-dependencies.patch +++ /dev/null @@ -1,56 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -38,7 +38,6 @@ - 'libcap' - 'libdrm' - 'libevdev' -- 'libmfx' - 'libpipewire' - 'libpulse' - 'libva' -@@ -58,6 +57,9 @@ - 'which' - ) - -+# Intel Media SDK is unavailable on ARM. -+depends_x86_64=('libmfx') -+ - makedepends=( - 'appstream' - 'appstream-glib' -@@ -72,6 +74,9 @@ - 'shaderc' - ) - -+# Use distro Vulkan headers instead of the bundled SDK's recursive sources. -+makedepends_aarch64=('vulkan-headers') -+ - checkdepends=( - 'gcovr' - 'imagemagick' -@@ -119,7 +124,13 @@ - - prepare() { - cd "$pkgname" -- git submodule update --recursive --init --depth 1 -+ if [[ $CARCH == aarch64 ]]; then -+ git submodule update --init --depth 1 -+ # Fetch Moonlight's nested sources without pulling in the bundled SDK. -+ git -C third-party/moonlight-common-c submodule update --recursive --init --depth 1 -+ else -+ git submodule update --recursive --init --depth 1 -+ fi - } - - build() { -@@ -149,6 +160,10 @@ - -D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' - ) - -+ if [[ $CARCH == aarch64 ]]; then -+ _cmake_options+=(-D SUNSHINE_SYSTEM_VULKAN_HEADERS=ON) -+ fi -+ - if [[ "${_use_cuda::1}" != "t" ]]; then - _cmake_options+=(-DSUNSHINE_ENABLE_CUDA=OFF -DCUDA_FAIL_ON_MISSING=OFF) - else diff --git a/pkgbuilds/sunshine/.omarchy/patches/packager-build-flags.patch b/pkgbuilds/sunshine/.omarchy/patches/packager-build-flags.patch deleted file mode 100644 index 3a5b626..0000000 --- a/pkgbuilds/sunshine/.omarchy/patches/packager-build-flags.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -155,9 +155,9 @@ build() { - -D CMAKE_INSTALL_PREFIX=/usr - -D SUNSHINE_EXECUTABLE_PATH=/usr/bin/sunshine - -D SUNSHINE_ASSETS_DIR="share/sunshine" -- -D SUNSHINE_PUBLISHER_NAME='LizardByte' -- -D SUNSHINE_PUBLISHER_WEBSITE='https://app.lizardbyte.dev' -- -D SUNSHINE_PUBLISHER_ISSUE_URL='https://app.lizardbyte.dev/support' -+ -D SUNSHINE_PUBLISHER_NAME='Omarchy' -+ -D SUNSHINE_PUBLISHER_WEBSITE='https://omarchy.org' -+ -D SUNSHINE_PUBLISHER_ISSUE_URL='https://github.com/omacom/omarchy-pkgs/issues' - ) - - if [[ $CARCH == aarch64 ]]; then diff --git a/pkgbuilds/sunshine/PKGBUILD b/pkgbuilds/sunshine/PKGBUILD index a9842ce..0e4d20c 100644 --- a/pkgbuilds/sunshine/PKGBUILD +++ b/pkgbuilds/sunshine/PKGBUILD @@ -6,11 +6,11 @@ : "${_support_headless_testing:=false}" : "${_use_cuda:=detect}" # nvenc -: "${_commit:=cb72dffa3233c5815cd5ba88f09f049dd679ba75}" +_commit=cb72dffa3233c5815cd5ba88f09f049dd679ba75 pkgname='sunshine' pkgver=2026.906.222525 -pkgrel=1.1 +pkgrel=1.2 pkgdesc="Self-hosted game stream host for Moonlight" arch=('x86_64' 'aarch64') url=https://app.lizardbyte.dev/Sunshine @@ -135,7 +135,7 @@ prepare() { build() { export BRANCH="master" - export BUILD_VERSION="2026.906.222525" + export BUILD_VERSION="${pkgver}" export COMMIT="${_commit}" export CC="gcc${_gcc_env_suffix}" diff --git a/pkgbuilds/supergfxctl/.omarchy/package.json b/pkgbuilds/supergfxctl/.omarchy/package.json index a48e412..f72c893 100644 --- a/pkgbuilds/supergfxctl/.omarchy/package.json +++ b/pkgbuilds/supergfxctl/.omarchy/package.json @@ -1,4 +1,8 @@ { - "source": "aur", - "sync": false + "source": "local", + "sync": false, + "origin": { + "aur": "supergfxctl", + "commit": null + } } diff --git a/pkgbuilds/ttf-ia-writer/.omarchy/package.json b/pkgbuilds/ttf-ia-writer/.omarchy/package.json index 34f9737..2fec430 100644 --- a/pkgbuilds/ttf-ia-writer/.omarchy/package.json +++ b/pkgbuilds/ttf-ia-writer/.omarchy/package.json @@ -1,4 +1,17 @@ { - "source": "aur", - "upstream_commit": "e9aa94080338d7a7f83a561ce64bf30ab4fb24e4" + "source": "local", + "upstream": { + "watch": { + "git_branch": "https://github.com/iaolo/iA-Fonts.git", + "branch": "master", + "version": "{date}.r{count}", + "variables": { + "_commit": "{commit}" + } + } + }, + "origin": { + "aur": "ttf-ia-writer", + "commit": "e9aa94080338d7a7f83a561ce64bf30ab4fb24e4" + } } diff --git a/pkgbuilds/ttf-ia-writer/PKGBUILD b/pkgbuilds/ttf-ia-writer/PKGBUILD index fc23d45..6946a14 100644 --- a/pkgbuilds/ttf-ia-writer/PKGBUILD +++ b/pkgbuilds/ttf-ia-writer/PKGBUILD @@ -2,14 +2,17 @@ pkgname=ttf-ia-writer pkgdesc='Subset of the fonts provided by iA Writer' pkgver=20181225 -pkgrel=1 +pkgrel=2 url=https://github.com/iaolo/iA-Fonts conflicts=(ttf-ia-writer-duospace) provides=(${conflicts[@]}) license=(custom:OFL) arch=(any) -_baseurl="${url}/raw/b337fe1a4c93026268f70e4b2678371f3e89e2ce/" +_commit=b337fe1a4c93026268f70e4b2678371f3e89e2ce +_baseurl="${url}/raw/${_commit}/" +# Duospace was removed upstream; retain the shipped legacy family at its last pin. +_legacy_baseurl="${url}/raw/b337fe1a4c93026268f70e4b2678371f3e89e2ce/" source=("${_baseurl}/iA%20Writer%20Mono/Static/iAWriterMonoS-Bold.ttf" "${_baseurl}/iA%20Writer%20Mono/Static/iAWriterMonoS-BoldItalic.ttf" "${_baseurl}/iA%20Writer%20Mono/Static/iAWriterMonoS-Italic.ttf" @@ -22,10 +25,10 @@ source=("${_baseurl}/iA%20Writer%20Mono/Static/iAWriterMonoS-Bold.ttf" "${_baseurl}/iA%20Writer%20Duo/Static/iAWriterDuoS-BoldItalic.ttf" "${_baseurl}/iA%20Writer%20Duo/Static/iAWriterDuoS-Italic.ttf" "${_baseurl}/iA%20Writer%20Duo/Static/iAWriterDuoS-Regular.ttf" - "${_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-Bold.ttf" - "${_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-BoldItalic.ttf" - "${_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-Italic.ttf" - "${_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-Regular.ttf") + "${_legacy_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-Bold.ttf" + "${_legacy_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-BoldItalic.ttf" + "${_legacy_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-Italic.ttf" + "${_legacy_baseurl}/iA%20Writer%20Duospace/TTF%20(PC)/iAWriterDuospace-Regular.ttf") package () { install -m644 -D -t "${pkgdir}/usr/share/fonts/${pkgname}" *.ttf diff --git a/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/.omarchy/package.json b/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/.omarchy/package.json index d150d8e..b86b164 100644 --- a/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/.omarchy/package.json +++ b/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/.omarchy/package.json @@ -1,4 +1,18 @@ { - "source": "aur", - "upstream_commit": "58203050bad3d23406a1e2e4357f1b7be2c6a45b" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://gitlab.com/kronerm/tuxedo-drivers-nocompatcheck.git", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)-patched\\.(?P[0-9]+)", + "variables": { + "_patchrel": "{build}" + }, + "revision": "{build}", + "revision_variable": "_patchrel" + } + }, + "origin": { + "aur": "tuxedo-drivers-nocompatcheck-dkms", + "commit": "58203050bad3d23406a1e2e4357f1b7be2c6a45b" + } } diff --git a/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/PKGBUILD b/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/PKGBUILD index b6a78fa..c8c30ea 100644 --- a/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/PKGBUILD +++ b/pkgbuilds/tuxedo-drivers-nocompatcheck-dkms/PKGBUILD @@ -4,7 +4,8 @@ _pkgname=tuxedo-drivers _reponame=${_pkgname}-nocompatcheck pkgname=${_reponame}-dkms pkgver=4.22.1 -pkgrel=1 +pkgrel=2 +_patchrel=1 pkgdesc="TUXEDO Computers kernel module drivers. Compatibility check disabled - works when using identical models from other brands, example being TUXEDO Pulse 14 Gen 4 and Schenker Via 14 Pro (M24)" url="https://gitlab.com/kronerm/${_reponame}" license=("GPL-2.0-or-later") @@ -29,14 +30,14 @@ provides=('tuxedo-drivers-dkms' 'ite_8297' 'ite_829x') conflicts=('tuxedo-drivers-dkms' 'tuxedo-keyboard-dkms' 'tuxedo-keyboard-ite-dkms') -source=($pkgname-$pkgver.tar.gz::https://gitlab.com/kronerm/${_reponame}/-/archive/v${pkgver}-patched.${pkgrel}/tuxedo-drivers-v${pkgver}-patched.${pkgrel}.tar.gz dkms.conf) +source=($pkgname-$pkgver.tar.gz::https://gitlab.com/kronerm/${_reponame}/-/archive/v${pkgver}-patched.${_patchrel}/tuxedo-drivers-v${pkgver}-patched.${_patchrel}.tar.gz dkms.conf) sha256sums=('739e101123cdd44f619c5533dc6509608be517416a5e19807ca012a9f98e59f2' '0b1f2ceb729b1944504d1227e39b202159076846aaa38f8b6237b9535e543a21') sha512sums=('d8fb9a24c8722e27d62267b9e0dfffa131ceaae26e2fc89065badb1fd1545cc617a5be338492592f6a2cd25f8f2ac6cc25b819856b88529e373bb0c8b4bfa145' 'dda443b5966221a355fecdae7a2eb23346666cbcf93707d2fff660a32ec75cee592ae211c8d22e55413d530f59e8667292a0346d8bf6b2d280b45f3bc09efafd') package() { - extracted_source_dir=("$_reponame"-v"$pkgver"-patched."$pkgrel"-*/) + extracted_source_dir=("$_reponame"-v"$pkgver"-patched."$_patchrel"-*/) target_dkms_dir="$pkgdir"/usr/src/"$_pkgname"-v"$pkgver" install -Dm644 "$srcdir"/dkms.conf "$target_dkms_dir"/dkms.conf diff --git a/pkgbuilds/typora/.omarchy/package.json b/pkgbuilds/typora/.omarchy/package.json index 3c3fcb9..fc0627d 100644 --- a/pkgbuilds/typora/.omarchy/package.json +++ b/pkgbuilds/typora/.omarchy/package.json @@ -1,4 +1,14 @@ { - "source": "aur", - "upstream_commit": "029ff738d5928db82edfa34fc365fcb6743a74e5" + "source": "local", + "upstream": { + "watch": { + "debian": "https://downloads.typora.io/linux/Packages", + "package": "typora", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*)(?:-[0-9]+)?" + } + }, + "origin": { + "aur": "typora", + "commit": "029ff738d5928db82edfa34fc365fcb6743a74e5" + } } diff --git a/pkgbuilds/ufw-docker/.omarchy/package.json b/pkgbuilds/ufw-docker/.omarchy/package.json index 9e3761d..fcd8057 100644 --- a/pkgbuilds/ufw-docker/.omarchy/package.json +++ b/pkgbuilds/ufw-docker/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "76e18ac8c40a4e8f018f4b35289718a29eca3d6d" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://github.com/chaifeng/ufw-docker.git", + "pattern": "(?P[0-9]{6})" + } + }, + "origin": { + "aur": "ufw-docker", + "commit": "76e18ac8c40a4e8f018f4b35289718a29eca3d6d" + } } diff --git a/pkgbuilds/vi/.omarchy/package.json b/pkgbuilds/vi/.omarchy/package.json index a07823f..5354a14 100644 --- a/pkgbuilds/vi/.omarchy/package.json +++ b/pkgbuilds/vi/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "9aa84b0998874261e94bbbe25e0dcf3de7286b94" + "source": "local", + "upstream": { + "watch": { + "regex": "https://sources.archlinux.org/other/vi/", + "pattern": "ex-(?P[0-9]{6})\\.tar\\.xz" + } + }, + "origin": { + "aur": "vi", + "commit": "9aa84b0998874261e94bbbe25e0dcf3de7286b94" + } } diff --git a/pkgbuilds/visual-studio-code-bin/.omarchy/package.json b/pkgbuilds/visual-studio-code-bin/.omarchy/package.json index 48711f6..9daebc8 100644 --- a/pkgbuilds/visual-studio-code-bin/.omarchy/package.json +++ b/pkgbuilds/visual-studio-code-bin/.omarchy/package.json @@ -1,5 +1,14 @@ { - "source": "aur", + "source": "local", "release_ring": "fast", - "upstream_commit": "4e46b8b4ca50f6aed23c848aa4f2d16fbd2432e5" + "upstream": { + "watch": { + "json": "https://update.code.visualstudio.com/api/update/linux-deb-x64/stable/latest", + "path": "productVersion" + } + }, + "origin": { + "aur": "visual-studio-code-bin", + "commit": "4e46b8b4ca50f6aed23c848aa4f2d16fbd2432e5" + } } diff --git a/pkgbuilds/walker/.omarchy/package.json b/pkgbuilds/walker/.omarchy/package.json index ba3a040..30aa091 100644 --- a/pkgbuilds/walker/.omarchy/package.json +++ b/pkgbuilds/walker/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "9dbe9e62a133a14a16f4a6f6e9fe7de04ef651ef" + "source": "local", + "upstream": { + "watch": { + "github": "abenz1267/walker", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "walker", + "commit": "9dbe9e62a133a14a16f4a6f6e9fe7de04ef651ef" + } } diff --git a/pkgbuilds/xdg-terminal-exec/.omarchy/package.json b/pkgbuilds/xdg-terminal-exec/.omarchy/package.json index 8a4d806..5e59cc2 100644 --- a/pkgbuilds/xdg-terminal-exec/.omarchy/package.json +++ b/pkgbuilds/xdg-terminal-exec/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "a52e8f23c0be7d482b944c6cf5ddee172da171e4" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://gitlab.freedesktop.org/Vladimir-csp/xdg-terminal-exec.git", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "xdg-terminal-exec", + "commit": "a52e8f23c0be7d482b944c6cf5ddee172da171e4" + } } diff --git a/pkgbuilds/xpadneo-dkms/.omarchy/package.json b/pkgbuilds/xpadneo-dkms/.omarchy/package.json index e23a5b8..906b421 100644 --- a/pkgbuilds/xpadneo-dkms/.omarchy/package.json +++ b/pkgbuilds/xpadneo-dkms/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "ae15a8de85094bee24c0e24408a22decb21121e7" + "source": "local", + "upstream": { + "watch": { + "github": "atar-axis/xpadneo", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "xpadneo-dkms", + "commit": "ae15a8de85094bee24c0e24408a22decb21121e7" + } } diff --git a/pkgbuilds/xpadneo-dkms/.omarchy/patches/arm-kernel-headers.patch b/pkgbuilds/xpadneo-dkms/.omarchy/patches/arm-kernel-headers.patch deleted file mode 100644 index 9dcc175..0000000 --- a/pkgbuilds/xpadneo-dkms/.omarchy/patches/arm-kernel-headers.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -14,7 +14,9 @@ arch=(any) - license=('GPL-2.0-only AND GPL-3.0-or-later') --checkdepends=('dkms' 'fakeroot' 'LINUX-HEADERS') -+checkdepends=('dkms' 'fakeroot') -+checkdepends_x86_64=('LINUX-HEADERS') -+checkdepends_aarch64=('linux-aarch64-headers') - source=("xpadneo-v${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz") - b2sums=('2858e466c5fde7e3d06d878dd7fb695751375e11a112bd3d389f9db5a82ef3ffcc1e3431b213f4807aeb8f05fd4280c7ca2a0a56305b0e984eb9b70df4843735') - diff --git a/pkgbuilds/yaru-icon-theme/.omarchy/package.json b/pkgbuilds/yaru-icon-theme/.omarchy/package.json index b9d987c..c20fa15 100644 --- a/pkgbuilds/yaru-icon-theme/.omarchy/package.json +++ b/pkgbuilds/yaru-icon-theme/.omarchy/package.json @@ -1,5 +1,13 @@ { - "source": "aur", - "aur": "yaru", - "upstream_commit": "7206d6736121b4564998262d99d6afdbc28b1563" + "source": "local", + "upstream": { + "watch": { + "git_tags": "https://github.com/ubuntu/yaru.git", + "pattern": "(?P[0-9]+(?:\\.[0-9]+)*(?:ubuntu)?)" + } + }, + "origin": { + "aur": "yaru", + "commit": "7206d6736121b4564998262d99d6afdbc28b1563" + } } diff --git a/pkgbuilds/yay/.omarchy/package.json b/pkgbuilds/yay/.omarchy/package.json index 82766e4..eec3de3 100644 --- a/pkgbuilds/yay/.omarchy/package.json +++ b/pkgbuilds/yay/.omarchy/package.json @@ -1,4 +1,13 @@ { - "source": "aur", - "upstream_commit": "cb43f84828ab4f9700f7c6f9c6d7a923d4cfaff0" + "source": "local", + "upstream": { + "watch": { + "github": "Jguer/yay", + "pattern": "v(?P[0-9]+(?:\\.[0-9]+)*)" + } + }, + "origin": { + "aur": "yay", + "commit": "cb43f84828ab4f9700f7c6f9c6d7a923d4cfaff0" + } } diff --git a/pkgbuilds/yt6801-dkms/.omarchy/package.json b/pkgbuilds/yt6801-dkms/.omarchy/package.json index 436ae2c..fa2b446 100644 --- a/pkgbuilds/yt6801-dkms/.omarchy/package.json +++ b/pkgbuilds/yt6801-dkms/.omarchy/package.json @@ -1,4 +1,17 @@ { - "source": "aur", - "upstream_commit": "020a0f11079cc974794e49856a1a98ab677570a9" + "source": "local", + "upstream": { + "watch": { + "archive": "https://www.motor-comm.com/Cn/Skippower/downloadFile.html?id=1817", + "filenames": true, + "pattern": "yt6801-(?P[0-9]+(?:\\.[0-9]+)*)\\.tar\\.gz", + "mutable_sources": [ + "source:0" + ] + } + }, + "origin": { + "aur": "yt6801-dkms", + "commit": "020a0f11079cc974794e49856a1a98ab677570a9" + } } diff --git a/tests/upstream-watch.py b/tests/upstream-watch.py new file mode 100644 index 0000000..856a928 --- /dev/null +++ b/tests/upstream-watch.py @@ -0,0 +1,334 @@ +#!/usr/bin/env python3 +"""Offline integration tests for owned-recipe updates and failure isolation.""" +import importlib.util +import json +import os +from pathlib import Path +import shutil +import subprocess +import tempfile +import unittest +from unittest.mock import patch +import zipfile + +ROOT = Path(__file__).resolve().parents[1] +spec = importlib.util.spec_from_file_location("upstream_watch", ROOT / "helpers/upstream-watch.py") +w = importlib.util.module_from_spec(spec) +spec.loader.exec_module(w) + + +class WatchTest(unittest.TestCase): + def setUp(self): + self.work = tempfile.TemporaryDirectory() + self.addCleanup(self.work.cleanup) + self.root = Path(self.work.name) + self.package = self.root / "package" + (self.package / ".omarchy").mkdir(parents=True) + self.fetch = w.Fetcher(self.root / "cache") + self.write_watch({"github": "owner/tool", "pattern": r"v(?P[0-9.]+)"}) + self.recipe = self.package / "PKGBUILD" + self.recipe.write_text("""pkgname=tool +pkgver=1.0 +pkgrel=3.1 +arch=('x86_64' 'aarch64') +source_x86_64=("https://example.test/tool-$pkgver-x64") +source_aarch64=("https://example.test/tool-$pkgver-arm64") +sha256sums_x86_64=('old-x64') +sha256sums_aarch64=('old-arm64') +package() { touch SHOULD-NOT-RUN; } +""") + + def write_watch(self, watch): + (self.package / ".omarchy/package.json").write_text(json.dumps({"source": "local", "upstream": {"watch": watch}})) + + def release(self, version="2.0", **values): + return {"pkgver": version, "values": {"version": version, "tag": "v" + version, **values}, "revision": "", "published_at": "2026-01-01T00:00:00Z"} + + def fake_file(self, url): + p = self.root / ("source-" + url.rsplit("/", 1)[-1]) + p.write_text(url) + return p + + def sync_release(self, release, file=None): + with patch.object(w, "discover", return_value=[release]), patch.object(self.fetch, "file", side_effect=file or self.fake_file): + return w.sync(self.package, self.fetch) + + def test_updates_both_arches_without_running_build_functions(self): + result = self.sync_release(self.release()) + self.assertEqual(result["after"], "0:2.0-1") + recipe = w.read_recipe(self.recipe) + for arch, upstream in [("x86_64", "x64"), ("aarch64", "arm64")]: + file = self.fake_file(f"https://example.test/tool-2.0-{upstream}") + self.assertEqual(recipe["sha256sums_" + arch], [w.hash_file(file, "sha256")]) + self.assertFalse((self.package / "SHOULD-NOT-RUN").exists()) + + def test_missing_arm_payload_preserves_original_recipe(self): + original = self.recipe.read_bytes() + def fetch(url): + if url.endswith('arm64'): + raise ValueError("ARM release not published") + return self.fake_file(url) + with self.assertRaisesRegex(ValueError, "ARM"): + self.sync_release(self.release(), fetch) + self.assertEqual(self.recipe.read_bytes(), original) + self.assertFalse(self.recipe.with_name('PKGBUILD.sync-upstream').exists()) + + def test_changed_checksum_override_is_detected_and_rolled_back(self): + self.recipe.write_text(self.recipe.read_text() + "sha256sums_aarch64[0]='stale'\n") + original = self.recipe.read_bytes() + with self.assertRaisesRegex(ValueError, "differs"): + self.sync_release(self.release()) + self.assertEqual(self.recipe.read_bytes(), original) + + def test_old_or_equal_versions_do_not_download_sources(self): + for version in ['0.9', '1.0']: + with patch.object(w, 'discover', return_value=[self.release(version)]), patch.object(self.fetch, 'file') as fetch: + self.assertEqual(w.sync(self.package, self.fetch)['status'], 'skipped') + fetch.assert_not_called() + + def test_manual_hold_prevents_release_discovery(self): + path = self.package / '.omarchy/package.json' + metadata = json.loads(path.read_text()) + metadata['sync'] = False + path.write_text(json.dumps(metadata)) + with patch.object(w, 'discover') as discover: + self.assertEqual(w.sync(self.package, self.fetch)['status'], 'skipped') + discover.assert_not_called() + + def test_epoch_change_in_recipe_cannot_mask_downgrade(self): + self.recipe.write_text(self.recipe.read_text() + "if [[ $pkgver == 1.0 ]]; then epoch=2; else epoch=1; fi\n") + original = self.recipe.read_bytes() + with self.assertRaisesRegex(ValueError, "complete package version"): + self.sync_release(self.release()) + self.assertEqual(self.recipe.read_bytes(), original) + + def test_same_version_build_revision_advances_downstream_pkgrel(self): + self.write_watch({'github': 'owner/tool', 'pattern': r'v(?P[0-9.]+)-(?P[0-9]+)', 'variables': {'_build': '{build}'}, 'revision': '{build}', 'revision_variable': '_build'}) + self.recipe.write_text(self.recipe.read_text().replace('pkgrel=3.1', 'pkgrel=3.1\n_build=8').replace('tool-$pkgver-', 'tool-$pkgver-$_build-')) + release = self.release('1.0', build='9');release['revision'] = '9' + self.assertEqual(self.sync_release(release)['after'], '0:1.0-3.2') + self.assertEqual(w.scalar(w.read_recipe(self.recipe), '_build'), '9') + release = self.release('1.0', build='7');release['revision'] = '7' + original = self.recipe.read_bytes() + with self.assertRaisesRegex(ValueError, 'without a newer'): + self.sync_release(release) + self.assertEqual(self.recipe.read_bytes(), original) + + def test_sha512_blake2_and_local_hashes_are_preserved(self): + self.recipe.write_text("""pkgver=1.0 +pkgrel=1 +arch=('any') +source=("https://example.test/tool-$pkgver" 'fix.patch') +sha512sums=('old' 'local-sha512') +b2sums=('old' 'local-b2') +""") + (self.package / 'fix.patch').write_text('local patch') + self.sync_release(self.release()) + recipe = w.read_recipe(self.recipe) + file = self.fake_file('https://example.test/tool-2.0') + self.assertEqual(recipe['sha512sums'], [w.hash_file(file, 'sha512'), 'local-sha512']) + self.assertEqual(recipe['b2sums'], [w.hash_file(file, 'b2'), 'local-b2']) + + def test_mutable_sources_are_rehashed_when_version_changes(self): + self.write_watch({'regex': 'https://example.test/feed', 'pattern': r'(?P[0-9.]+)', 'mutable_sources': ['source_x86_64:0']}) + self.recipe.write_text(self.recipe.read_text().replace('tool-$pkgver-x64','tool-current-x64')) + self.sync_release(self.release()) + result = w.read_recipe(self.recipe) + self.assertEqual(result['sha256sums_x86_64'], [w.hash_file(self.fake_file('https://example.test/tool-current-x64'), 'sha256')]) + + def test_release_selection_and_age(self): + a, b = self.release('1.9'), self.release('1.10') + self.assertEqual(w.select_release([a, b])['pkgver'], '1.10') + b['published_at'] = '2 days ago' + with self.assertRaisesRegex(ValueError, 'age'): + w.select_release([b], 86400) + b['published_at'] = '2999-01-01T00:00:00Z' + self.assertIsNone(w.select_release([b], 86400)) + self.assertEqual(w.select_release([b], 86400, bypass=True), b) + + def test_hostile_release_values_do_not_reach_shell(self): + for value in ['1.0\ntouch bad', '$(touch bad)', '`id`', '1.0;id', '1.0"']: + with self.assertRaises(ValueError): + w.candidate({}, {'version': value}) + with self.assertRaises(ValueError): + w.replace_scalar('pkgver=1.0\n', 'pkgver', '$(id)') + for url in ['http://example.test', 'https://user:password@example.test/file', 'https://example.test/\nfile']: + with self.assertRaises(ValueError):w.https(url) + + def test_array_writer_handles_comments_and_quoted_parentheses(self): + text = "sha256sums=( # closing ) in a comment\n 'old(value)'\n) # trailing\npackage() { :; }\n" + output = w.replace_array(text, 'sha256sums', ['abc']) + self.assertEqual(output, "sha256sums=('abc') # trailing\npackage() { :; }\n") + + def test_git_hash_matches_makepkg(self): + repo = self.root / 'git' + repo.mkdir() + subprocess.run(['git', 'init', '-q', str(repo)], check=True) + (repo / 'source').write_text('upstream code') + subprocess.run(['git', '-C', str(repo), 'add', '.'], check=True) + subprocess.run(['git', '-C', str(repo), '-c', 'user.name=Test', '-c', 'user.email=test@example.test', 'commit', '-qm', 'release'], check=True) + subprocess.run(['git', '-C', str(repo), 'tag', 'v1.0'], check=True) + command = w.subprocess.run + def redirect(args, **kwargs): + if 'fetch' in args: + args = [str(repo) if arg == 'https://example.test/tool.git' else arg for arg in args] + return command(args, **kwargs) + with patch.object(w.subprocess, 'run', side_effect=redirect): + archive = w.git_source_file('git+https://example.test/tool.git#tag=v1.0', self.fetch.cache) + expected = subprocess.check_output(['git', '-c', 'core.abbrev=no', '-C', str(repo), 'archive', '--format', 'tar', 'v1.0']) + self.assertEqual(archive.read_bytes(), expected) + + def test_invalid_optional_metadata_fails_validation(self): + valid = {'github': 'owner/tool', 'pattern': r'v(?P[0-9.]+)'} + for extra in [{'variables': []}, {'fields': {'commit': 3}}, {'submodules': {'pkgver': 'libs/common'}}, + {'allow_prerelease': 'false'}, {'sequence': 1}, {'mutable_sources': ['source:no']}, + {'revision_variable': '_build'}, {'submodules': {'_commit': '../outside'}}, + {'allow_prerelase': True}]: + with self.subTest(extra=extra), self.assertRaises(ValueError): + w.validate({**valid, **extra}) + with self.assertRaisesRegex(ValueError, 'numeric'): + w.candidate({'revision': '{build}'}, {'version': '1.0', 'build': 'beta'}) + + def test_github_selects_stable_matching_tag_and_resolves_gitlinks(self): + watch = {'github': 'owner/tool', 'pattern': r'v(?P[0-9.]+)', + 'variables': {'_commit': '{commit}'}, 'submodules': {'_common': 'libs/common'}} + def fetch(url): + if '/releases?' in url: + return [{'tag_name': tag, 'published_at': '2026-01-01T00:00:00Z', **flags} + for tag, flags in [('v1.0', {}), ('v2.0', {}), ('v3.0', {'prerelease': True}), + ('v4.0', {'draft': True}), ('unrelated-v5.0', {})]] + if '/git/ref/' in url: return {'object': {'type': 'tag', 'sha': 'a' * 40}} + if '/git/tags/' in url: return {'object': {'type': 'commit', 'sha': 'b' * 40}} + if '/contents/' in url: + self.assertTrue(url.endswith('?ref=v2.0')) + return {'sha': 'c' * 40, 'submodule_git_url': 'https://example.test/common'} + self.fail(url) + with patch.object(self.fetch, 'json', side_effect=fetch): + release = w.select_release(w.discover(watch, self.fetch)) + self.assertEqual(release['pkgver'], '2.0') + self.assertEqual(w.resolve_release_fields(watch, release, self.fetch)['variables'], + {'_commit': 'b' * 40, '_common': 'c' * 40}) + + def test_vendor_feeds_preserve_version_schemes(self): + cases = [ + ('1password-beta', 'Package: unrelated\nVersion: 99.0\n\nPackage: 1password\nVersion: 8.12.38~25.BETA\n', '8.12.38_25.BETA'), + ('spotify', 'Package: spotify-client\nVersion: 1:1.2.96.518.g366879e1\n', '1.2.96.518'), + ('typora', 'Package: typora\nVersion: 1.12.6-1\n\nPackage: typora\nVersion: 1.9.0-1\n', '1.12.6'), + ('nvidia-580xx-utils', '580.159.04/ 590.1/', '580.159.04'), + ] + for name, feed, expected in cases: + watch = json.loads((ROOT / 'pkgbuilds' / name / '.omarchy/package.json').read_text())['upstream']['watch'] + with self.subTest(package=name), patch.object(self.fetch, 'text', return_value=feed): + self.assertEqual(w.select_release(w.discover(watch, self.fetch))['pkgver'], expected) + with patch.object(self.fetch, 'json', return_value={'release': {'version': '2.0', 'commit': 'a' * 40}}): + release = w.discover({'json': 'https://example.test/feed', 'path': 'release.version', 'fields': {'commit': 'release.commit'}}, self.fetch)[0] + self.assertEqual(release['values']['commit'], 'a' * 40) + + def test_registry_releases_and_archive_filenames(self): + with patch.object(self.fetch, 'json', return_value={'dist-tags': {'latest': '2.0'}, 'time': {'2.0': '2026-01-01T00:00:00Z'}}): + self.assertEqual(w.discover({'npm': '@owner/tool'}, self.fetch)[0]['pkgver'], '2.0') + with patch.object(self.fetch, 'json', return_value={'info': {'version': '2.0'}, 'releases': {'2.0': [{'yanked': True}]}}): + with self.assertRaisesRegex(ValueError, 'unyanked'): + w.discover({'pypi': 'tool'}, self.fetch) + archive = self.root / 'vendor.zip' + with zipfile.ZipFile(archive, 'w') as z: + z.writestr('driver/yt6801-1.0.34.tar.gz', 'not executed or extracted') + watch = json.loads((ROOT / 'pkgbuilds/yt6801-dkms/.omarchy/package.json').read_text())['upstream']['watch'] + with patch.object(self.fetch, 'file', return_value=archive): + self.assertEqual(w.discover(watch, self.fetch)[0]['pkgver'], '1.0.34') + + def test_cursor_same_day_hash_uses_counter_not_hash_order(self): + self.write_watch({'regex': 'https://example.test/feed', 'pattern': r'(?P[0-9.]+)-(?P[a-f0-9]+)', + 'version': '{version}.1.{hash}', 'sequence': True}) + self.recipe.write_text(self.recipe.read_text().replace('pkgver=1.0', 'pkgver=2026.09.14.1.ffff')) + release = w.candidate({'version': '{version}.1.{hash}'}, {'version': '2026.09.14', 'hash': 'aaaa'}) + self.assertEqual(self.sync_release(release)['after'], '0:2026.09.14.2.aaaa-1') + self.assertEqual(self.sync_release(release)['status'], 'skipped') + + def test_existing_signed_metadata_skips_are_retained(self): + self.recipe.write_text(self.recipe.read_text().replace("'old-arm64'", "'SKIP'") + "sha256sums_aarch64[0]='SKIP'\n") + self.sync_release(self.release()) + self.assertEqual(w.read_recipe(self.recipe)['sha256sums_aarch64'], ['SKIP']) + self.assertTrue((self.root / 'source-tool-2.0-arm64').exists()) + + def test_conditional_arm_source_cannot_use_x86_hash(self): + self.recipe.write_text(self.recipe.read_text() + 'if [[ $CARCH == aarch64 ]]; then source_aarch64=("https://example.test/different-$pkgver"); fi\n') + original = self.recipe.read_bytes() + with self.assertRaisesRegex(ValueError, 'conditional source'): + self.sync_release(self.release()) + self.assertEqual(self.recipe.read_bytes(), original) + + def test_cli_continues_after_one_package_fails(self): + for directory in ['bin', 'helpers']: + shutil.copytree(ROOT / directory, self.root / directory) + for name in ['bad', 'good', 'held']: + pkg = self.root / 'pkgbuilds' / name + shutil.copytree(self.package, pkg) + (pkg / '.omarchy/package.json').write_text(json.dumps({'source': 'local', 'sync': name != 'held', 'upstream': {'watch': { + 'regex': 'https://example.test/feed', 'pattern': '(?P[0-9.]+)'}}})) + path = pkg / 'PKGBUILD' + path.write_text(path.read_text().replace('example.test/tool-', f'example.test/{name}-')) + stub = self.root / 'stub' + stub.mkdir() + curl = stub / 'curl' + curl.write_text('''#!/usr/bin/env python3 +import sys +from pathlib import Path +url = sys.argv[-1] +if 'bad-2.0-arm64' in url: sys.exit(22) +Path(sys.argv[sys.argv.index('-o') + 1]).write_text('2.0' if url.endswith('/feed') else url) +''') + curl.chmod(0o755) + bad = self.root / 'pkgbuilds/bad/PKGBUILD' + original = bad.read_bytes() + result = subprocess.run([str(self.root / 'bin/sync-upstream'), 'bad', 'good', 'held'], + env={**os.environ, 'PATH': str(stub) + os.pathsep + os.environ['PATH']}, + text=True, capture_output=True) + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertEqual(bad.read_bytes(), original) + self.assertEqual(w.scalar(w.read_recipe(self.root / 'pkgbuilds/good/PKGBUILD'), 'pkgver'), '2.0') + self.assertEqual(w.scalar(w.read_recipe(self.root / 'pkgbuilds/held/PKGBUILD'), 'pkgver'), '1.0') + self.assertIn('Updated: 1', result.stdout) + self.assertIn('Failed: 1', result.stdout) + + def test_aur_import_is_once_only_and_records_local_ownership(self): + for directory in ['bin', 'helpers']: + shutil.copytree(ROOT / directory, self.root / directory) + repo = self.root / 'aur' + repo.mkdir() + subprocess.run(['git', 'init', '-q', str(repo)], check=True) + (repo / 'PKGBUILD').write_text('pkgver=1.0\npkgrel=1\ntouch SHOULD-NOT-RUN\n') + (repo / '.SRCINFO').write_text('AUR only') + subprocess.run(['git', '-C', str(repo), 'add', '.'], check=True) + subprocess.run(['git', '-C', str(repo), '-c', 'user.name=Test', '-c', 'user.email=test@example.test', 'commit', '-qm', 'recipe'], check=True) + stub = self.root / 'stub' + stub.mkdir() + git = stub / 'git' + git.write_text('''#!/usr/bin/env python3 +import os, sys +args = [os.environ['AUR_FIXTURE'] if v == 'https://aur.archlinux.org/upstream-name.git' else v for v in sys.argv[1:]] +os.execv(os.environ['REAL_GIT'], ['git', *args]) +''') + git.chmod(0o755) + env = {**os.environ, 'PATH': str(stub) + os.pathsep + os.environ['PATH'], 'AUR_FIXTURE': str(repo), 'REAL_GIT': shutil.which('git')} + command = [str(self.root / 'bin/add-package'), 'local-name', '--source', 'aur', '--aur', 'upstream-name', '--no-sync', '--fast'] + result = subprocess.run(command, env=env, text=True, capture_output=True) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + package = self.root / 'pkgbuilds/local-name' + metadata_file = package / '.omarchy/package.json' + metadata = json.loads(metadata_file.read_text()) + self.assertEqual(metadata['source'], 'local') + self.assertEqual(metadata['origin']['aur'], 'upstream-name') + self.assertEqual(metadata['origin']['commit'], subprocess.check_output(['git', '-C', str(repo), 'rev-parse', 'HEAD'], text=True).strip()) + self.assertFalse(metadata['sync']) + self.assertEqual(metadata['release_ring'], 'fast') + self.assertFalse((package / '.SRCINFO').exists()) + self.assertFalse((package / 'SHOULD-NOT-RUN').exists()) + original = metadata_file.read_bytes() + result = subprocess.run([*command, '--force'], env=env, text=True, capture_output=True) + self.assertNotEqual(result.returncode, 0) + self.assertEqual(metadata_file.read_bytes(), original) + + +if __name__ == '__main__': + unittest.main(verbosity=2)