Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bce7b5345 | ||
|
|
18bef94a96 | ||
|
|
7b8347aee9 | ||
|
|
73f99ad8dc | ||
|
|
59c5942572 | ||
|
|
0e0e474b72 | ||
|
|
73b5e87e95 | ||
|
|
6401c42a91 | ||
|
|
3fdc6a608a | ||
|
|
9833b202f9 | ||
|
|
d3b2abecdd | ||
|
|
b9e2887b2f | ||
|
|
f33ec4b124 | ||
|
|
c0929c030a | ||
|
|
f02fc98097 | ||
|
|
08104de30c | ||
|
|
91fe77b794 | ||
|
|
5dc78222f6 | ||
|
|
71d6f41d92 | ||
|
|
a68fb112d7 | ||
|
|
84a1bbea8a | ||
|
|
8564f84ed5 | ||
|
|
07d13aca64 | ||
|
|
c34650a941 | ||
|
|
fdb4a492ef | ||
|
|
3cc4217790 | ||
|
|
f3af93802f | ||
|
|
1801be3549 |
@@ -2,6 +2,70 @@
|
|||||||
|
|
||||||
В файле фиксируются значимые изменения Nivora.
|
В файле фиксируются значимые изменения Nivora.
|
||||||
|
|
||||||
|
## 2026-07-25 — Vintner
|
||||||
|
|
||||||
|
### Изменено
|
||||||
|
|
||||||
|
- Пакет `msvc-go-wine` переименован в `vintner` вслед за ребрендингом
|
||||||
|
апстрима (github.com/Cheviiot/vintner); `replaces` обновлён для чистого
|
||||||
|
перехода при обновлении.
|
||||||
|
- Версия поднята до `0.2.0`: добавлена поддержка сборки KMDF/UMDF-драйверов
|
||||||
|
через Windows Driver Kit (`download --with-wdk`), короткие алиасы команд
|
||||||
|
и локализация CLI на английский и русский (`VINTNER_LANG`).
|
||||||
|
- Версия поднята до `0.3.0`: пакет теперь сам регистрирует автодополнение
|
||||||
|
для bash (`/usr/share/bash-completion/completions/vintner`) и zsh
|
||||||
|
(`/usr/share/zsh/site-functions/_vintner`) через хелпер Stapler
|
||||||
|
`install-completion` — работает сразу после `stplr install`, без
|
||||||
|
ручного `source <(vintner completion bash)`. Также добавлена корректная
|
||||||
|
остановка процессов Wine при завершении `vintner` по PID.
|
||||||
|
- Версия поднята до `0.3.1`: исправлен реальный баг в `toolrelay.exe` —
|
||||||
|
определение `mt.exe` по имени файла никогда не срабатывало (путь
|
||||||
|
приходил с прямыми слэшами, а проверка искала обратный), из-за чего
|
||||||
|
перевод кода возврата `mt.exe` для совместимости с CMake фактически не
|
||||||
|
работал ни разу. Найдено и исправлено при реальной сборке движка Ogre3D
|
||||||
|
через CMake+Ninja+cl.exe.
|
||||||
|
- Версия поднята до `0.4.0`: добавлена поддержка DirectX SDK (июнь 2010)
|
||||||
|
для сборки устаревшего кода на D3DX9 (`download --with-dxsdk`), и
|
||||||
|
алиасинг старых имён PlatformToolset (v90–v143) на единственный
|
||||||
|
установленный компилятор — теперь старые `.vcxproj`, закреплённые за
|
||||||
|
давними версиями тулсета, тоже собираются. В зависимости добавлен
|
||||||
|
`cabextract` (нужен рантайму для `--with-dxsdk`).
|
||||||
|
- Версия поднята до `0.5.0`: инструменты MSVC теперь можно вызывать без
|
||||||
|
добавления `<dest>/bin/<arch>` в PATH — напрямую как `vintner cl ...`,
|
||||||
|
`vintner msbuild ...` и т.д. Добавлена команда `vintner doctor`,
|
||||||
|
диагностирующая неисправную настройку wine/toolchain. `download` теперь
|
||||||
|
докачивает прерванные загрузки вместо перезапуска с нуля, а
|
||||||
|
`download`/`install` берут файловую блокировку на каталог назначения,
|
||||||
|
чтобы два параллельных запуска не повредили дерево файлов. Ошибка
|
||||||
|
«wine не найден» теперь называет конкретный пакет для установки.
|
||||||
|
Wine-процессы больше не зависают навечно при обрыве сборки (принудительно
|
||||||
|
отключён node reuse MSBuild, добавлена поддержка таймаута через
|
||||||
|
`VINTNER_TIMEOUT`).
|
||||||
|
|
||||||
|
## 2026-07-25 — Telegram Desktop
|
||||||
|
|
||||||
|
### Добавлено
|
||||||
|
|
||||||
|
- В каталог добавлен Telegram Desktop 7.0.5 для `amd64` из официального
|
||||||
|
статически собранного Linux-архива `tsetup.<version>.tar.xz`.
|
||||||
|
- Сохранены официальные desktop-id `org.telegram.desktop` и WM-класс
|
||||||
|
`TelegramDesktop`; иконка взята из официального репозитория
|
||||||
|
`telegramdesktop/tdesktop` для закреплённого тега релиза.
|
||||||
|
- Пакет добавляет команду `telegram-desktop`; сборка распространяется под
|
||||||
|
GPL-3.0-only с отдельным разрешением на линковку с OpenSSL.
|
||||||
|
|
||||||
|
## 2026-07-25 — Nivora CLI
|
||||||
|
|
||||||
|
### Изменено
|
||||||
|
|
||||||
|
- Пакет `nivora-stplr` полностью переработан и переименован в `nivora-cli`.
|
||||||
|
- Новая команда `nv` получила компактное интерактивное меню, русскую и
|
||||||
|
английскую локализацию, диагностику, dry-run и генерацию автодополнения.
|
||||||
|
- Повседневные операции доступны отдельными командами в стиле eepm:
|
||||||
|
`nvi`, `nve`, `nvu`, `nvs`, `nvqi`, `nvqa`, `nvr`, `nvrl`, `nvf`, `nvd`
|
||||||
|
и `nvc`.
|
||||||
|
- Прежние команды семейства `sl*` удалены без слоя совместимости.
|
||||||
|
|
||||||
## 2026-07-24 — GitHub Desktop
|
## 2026-07-24 — GitHub Desktop
|
||||||
|
|
||||||
### Добавлено
|
### Добавлено
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Nivora предлагает открытые рецепты упаковки д
|
|||||||
официальный репозиторий Stapler и не официальные пакеты upstream-проектов.
|
официальный репозиторий Stapler и не официальные пакеты upstream-проектов.
|
||||||
|
|
||||||
<!-- package-count -->
|
<!-- package-count -->
|
||||||
**19 пакетов** · **6 категорий** · `amd64`, `arm64` и `all`
|
**24 пакета** · **6 категорий** · `amd64`, `arm64` и `all`
|
||||||
|
|
||||||
[](https://github.com/Cheviiot/Nivora/actions/workflows/quality.yml)
|
[](https://github.com/Cheviiot/Nivora/actions/workflows/quality.yml)
|
||||||
|
|
||||||
@@ -47,9 +47,12 @@ stplr info nivora/codex
|
|||||||
|:--|:--:|:--:|:--|
|
|:--|:--:|:--:|:--|
|
||||||
| [Clash Verge Rev](https://github.com/clash-verge-rev/clash-verge-rev) | `2.5.2` | `amd64`, `arm64` | `stplr install nivora/clash-verge-rev` |
|
| [Clash Verge Rev](https://github.com/clash-verge-rev/clash-verge-rev) | `2.5.2` | `amd64`, `arm64` | `stplr install nivora/clash-verge-rev` |
|
||||||
| [Happ](https://happ.su/) | `3.3.6` | `amd64`, `arm64` | `stplr install nivora/happ` |
|
| [Happ](https://happ.su/) | `3.3.6` | `amd64`, `arm64` | `stplr install nivora/happ` |
|
||||||
| [NetBird](https://netbird.io/) | `0.75.0` | `amd64`, `arm64` | `stplr install nivora/netbird` |
|
| [MAX](https://max.ru/) (в песочнице Firejail) | `26.24.0~75261` | `amd64` | `stplr install nivora/max` |
|
||||||
| [Tailscale](https://tailscale.com/) | `1.98.9` | `amd64`, `arm64` | `stplr install nivora/tailscale` |
|
| [NetBird](https://netbird.io/) | `0.76.0` | `amd64`, `arm64` | `stplr install nivora/netbird` |
|
||||||
| [Яндекс Браузер](https://browser.yandex.ru/) | `26.4.1.1110` | `amd64` | `stplr install nivora/yandex-browser-stable` |
|
| [Tailscale](https://tailscale.com/) | `1.98.10` | `amd64`, `arm64` | `stplr install nivora/tailscale` |
|
||||||
|
| [Telegram](https://desktop.telegram.org/) | `7.0.6` | `amd64` | `stplr install nivora/telegram` |
|
||||||
|
| [VK Messenger](https://vk.me/app) | `6.0.57` | `amd64` | `stplr install nivora/vk-messenger` |
|
||||||
|
| [Яндекс Браузер](https://browser.yandex.ru/) | `26.6.1.1003` | `amd64` | `stplr install nivora/yandex-browser-stable` |
|
||||||
|
|
||||||
### Удалённый доступ
|
### Удалённый доступ
|
||||||
|
|
||||||
@@ -62,10 +65,12 @@ stplr info nivora/codex
|
|||||||
| Приложение | Версия | Архитектуры | Установка |
|
| Приложение | Версия | Архитектуры | Установка |
|
||||||
|:--|:--:|:--:|:--|
|
|:--|:--:|:--:|:--|
|
||||||
| [Chatbox](https://chatboxai.app/ru) | `1.20.3` | `amd64`, `arm64` | `stplr install nivora/chatbox` |
|
| [Chatbox](https://chatboxai.app/ru) | `1.20.3` | `amd64`, `arm64` | `stplr install nivora/chatbox` |
|
||||||
| [Claude](https://code.claude.com/docs/en/desktop-quickstart) | `1.24012.0` | `amd64`, `arm64` | `stplr install nivora/claude-desktop` |
|
| [Claude](docs/packages/claude.md) | `1.24012.0` | `amd64`, `arm64` | `stplr install nivora/claude` |
|
||||||
| [Codex](docs/packages/codex.md) | `26.721.31836` | `amd64` | `stplr install nivora/codex` |
|
| [ClaudeAlt](docs/packages/claude-alt.md) | `1.24012.0` | `amd64`, `arm64` | `stplr install nivora/claude-alt` |
|
||||||
|
| [Codex](docs/packages/codex.md) | `26.721.81911` | `amd64` | `stplr install nivora/codex` |
|
||||||
| [GitHub Desktop](docs/packages/github-desktop.md) | `3.6.3` | `amd64`, `arm64` | `stplr install nivora/github-desktop` |
|
| [GitHub Desktop](docs/packages/github-desktop.md) | `3.6.3` | `amd64`, `arm64` | `stplr install nivora/github-desktop` |
|
||||||
| [OpenCode](https://opencode.ai/) | `1.18.4` | `amd64`, `arm64` | `stplr install nivora/opencode` |
|
| [OpenCode](https://opencode.ai/) | `1.18.10` | `amd64`, `arm64` | `stplr install nivora/opencode` |
|
||||||
|
| [Vintner](https://github.com/Cheviiot/vintner) | `0.5.0` | `amd64`, `arm64` | `stplr install nivora/vintner` |
|
||||||
|
|
||||||
### Рабочий стол
|
### Рабочий стол
|
||||||
|
|
||||||
@@ -87,7 +92,7 @@ stplr info nivora/codex
|
|||||||
|:--|:--:|:--:|:--|
|
|:--|:--:|:--:|:--|
|
||||||
| [balenaEtcher](https://etcher.balena.io/) | `2.1.6` | `amd64` | `stplr install nivora/balena-etcher` |
|
| [balenaEtcher](https://etcher.balena.io/) | `2.1.6` | `amd64` | `stplr install nivora/balena-etcher` |
|
||||||
| [Fisher](https://github.com/jorgebucaran/fisher) | `4.4.8` | `all` | `stplr install nivora/fisher` |
|
| [Fisher](https://github.com/jorgebucaran/fisher) | `4.4.8` | `all` | `stplr install nivora/fisher` |
|
||||||
| [Nivora Stapler Helper](docs/packages/nivora-stplr.md) | `0.3.0` | `all` | `stplr install nivora/nivora-stplr` |
|
| [Nivora CLI](docs/packages/nivora-cli.md) | `1.0.0` | `all` | `stplr install nivora/nivora-cli` |
|
||||||
| [Ventoy](docs/packages/ventoy.md) | `1.1.17` | `amd64`, `arm64` | `stplr install nivora/ventoy` |
|
| [Ventoy](docs/packages/ventoy.md) | `1.1.17` | `amd64`, `arm64` | `stplr install nivora/ventoy` |
|
||||||
|
|
||||||
## Обновление
|
## Обновление
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
exec "${root}/tools/package_updates.sh" check claude-alt
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
name='claude-alt'
|
||||||
|
version=1.24012.0
|
||||||
|
release=1
|
||||||
|
summary='Independent secondary Claude desktop application'
|
||||||
|
summary_ru='Независимое второе приложение Claude'
|
||||||
|
group='Development/Tools'
|
||||||
|
desc='A fully independent secondary Claude Desktop installation with its own runtime, profile, desktop identity and Nivora icons.'
|
||||||
|
desc_ru='Полностью независимая вторая установка Claude Desktop с собственным runtime, профилем, desktop-идентичностью и иконками Nivora.'
|
||||||
|
homepage='https://github.com/Cheviiot/Nivora'
|
||||||
|
maintainer='Nivora <https://github.com/Cheviiot/Nivora>'
|
||||||
|
architectures=('amd64' 'arm64')
|
||||||
|
license=('Custom')
|
||||||
|
nonfree=1
|
||||||
|
nonfree_msg='ClaudeAlt использует проприетарный Claude Desktop и условия Anthropic.'
|
||||||
|
nonfree_url='https://www.anthropic.com/legal/consumer-terms'
|
||||||
|
provides=()
|
||||||
|
replaces=('claude-alt')
|
||||||
|
conflicts=()
|
||||||
|
auto_reqprov_method="dirty"
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
deps=()
|
||||||
|
deps_debian=('libgtk-3-0' 'libnotify4' 'libnss3' 'xdg-utils' 'libatspi2.0-0' 'libdrm2' 'libgbm1' 'libxcb-dri3-0' 'libsecret-1-0' 'libc6' 'libxtst6' 'libuuid1' 'xdg-desktop-portal')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('gtk3' 'libnotify' 'nss' 'xdg-utils' 'at-spi2-core' 'libdrm' 'mesa-libgbm' 'libxcb' 'libsecret' 'glibc' 'libXtst' 'libuuid' 'xdg-desktop-portal')
|
||||||
|
deps_arch=('gtk3' 'libnotify' 'nss' 'xdg-utils' 'at-spi2-core' 'libdrm' 'libgbm' 'libxcb' 'libsecret' 'glibc' 'libxtst' 'libutil-linux' 'xdg-desktop-portal')
|
||||||
|
deps_opensuse=('gtk3' 'libnotify4' 'mozilla-nss' 'xdg-utils' 'at-spi2-core' 'libdrm2' 'libgbm1' 'libxcb-dri3-0' 'libsecret-1-0' 'glibc' 'libXtst6' 'libuuid1' 'xdg-desktop-portal')
|
||||||
|
deps_altlinux=('libgtk+3' 'libnotify' 'libnss' 'xdg-utils' 'libat-spi2-core' 'libdrm' 'libgbm' 'libxcb' 'libsecret' 'glibc' 'libXtst' 'libuuid' 'xdg-desktop-portal')
|
||||||
|
|
||||||
|
build_deps=('binutils')
|
||||||
|
build_deps_debian=('binutils' 'python3')
|
||||||
|
build_deps_ubuntu=("${build_deps_debian[@]}")
|
||||||
|
build_deps_fedora=('binutils' 'python3')
|
||||||
|
build_deps_arch=('binutils' 'python')
|
||||||
|
build_deps_opensuse=('binutils' 'python3')
|
||||||
|
build_deps_altlinux=('binutils' 'python3')
|
||||||
|
|
||||||
|
sources=(
|
||||||
|
"https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${version}_amd64.deb?~archive=false&~name=claude-desktop.deb"
|
||||||
|
"local:///claude-alt"
|
||||||
|
"https://raw.githubusercontent.com/Cheviiot/Nivora/main/claude/claude-alt.png?~archive=false&~name=claude-alt.png"
|
||||||
|
"https://raw.githubusercontent.com/Cheviiot/Nivora/main/claude/claude-alt-tray-turquoise.png?~archive=false&~name=claude-alt-tray.png"
|
||||||
|
"local:///patch-asar.py"
|
||||||
|
)
|
||||||
|
sources_arm64=(
|
||||||
|
"https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${version}_arm64.deb?~archive=false&~name=claude-desktop.deb"
|
||||||
|
"local:///claude-alt"
|
||||||
|
"https://raw.githubusercontent.com/Cheviiot/Nivora/main/claude/claude-alt.png?~archive=false&~name=claude-alt.png"
|
||||||
|
"https://raw.githubusercontent.com/Cheviiot/Nivora/main/claude/claude-alt-tray-turquoise.png?~archive=false&~name=claude-alt-tray.png"
|
||||||
|
"local:///patch-asar.py"
|
||||||
|
)
|
||||||
|
checksums=(
|
||||||
|
'sha256:1096a8063956f8430fdbe504bb1c5e02985f31d0f45d082e4966e5d30ea7e3ac'
|
||||||
|
'sha256:b5264918d7cc3436bde057057e5790f617e42ccfcd1237d9170d26aea12799b8'
|
||||||
|
'sha256:f23de36a74c3f6ddae92511fc0dc659816853bf1d28520a6e0232fe2606fd0b4'
|
||||||
|
'sha256:21d1db80c30921346252ed405fa36cb5c48c287afdd8ebe474073389fd88e85e'
|
||||||
|
'sha256:14e0a5ce4da6afb25b13b3cee0b0264fbd896430dae85ade1f3394d8ca999e7d'
|
||||||
|
)
|
||||||
|
checksums_arm64=(
|
||||||
|
'sha256:37dd5dc1b0bfcb3192561acbd33cb59037806fe9b95221a3ddf38244203196f1'
|
||||||
|
'sha256:b5264918d7cc3436bde057057e5790f617e42ccfcd1237d9170d26aea12799b8'
|
||||||
|
'sha256:f23de36a74c3f6ddae92511fc0dc659816853bf1d28520a6e0232fe2606fd0b4'
|
||||||
|
'sha256:21d1db80c30921346252ed405fa36cb5c48c287afdd8ebe474073389fd88e85e'
|
||||||
|
'sha256:14e0a5ce4da6afb25b13b3cee0b0264fbd896430dae85ade1f3394d8ca999e7d'
|
||||||
|
)
|
||||||
|
|
||||||
|
scripts=(
|
||||||
|
['postinstall']='postinstall.sh'
|
||||||
|
['postremove']='postremove.sh'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}"
|
||||||
|
mkdir -p extracted
|
||||||
|
ar x claude-desktop.deb
|
||||||
|
tar -xf data.tar.* -C extracted
|
||||||
|
install -dm755 "${pkgdir}/usr/lib"
|
||||||
|
cp -a extracted/usr/lib/claude-desktop "${pkgdir}/usr/lib/claude-alt"
|
||||||
|
mv "${pkgdir}/usr/lib/claude-alt/claude-desktop" \
|
||||||
|
"${pkgdir}/usr/lib/claude-alt/claude-alt-bin"
|
||||||
|
chmod 0755 "${pkgdir}/usr/lib/claude-alt/claude-alt-bin" \
|
||||||
|
"${pkgdir}/usr/lib/claude-alt/chrome-sandbox"
|
||||||
|
python3 patch-asar.py "${pkgdir}/usr/lib/claude-alt/resources/app.asar"
|
||||||
|
install -Dm755 claude-alt "${pkgdir}/usr/lib/claude-alt/claude-alt"
|
||||||
|
install -Dm644 claude-alt.png "${pkgdir}/usr/lib/claude-alt/resources/icon.png"
|
||||||
|
for icon in TrayIconLinux.png TrayIconLinux-Dark.png; do
|
||||||
|
install -Dm644 claude-alt-tray.png \
|
||||||
|
"${pkgdir}/usr/lib/claude-alt/resources/${icon}"
|
||||||
|
done
|
||||||
|
install -dm755 "${pkgdir}/usr/bin"
|
||||||
|
ln -s /usr/lib/claude-alt/claude-alt "${pkgdir}/usr/bin/claude-alt"
|
||||||
|
ln -s claude-alt "${pkgdir}/usr/bin/claude-code-alt"
|
||||||
|
install -Dm644 claude-alt.png \
|
||||||
|
"${pkgdir}/usr/share/icons/hicolor/512x512/apps/claude-alt.png"
|
||||||
|
install -Dm644 /dev/stdin \
|
||||||
|
"${pkgdir}/usr/share/applications/com.anthropic.ClaudeAlt.desktop" <<'EOF'
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=ClaudeAlt
|
||||||
|
Name[ru]=ClaudeAlt
|
||||||
|
Comment=Independent secondary Claude desktop application
|
||||||
|
Comment[ru]=Независимое второе приложение Claude
|
||||||
|
GenericName=AI Assistant
|
||||||
|
Keywords=AI;Chat;Assistant;Claude;Code;LLM;
|
||||||
|
Exec=/usr/bin/claude-alt %U
|
||||||
|
Icon=claude-alt
|
||||||
|
Type=Application
|
||||||
|
StartupNotify=true
|
||||||
|
StartupWMClass=com.anthropic.ClaudeAlt
|
||||||
|
SingleMainWindow=true
|
||||||
|
Categories=Development;
|
||||||
|
Actions=NewChat;NewCode;
|
||||||
|
|
||||||
|
[Desktop Action NewChat]
|
||||||
|
Name=New chat
|
||||||
|
Name[ru]=Новый чат
|
||||||
|
Exec=/usr/bin/claude-alt claude://claude.ai/new
|
||||||
|
|
||||||
|
[Desktop Action NewCode]
|
||||||
|
Name=New Claude Code session
|
||||||
|
Name[ru]=Новая сессия Claude Code
|
||||||
|
Exec=/usr/bin/claude-alt claude://code/new
|
||||||
|
EOF
|
||||||
|
install-license extracted/usr/share/doc/claude-desktop/copyright \
|
||||||
|
"claude-alt/copyright"
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find "/usr/lib/claude-alt/**/*"
|
||||||
|
files-find-binary
|
||||||
|
files-find-desktop
|
||||||
|
files-find-license
|
||||||
|
files-find "/usr/share/icons/hicolor/*/apps/claude-alt.png"
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if [ -z "${HOME:-}" ] && [ -z "${XDG_CONFIG_HOME:-}" ]; then
|
||||||
|
echo "claude-alt: HOME or XDG_CONFIG_HOME is required" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
config_home="${XDG_CONFIG_HOME:-${HOME}/.config}"
|
||||||
|
default_data_dir="${config_home}/ClaudeAlt"
|
||||||
|
legacy_data_dir="${CLAUDE_DESKTOP_ACCOUNT2_DIR:-${config_home}/Claude-Account-2}"
|
||||||
|
claude_alt_executable="${CLAUDE_ALT_EXECUTABLE:-/usr/lib/claude-alt/claude-alt-bin}"
|
||||||
|
|
||||||
|
if [ -n "${CLAUDE_ALT_DATA_DIR:-}" ]; then
|
||||||
|
data_dir="${CLAUDE_ALT_DATA_DIR}"
|
||||||
|
elif [ -d "${default_data_dir}" ]; then
|
||||||
|
data_dir="${default_data_dir}"
|
||||||
|
elif [ -d "${legacy_data_dir}" ]; then
|
||||||
|
data_dir="${legacy_data_dir}"
|
||||||
|
else
|
||||||
|
data_dir="${default_data_dir}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "${claude_alt_executable}" ]; then
|
||||||
|
echo "claude-alt: executable not found: ${claude_alt_executable}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${data_dir}"
|
||||||
|
CHROME_DESKTOP='com.anthropic.ClaudeAlt.desktop'
|
||||||
|
export CHROME_DESKTOP
|
||||||
|
|
||||||
|
exec "${claude_alt_executable}" \
|
||||||
|
--user-data-dir="${data_dir}" \
|
||||||
|
--class=com.anthropic.ClaudeAlt \
|
||||||
|
"$@"
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Give ClaudeAlt an independent Electron identity without changing its protocol."""
|
||||||
|
|
||||||
|
import copy
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
path = Path(sys.argv[1])
|
||||||
|
data = path.read_bytes()
|
||||||
|
if len(data) < 16:
|
||||||
|
raise SystemExit("ClaudeAlt app.asar is too small")
|
||||||
|
|
||||||
|
_, _, _, header_size = struct.unpack("<IIII", data[:16])
|
||||||
|
header = json.loads(data[16 : 16 + header_size])
|
||||||
|
base_offset = 16 + ((header_size + 3) & ~3)
|
||||||
|
output = bytearray()
|
||||||
|
counts = {"package": 0, "socket": 0, "user_agent": 0}
|
||||||
|
|
||||||
|
|
||||||
|
def integrity(content: bytes, block_size: int) -> dict:
|
||||||
|
blocks = [
|
||||||
|
hashlib.sha256(content[index : index + block_size]).hexdigest()
|
||||||
|
for index in range(0, len(content), block_size)
|
||||||
|
] or [hashlib.sha256(b"").hexdigest()]
|
||||||
|
return {
|
||||||
|
"algorithm": "SHA256",
|
||||||
|
"hash": hashlib.sha256(content).hexdigest(),
|
||||||
|
"blockSize": block_size,
|
||||||
|
"blocks": blocks,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def rebuild(node: dict, prefix: str = "") -> dict:
|
||||||
|
result = {}
|
||||||
|
for name, child in node.get("files", {}).items():
|
||||||
|
item_path = f"{prefix}/{name}" if prefix else name
|
||||||
|
if "files" in child:
|
||||||
|
result[name] = {
|
||||||
|
**{key: value for key, value in child.items() if key != "files"},
|
||||||
|
"files": rebuild(child, item_path),
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
entry = copy.deepcopy(child)
|
||||||
|
if entry.get("unpacked"):
|
||||||
|
result[name] = entry
|
||||||
|
continue
|
||||||
|
|
||||||
|
offset, size = int(entry["offset"]), int(entry["size"])
|
||||||
|
content = data[base_offset + offset : base_offset + offset + size]
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
if item_path == "package.json":
|
||||||
|
package = json.loads(content)
|
||||||
|
expected = {
|
||||||
|
"productName": "Claude",
|
||||||
|
"desktopName": "com.anthropic.Claude.desktop",
|
||||||
|
}
|
||||||
|
for field, value in expected.items():
|
||||||
|
if package.get(field) != value:
|
||||||
|
raise SystemExit(
|
||||||
|
f"unexpected Claude package.json {field}: "
|
||||||
|
f"{package.get(field)!r} != {value!r}"
|
||||||
|
)
|
||||||
|
package["productName"] = "ClaudeAlt"
|
||||||
|
package["desktopName"] = "com.anthropic.ClaudeAlt.desktop"
|
||||||
|
content = (json.dumps(package, indent=2) + "\n").encode()
|
||||||
|
counts["package"] += 1
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
old_socket = b"claude-cowork-vm.sock"
|
||||||
|
socket_count = content.count(old_socket)
|
||||||
|
if socket_count:
|
||||||
|
content = content.replace(old_socket, b"claude-alt-cowork-vm.sock")
|
||||||
|
counts["socket"] += socket_count
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
marker = b'P.app.isPackaged||P.app.setName("Claude");RRn();'
|
||||||
|
marker_count = content.count(marker)
|
||||||
|
if marker_count:
|
||||||
|
content = content.replace(
|
||||||
|
marker,
|
||||||
|
b'P.app.isPackaged||P.app.setName("Claude");'
|
||||||
|
b'P.app.userAgentFallback=P.app.userAgentFallback'
|
||||||
|
b'.replaceAll("ClaudeAlt","Claude");RRn();',
|
||||||
|
)
|
||||||
|
counts["user_agent"] += marker_count
|
||||||
|
changed = True
|
||||||
|
|
||||||
|
entry["offset"] = str(len(output))
|
||||||
|
if changed:
|
||||||
|
entry["size"] = len(content)
|
||||||
|
block_size = entry.get("integrity", {}).get("blockSize", 4194304)
|
||||||
|
entry["integrity"] = integrity(content, block_size)
|
||||||
|
output.extend(content)
|
||||||
|
result[name] = entry
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
rebuilt_header = {"files": rebuild(header)}
|
||||||
|
if counts != {"package": 1, "socket": 1, "user_agent": 1}:
|
||||||
|
raise SystemExit(f"unexpected ClaudeAlt patch counts: {counts}")
|
||||||
|
|
||||||
|
header_bytes = json.dumps(rebuilt_header, separators=(",", ":")).encode()
|
||||||
|
padded_size = (len(header_bytes) + 3) & ~3
|
||||||
|
patched = (
|
||||||
|
struct.pack("<IIII", 4, padded_size + 8, padded_size + 4, len(header_bytes))
|
||||||
|
+ header_bytes
|
||||||
|
+ b"\0" * (padded_size - len(header_bytes))
|
||||||
|
+ bytes(output)
|
||||||
|
)
|
||||||
|
required = (
|
||||||
|
b"com.anthropic.ClaudeAlt.desktop",
|
||||||
|
b'"productName": "ClaudeAlt"',
|
||||||
|
b'.replaceAll("ClaudeAlt","Claude")',
|
||||||
|
b"claude-alt-cowork-vm.sock",
|
||||||
|
)
|
||||||
|
if any(patched.count(value) != 1 for value in required):
|
||||||
|
raise SystemExit("ClaudeAlt identity verification failed")
|
||||||
|
path.write_bytes(patched)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sandbox=/usr/lib/claude-alt/chrome-sandbox
|
||||||
|
if [[ ! -f "$sandbox" ]]; then
|
||||||
|
echo "Ошибка: не найден Electron sandbox: ${sandbox}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -L /proc/self/ns/user ]] && command -v unshare >/dev/null 2>&1 \
|
||||||
|
&& unshare --user true 2>/dev/null; then
|
||||||
|
chmod 0755 "$sandbox"
|
||||||
|
else
|
||||||
|
chmod 4755 "$sandbox"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
update-desktop-database -q /usr/share/applications || true
|
||||||
|
fi
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
gtk-update-icon-cache -f -q /usr/share/icons/hicolor || true
|
||||||
|
fi
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
update-desktop-database -q /usr/share/applications || true
|
||||||
|
fi
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
gtk-update-icon-cache -f -q /usr/share/icons/hicolor || true
|
||||||
|
fi
|
||||||
@@ -1,388 +0,0 @@
|
|||||||
name='claude-desktop'
|
|
||||||
version=1.24012.0
|
|
||||||
release=4
|
|
||||||
summary='Claude desktop application'
|
|
||||||
summary_ru='Десктопное приложение Claude'
|
|
||||||
group='Development/Tools'
|
|
||||||
desc='Claude is the Anthropic desktop application for Claude and Claude Code workflows with chat, project context, integrated terminal, editor and visual diff review.'
|
|
||||||
desc_ru='Claude — десктопное приложение Anthropic для Claude и сценариев Claude Code: чат, контекст проекта, встроенный терминал, редактор и визуальный просмотр diff.'
|
|
||||||
homepage='https://code.claude.com/docs/en/desktop-quickstart'
|
|
||||||
maintainer='Anthropic PBC <support@anthropic.com>'
|
|
||||||
|
|
||||||
architectures=('amd64' 'arm64')
|
|
||||||
|
|
||||||
license=('Custom')
|
|
||||||
nonfree=1
|
|
||||||
nonfree_msg='Claude Desktop является проприетарным приложением Anthropic. Использование Claude, Claude Code, учетной записи, подписки, сетевых функций и моделей регулируется условиями Anthropic.'
|
|
||||||
nonfree_url='https://www.anthropic.com/legal/consumer-terms'
|
|
||||||
|
|
||||||
provides=()
|
|
||||||
replaces=('claude-desktop')
|
|
||||||
conflicts=()
|
|
||||||
|
|
||||||
auto_reqprov_method="dirty"
|
|
||||||
auto_req=0
|
|
||||||
auto_prov=0
|
|
||||||
|
|
||||||
deps=()
|
|
||||||
deps_debian=('libgtk-3-0' 'libnotify4' 'libnss3' 'xdg-utils' 'libatspi2.0-0' 'libdrm2' 'libgbm1' 'libxcb-dri3-0' 'libsecret-1-0' 'libc6' 'libxtst6' 'libuuid1' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk | xdg-desktop-portal-gnome | xdg-desktop-portal-kde')
|
|
||||||
deps_ubuntu=("${deps_debian[@]}")
|
|
||||||
deps_fedora=('gtk3' 'libnotify' 'nss' 'xdg-utils' 'at-spi2-core' 'libdrm' 'mesa-libgbm' 'libxcb' 'libsecret' 'glibc' 'libXtst' 'libuuid' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
|
||||||
deps_arch=('gtk3' 'libnotify' 'nss' 'xdg-utils' 'at-spi2-core' 'libdrm' 'libgbm' 'libxcb' 'libsecret' 'glibc' 'libxtst' 'libutil-linux' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
|
||||||
deps_opensuse=('gtk3' 'libnotify4' 'mozilla-nss' 'xdg-utils' 'at-spi2-core' 'libdrm2' 'libgbm1' 'libxcb-dri3-0' 'libsecret-1-0' 'glibc' 'libXtst6' 'libuuid1' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
|
||||||
deps_altlinux=('libgtk+3' 'libnotify' 'libnss' 'xdg-utils' 'libat-spi2-core' 'libdrm' 'libgbm' 'libxcb' 'libsecret' 'glibc' 'libXtst' 'libuuid' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
|
||||||
|
|
||||||
opt_deps=()
|
|
||||||
opt_deps_debian=('libasound2t64 | libasound2 | pulseaudio' 'libayatana-appindicator3-1 | libappindicator3-1' 'ca-certificates' 'gnome-keyring | kwalletd6 | kwalletd5' 'qemu-system-x86' 'ovmf' 'virtiofsd')
|
|
||||||
opt_deps_ubuntu=("${opt_deps_debian[@]}")
|
|
||||||
opt_deps_fedora=('alsa-lib' 'pulseaudio-libs' 'libappindicator-gtk3' 'ca-certificates' 'gnome-keyring' 'kwallet' 'qemu-system-x86' 'edk2-ovmf' 'virtiofsd')
|
|
||||||
opt_deps_arch=('alsa-lib' 'pulseaudio' 'libappindicator-gtk3' 'ca-certificates' 'gnome-keyring' 'kwallet' 'qemu-system-x86' 'edk2-ovmf' 'virtiofsd')
|
|
||||||
opt_deps_opensuse=('libasound2' 'libpulse0' 'libappindicator3-1' 'ca-certificates' 'gnome-keyring' 'kwallet6' 'qemu-x86' 'ovmf' 'virtiofsd')
|
|
||||||
opt_deps_altlinux=('libalsa' 'libappindicator-gtk3' 'ca-certificates' 'gnome-keyring' 'qemu-system-x86' 'virtiofsd')
|
|
||||||
|
|
||||||
build_deps=('binutils')
|
|
||||||
build_deps_debian=('binutils' 'python3')
|
|
||||||
build_deps_ubuntu=("${build_deps_debian[@]}")
|
|
||||||
build_deps_fedora=('binutils' 'python3')
|
|
||||||
build_deps_arch=('binutils' 'python')
|
|
||||||
build_deps_opensuse=('binutils' 'python3')
|
|
||||||
build_deps_altlinux=('binutils' 'python3')
|
|
||||||
|
|
||||||
sources=(
|
|
||||||
"https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${version}_amd64.deb?~archive=false&~name=claude-desktop.deb"
|
|
||||||
"local:///claude-alt"
|
|
||||||
"local:///claude-alt.png"
|
|
||||||
"local:///claude-tray-orange.png"
|
|
||||||
"local:///claude-alt-tray-turquoise.png"
|
|
||||||
'local:///LICENSE'
|
|
||||||
)
|
|
||||||
|
|
||||||
sources_arm64=(
|
|
||||||
"https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${version}_arm64.deb?~archive=false&~name=claude-desktop.deb"
|
|
||||||
"local:///claude-alt"
|
|
||||||
"local:///claude-alt.png"
|
|
||||||
"local:///claude-tray-orange.png"
|
|
||||||
"local:///claude-alt-tray-turquoise.png"
|
|
||||||
'local:///LICENSE'
|
|
||||||
)
|
|
||||||
|
|
||||||
checksums=(
|
|
||||||
'sha256:1096a8063956f8430fdbe504bb1c5e02985f31d0f45d082e4966e5d30ea7e3ac'
|
|
||||||
'sha256:00d9fe6549d82f564a99c6e8ec54d1380fdf8f0a20c99bb9b3cda1f689adf57d'
|
|
||||||
'sha256:f23de36a74c3f6ddae92511fc0dc659816853bf1d28520a6e0232fe2606fd0b4'
|
|
||||||
'sha256:be51081c0e0b2eec3489c25da38194dccf68fe7445928b32c30e1b8051eb557b'
|
|
||||||
'sha256:21d1db80c30921346252ed405fa36cb5c48c287afdd8ebe474073389fd88e85e'
|
|
||||||
'sha256:40efe7a2755d02c9fe13f98cae18705e2d31e5bbb24816ebbd4951c5e3a56b3f'
|
|
||||||
)
|
|
||||||
|
|
||||||
checksums_arm64=(
|
|
||||||
'sha256:37dd5dc1b0bfcb3192561acbd33cb59037806fe9b95221a3ddf38244203196f1'
|
|
||||||
'sha256:00d9fe6549d82f564a99c6e8ec54d1380fdf8f0a20c99bb9b3cda1f689adf57d'
|
|
||||||
'sha256:f23de36a74c3f6ddae92511fc0dc659816853bf1d28520a6e0232fe2606fd0b4'
|
|
||||||
'sha256:be51081c0e0b2eec3489c25da38194dccf68fe7445928b32c30e1b8051eb557b'
|
|
||||||
'sha256:21d1db80c30921346252ed405fa36cb5c48c287afdd8ebe474073389fd88e85e'
|
|
||||||
'sha256:40efe7a2755d02c9fe13f98cae18705e2d31e5bbb24816ebbd4951c5e3a56b3f'
|
|
||||||
)
|
|
||||||
|
|
||||||
scripts=(
|
|
||||||
['postinstall']='postinstall.sh'
|
|
||||||
['postremove']='postremove.sh'
|
|
||||||
)
|
|
||||||
|
|
||||||
package() {
|
|
||||||
cd "${srcdir}"
|
|
||||||
|
|
||||||
mkdir -p "${srcdir}/extracted"
|
|
||||||
ar x claude-desktop.deb
|
|
||||||
tar -xf data.tar.* -C "${srcdir}/extracted"
|
|
||||||
|
|
||||||
install -dm755 "${pkgdir}/usr/lib"
|
|
||||||
cp -a "${srcdir}/extracted/usr/lib/claude-desktop" "${pkgdir}/usr/lib/"
|
|
||||||
chmod 0755 "${pkgdir}/usr/lib/claude-desktop/chrome-sandbox"
|
|
||||||
chmod 755 \
|
|
||||||
"${pkgdir}/usr/lib/claude-desktop/claude-desktop" \
|
|
||||||
"${pkgdir}/usr/lib/claude-desktop/resources/chrome-native-host" \
|
|
||||||
"${pkgdir}/usr/lib/claude-desktop/resources/cowork-linux-helper" \
|
|
||||||
"${pkgdir}/usr/lib/claude-desktop/resources/virtiofsd"
|
|
||||||
|
|
||||||
# Сохраняем штатный tray-глиф Claude, меняя только его цвет.
|
|
||||||
for icon_name in TrayIconLinux.png TrayIconLinux-Dark.png; do
|
|
||||||
install -Dm644 "${srcdir}/claude-tray-orange.png" \
|
|
||||||
"${pkgdir}/usr/lib/claude-desktop/resources/${icon_name}"
|
|
||||||
done
|
|
||||||
|
|
||||||
# ClaudeAlt получает отдельные executable и app.asar. Остальные неизменяемые
|
|
||||||
# Electron-файлы подключаются к основной копии относительными symlink-ами.
|
|
||||||
# Это сохраняет отдельный resourcesPath, но не удваивает пакет целиком.
|
|
||||||
install -dm755 \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/resources"
|
|
||||||
cp -p "${pkgdir}/usr/lib/claude-desktop/claude-desktop" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/claude-alt-bin"
|
|
||||||
|
|
||||||
for entry in "${pkgdir}/usr/lib/claude-desktop"/*; do
|
|
||||||
entry_name="${entry##*/}"
|
|
||||||
case "${entry_name}" in
|
|
||||||
claude-desktop | resources) continue ;;
|
|
||||||
esac
|
|
||||||
ln -s "../claude-desktop/${entry_name}" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/${entry_name}"
|
|
||||||
done
|
|
||||||
|
|
||||||
for entry in "${pkgdir}/usr/lib/claude-desktop/resources"/*; do
|
|
||||||
entry_name="${entry##*/}"
|
|
||||||
case "${entry_name}" in
|
|
||||||
app.asar)
|
|
||||||
cp -p "${entry}" "${pkgdir}/usr/lib/claude-alt/resources/app.asar"
|
|
||||||
;;
|
|
||||||
icon.png | TrayIconLinux.png | TrayIconLinux-Dark.png)
|
|
||||||
# Эти ресурсы ниже заменяются иконкой ClaudeAlt.
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
ln -s "../../claude-desktop/resources/${entry_name}" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/resources/${entry_name}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Большая иконка ClaudeAlt используется окном, а в tray устанавливается
|
|
||||||
# отдельный бирюзовый вариант штатного глифа Claude.
|
|
||||||
install -Dm644 "${srcdir}/claude-alt.png" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/resources/icon.png"
|
|
||||||
for icon_name in TrayIconLinux.png TrayIconLinux-Dark.png; do
|
|
||||||
install -Dm644 "${srcdir}/claude-alt-tray-turquoise.png" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/resources/${icon_name}"
|
|
||||||
done
|
|
||||||
|
|
||||||
alt_asar="${pkgdir}/usr/lib/claude-alt/resources/app.asar"
|
|
||||||
|
|
||||||
python3 - "${alt_asar}" <<'PY'
|
|
||||||
import copy
|
|
||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
asar_path = Path(sys.argv[1])
|
|
||||||
data = asar_path.read_bytes()
|
|
||||||
if len(data) < 16:
|
|
||||||
raise SystemExit("ClaudeAlt app.asar is too small")
|
|
||||||
|
|
||||||
_, _, _, header_size = struct.unpack("<IIII", data[:16])
|
|
||||||
header = json.loads(data[16 : 16 + header_size])
|
|
||||||
base_offset = 16 + ((header_size + 3) & ~3)
|
|
||||||
output = bytearray()
|
|
||||||
patched_package_json = 0
|
|
||||||
patched_cowork_socket = 0
|
|
||||||
patched_user_agent = 0
|
|
||||||
|
|
||||||
|
|
||||||
def integrity_for(content: bytes, block_size: int = 4194304) -> dict:
|
|
||||||
blocks = [
|
|
||||||
hashlib.sha256(content[index : index + block_size]).hexdigest()
|
|
||||||
for index in range(0, len(content), block_size)
|
|
||||||
]
|
|
||||||
if not blocks:
|
|
||||||
blocks = [hashlib.sha256(b"").hexdigest()]
|
|
||||||
return {
|
|
||||||
"algorithm": "SHA256",
|
|
||||||
"hash": hashlib.sha256(content).hexdigest(),
|
|
||||||
"blockSize": block_size,
|
|
||||||
"blocks": blocks,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def rebuild_node(node: dict, prefix: str = "") -> dict:
|
|
||||||
global patched_cowork_socket, patched_package_json, patched_user_agent
|
|
||||||
|
|
||||||
rebuilt = {}
|
|
||||||
for name, child in node.get("files", {}).items():
|
|
||||||
path = f"{prefix}/{name}" if prefix else name
|
|
||||||
if "files" in child:
|
|
||||||
rebuilt[name] = {
|
|
||||||
**{key: value for key, value in child.items() if key != "files"},
|
|
||||||
"files": rebuild_node(child, path),
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
|
|
||||||
entry = copy.deepcopy(child)
|
|
||||||
if entry.get("unpacked"):
|
|
||||||
rebuilt[name] = entry
|
|
||||||
continue
|
|
||||||
|
|
||||||
offset = int(entry["offset"])
|
|
||||||
size = int(entry["size"])
|
|
||||||
content = data[base_offset + offset : base_offset + offset + size]
|
|
||||||
content_changed = False
|
|
||||||
|
|
||||||
if path == "package.json":
|
|
||||||
package_json = json.loads(content)
|
|
||||||
expected = {
|
|
||||||
"productName": "Claude",
|
|
||||||
"desktopName": "com.anthropic.Claude.desktop",
|
|
||||||
}
|
|
||||||
for field, expected_value in expected.items():
|
|
||||||
if package_json.get(field) != expected_value:
|
|
||||||
raise SystemExit(
|
|
||||||
f"unexpected Claude package.json {field}: "
|
|
||||||
f"{package_json.get(field)!r} != {expected_value!r}"
|
|
||||||
)
|
|
||||||
# Отдельный productName нужен Electron для независимого instance
|
|
||||||
# lock. Официальный User-Agent восстанавливается ниже отдельно.
|
|
||||||
package_json["productName"] = "ClaudeAlt"
|
|
||||||
package_json["desktopName"] = "com.anthropic.ClaudeAlt.desktop"
|
|
||||||
content = (json.dumps(package_json, indent=2) + "\n").encode("utf-8")
|
|
||||||
patched_package_json += 1
|
|
||||||
content_changed = True
|
|
||||||
|
|
||||||
socket_name = b"claude-cowork-vm.sock"
|
|
||||||
socket_matches = content.count(socket_name)
|
|
||||||
if socket_matches:
|
|
||||||
content = content.replace(socket_name, b"claude-alt-cowork-vm.sock")
|
|
||||||
patched_cowork_socket += socket_matches
|
|
||||||
content_changed = True
|
|
||||||
|
|
||||||
user_agent_marker = (
|
|
||||||
b'P.app.isPackaged||P.app.setName("Claude");RRn();'
|
|
||||||
)
|
|
||||||
user_agent_matches = content.count(user_agent_marker)
|
|
||||||
if user_agent_matches:
|
|
||||||
content = content.replace(
|
|
||||||
user_agent_marker,
|
|
||||||
b'P.app.isPackaged||P.app.setName("Claude");'
|
|
||||||
b'P.app.userAgentFallback=P.app.userAgentFallback'
|
|
||||||
b'.replaceAll("ClaudeAlt","Claude");RRn();',
|
|
||||||
)
|
|
||||||
patched_user_agent += user_agent_matches
|
|
||||||
content_changed = True
|
|
||||||
|
|
||||||
entry["offset"] = str(len(output))
|
|
||||||
if content_changed:
|
|
||||||
entry["size"] = len(content)
|
|
||||||
entry["integrity"] = integrity_for(
|
|
||||||
content,
|
|
||||||
entry.get("integrity", {}).get("blockSize", 4194304),
|
|
||||||
)
|
|
||||||
output.extend(content)
|
|
||||||
rebuilt[name] = entry
|
|
||||||
|
|
||||||
return rebuilt
|
|
||||||
|
|
||||||
|
|
||||||
rebuilt_header = {"files": rebuild_node(header)}
|
|
||||||
if patched_package_json != 1:
|
|
||||||
raise SystemExit(
|
|
||||||
f"expected one ClaudeAlt package.json, got {patched_package_json}"
|
|
||||||
)
|
|
||||||
if patched_cowork_socket != 1:
|
|
||||||
raise SystemExit(
|
|
||||||
f"expected one ClaudeAlt Cowork socket, got {patched_cowork_socket}"
|
|
||||||
)
|
|
||||||
if patched_user_agent != 1:
|
|
||||||
raise SystemExit(
|
|
||||||
f"expected one ClaudeAlt User-Agent patch, got {patched_user_agent}"
|
|
||||||
)
|
|
||||||
|
|
||||||
header_bytes = json.dumps(rebuilt_header, separators=(",", ":")).encode("utf-8")
|
|
||||||
header_padded_size = (len(header_bytes) + 3) & ~3
|
|
||||||
patched_data = (
|
|
||||||
struct.pack(
|
|
||||||
"<IIII",
|
|
||||||
4,
|
|
||||||
header_padded_size + 8,
|
|
||||||
header_padded_size + 4,
|
|
||||||
len(header_bytes),
|
|
||||||
)
|
|
||||||
+ header_bytes
|
|
||||||
+ (b"\0" * (header_padded_size - len(header_bytes)))
|
|
||||||
+ bytes(output)
|
|
||||||
)
|
|
||||||
if patched_data.count(b"com.anthropic.ClaudeAlt.desktop") != 1:
|
|
||||||
raise SystemExit("ClaudeAlt desktopName was not written exactly once")
|
|
||||||
if patched_data.count(b'"productName": "ClaudeAlt"') != 1:
|
|
||||||
raise SystemExit("ClaudeAlt productName was not written exactly once")
|
|
||||||
if patched_data.count(b'.replaceAll("ClaudeAlt","Claude")') != 1:
|
|
||||||
raise SystemExit("ClaudeAlt official User-Agent patch is missing")
|
|
||||||
if patched_data.count(b"claude-alt-cowork-vm.sock") != 1:
|
|
||||||
raise SystemExit("ClaudeAlt Cowork socket was not written exactly once")
|
|
||||||
asar_path.write_bytes(patched_data)
|
|
||||||
PY
|
|
||||||
|
|
||||||
chmod 755 "${pkgdir}/usr/lib/claude-alt/claude-alt-bin"
|
|
||||||
install -Dm755 "${srcdir}/claude-alt" \
|
|
||||||
"${pkgdir}/usr/lib/claude-alt/claude-alt"
|
|
||||||
|
|
||||||
install -dm755 "${pkgdir}/usr/share"
|
|
||||||
cp -a "${srcdir}/extracted/usr/share/applications" "${pkgdir}/usr/share/"
|
|
||||||
cp -a "${srcdir}/extracted/usr/share/icons" "${pkgdir}/usr/share/"
|
|
||||||
|
|
||||||
desktop_file="$(find "${pkgdir}/usr/share/applications" -maxdepth 1 -type f -name "*.desktop" | head -1)"
|
|
||||||
[[ -n "${desktop_file}" ]] || {
|
|
||||||
echo "Claude desktop file not found" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
sed -i \
|
|
||||||
-e '0,/^Name=/{s/^Name=.*/Name=Claude\nName[ru]=Claude/}' \
|
|
||||||
-e 's/^Categories=.*/Categories=Development;/' \
|
|
||||||
"${desktop_file}"
|
|
||||||
|
|
||||||
install -Dm644 "${srcdir}/claude-alt.png" \
|
|
||||||
"${pkgdir}/usr/share/icons/hicolor/512x512/apps/claude-alt.png"
|
|
||||||
|
|
||||||
install -Dm644 /dev/stdin "${pkgdir}/usr/share/applications/com.anthropic.ClaudeAlt.desktop" <<'EOF'
|
|
||||||
[Desktop Entry]
|
|
||||||
Name=ClaudeAlt
|
|
||||||
Name[ru]=ClaudeAlt
|
|
||||||
Comment=Independent secondary Claude desktop application
|
|
||||||
Comment[ru]=Независимое второе приложение Claude
|
|
||||||
GenericName=AI Assistant
|
|
||||||
Keywords=AI;Chat;Assistant;Claude;Code;LLM;
|
|
||||||
Exec=claude-alt %U
|
|
||||||
Icon=claude-alt
|
|
||||||
Type=Application
|
|
||||||
StartupNotify=true
|
|
||||||
StartupWMClass=com.anthropic.ClaudeAlt
|
|
||||||
SingleMainWindow=true
|
|
||||||
Categories=Development;
|
|
||||||
Actions=NewChat;NewCode;
|
|
||||||
|
|
||||||
[Desktop Action NewChat]
|
|
||||||
Name=New chat
|
|
||||||
Name[ru]=Новый чат
|
|
||||||
Exec=claude-alt claude://claude.ai/new
|
|
||||||
|
|
||||||
[Desktop Action NewCode]
|
|
||||||
Name=New Claude Code session
|
|
||||||
Name[ru]=Новая сессия Claude Code
|
|
||||||
Exec=claude-alt claude://code/new
|
|
||||||
EOF
|
|
||||||
|
|
||||||
install -dm755 "${pkgdir}/usr/bin"
|
|
||||||
ln -sfn /usr/lib/claude-desktop/claude-desktop "${pkgdir}/usr/bin/claude-desktop"
|
|
||||||
ln -sfn /usr/lib/claude-alt/claude-alt "${pkgdir}/usr/bin/claude-alt"
|
|
||||||
ln -sfn /usr/lib/claude-alt/claude-alt "${pkgdir}/usr/bin/claude-code-alt"
|
|
||||||
ln -sfn /usr/lib/claude-alt/claude-alt "${pkgdir}/usr/bin/claude-desktop-account2"
|
|
||||||
|
|
||||||
install -dm755 "${pkgdir}/usr/share/licenses/claude-desktop"
|
|
||||||
install-license "${srcdir}/LICENSE" "claude-desktop/LICENSE.nivora"
|
|
||||||
install -Dm644 "${srcdir}/extracted/usr/share/doc/claude-desktop/copyright" \
|
|
||||||
"${pkgdir}/usr/share/licenses/claude-desktop/copyright"
|
|
||||||
install -Dm644 "${srcdir}/extracted/usr/lib/claude-desktop/LICENSES.chromium.html" \
|
|
||||||
"${pkgdir}/usr/share/licenses/claude-desktop/LICENSES.chromium.html"
|
|
||||||
install -Dm644 "${srcdir}/extracted/usr/lib/claude-desktop/resources/virtiofsd.LICENSE-APACHE" \
|
|
||||||
"${pkgdir}/usr/share/licenses/claude-desktop/virtiofsd.LICENSE-APACHE"
|
|
||||||
install -Dm644 "${srcdir}/extracted/usr/lib/claude-desktop/resources/virtiofsd.LICENSE-BSD-3-Clause" \
|
|
||||||
"${pkgdir}/usr/share/licenses/claude-desktop/virtiofsd.LICENSE-BSD-3-Clause"
|
|
||||||
}
|
|
||||||
|
|
||||||
files() {
|
|
||||||
files-find-binary
|
|
||||||
files-find-desktop
|
|
||||||
files-find-license
|
|
||||||
files-find \
|
|
||||||
"/usr/lib/claude-desktop/**/*" \
|
|
||||||
"/usr/lib/claude-alt/**/*" \
|
|
||||||
"/usr/share/icons/hicolor/*/apps/claude-desktop.png" \
|
|
||||||
"/usr/share/icons/hicolor/*/apps/claude-alt.png"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
name='claude'
|
||||||
|
version=1.24012.0
|
||||||
|
release=1
|
||||||
|
summary='Claude desktop application'
|
||||||
|
summary_ru='Десктопное приложение Claude'
|
||||||
|
group='Development/Tools'
|
||||||
|
desc='Claude is the Anthropic desktop application for Claude and Claude Code workflows with chat, project context, integrated terminal, editor and visual diff review.'
|
||||||
|
desc_ru='Claude — десктопное приложение Anthropic для Claude и сценариев Claude Code: чат, контекст проекта, встроенный терминал, редактор и визуальный просмотр diff.'
|
||||||
|
homepage='https://code.claude.com/docs/en/desktop-quickstart'
|
||||||
|
maintainer='Anthropic PBC <support@anthropic.com>'
|
||||||
|
|
||||||
|
architectures=('amd64' 'arm64')
|
||||||
|
|
||||||
|
license=('Custom')
|
||||||
|
nonfree=1
|
||||||
|
nonfree_msg='Claude Desktop является проприетарным приложением Anthropic. Использование Claude, Claude Code, учетной записи, подписки, сетевых функций и моделей регулируется условиями Anthropic.'
|
||||||
|
nonfree_url='https://www.anthropic.com/legal/consumer-terms'
|
||||||
|
|
||||||
|
provides=()
|
||||||
|
replaces=('claude' 'claude-desktop')
|
||||||
|
conflicts=()
|
||||||
|
|
||||||
|
auto_reqprov_method="dirty"
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
deps=()
|
||||||
|
deps_debian=('libgtk-3-0' 'libnotify4' 'libnss3' 'xdg-utils' 'libatspi2.0-0' 'libdrm2' 'libgbm1' 'libxcb-dri3-0' 'libsecret-1-0' 'libc6' 'libxtst6' 'libuuid1' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk | xdg-desktop-portal-gnome | xdg-desktop-portal-kde')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('gtk3' 'libnotify' 'nss' 'xdg-utils' 'at-spi2-core' 'libdrm' 'mesa-libgbm' 'libxcb' 'libsecret' 'glibc' 'libXtst' 'libuuid' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
||||||
|
deps_arch=('gtk3' 'libnotify' 'nss' 'xdg-utils' 'at-spi2-core' 'libdrm' 'libgbm' 'libxcb' 'libsecret' 'glibc' 'libxtst' 'libutil-linux' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
||||||
|
deps_opensuse=('gtk3' 'libnotify4' 'mozilla-nss' 'xdg-utils' 'at-spi2-core' 'libdrm2' 'libgbm1' 'libxcb-dri3-0' 'libsecret-1-0' 'glibc' 'libXtst6' 'libuuid1' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
||||||
|
deps_altlinux=('libgtk+3' 'libnotify' 'libnss' 'xdg-utils' 'libat-spi2-core' 'libdrm' 'libgbm' 'libxcb' 'libsecret' 'glibc' 'libXtst' 'libuuid' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk')
|
||||||
|
|
||||||
|
opt_deps=()
|
||||||
|
opt_deps_debian=('libasound2t64 | libasound2 | pulseaudio' 'libayatana-appindicator3-1 | libappindicator3-1' 'ca-certificates' 'gnome-keyring | kwalletd6 | kwalletd5' 'qemu-system-x86' 'ovmf' 'virtiofsd')
|
||||||
|
opt_deps_ubuntu=("${opt_deps_debian[@]}")
|
||||||
|
opt_deps_fedora=('alsa-lib' 'pulseaudio-libs' 'libappindicator-gtk3' 'ca-certificates' 'gnome-keyring' 'kwallet' 'qemu-system-x86' 'edk2-ovmf' 'virtiofsd')
|
||||||
|
opt_deps_arch=('alsa-lib' 'pulseaudio' 'libappindicator-gtk3' 'ca-certificates' 'gnome-keyring' 'kwallet' 'qemu-system-x86' 'edk2-ovmf' 'virtiofsd')
|
||||||
|
opt_deps_opensuse=('libasound2' 'libpulse0' 'libappindicator3-1' 'ca-certificates' 'gnome-keyring' 'kwallet6' 'qemu-x86' 'ovmf' 'virtiofsd')
|
||||||
|
opt_deps_altlinux=('libalsa' 'libappindicator-gtk3' 'ca-certificates' 'gnome-keyring' 'qemu-system-x86' 'virtiofsd')
|
||||||
|
|
||||||
|
build_deps=('binutils')
|
||||||
|
build_deps_debian=('binutils' 'python3')
|
||||||
|
build_deps_ubuntu=("${build_deps_debian[@]}")
|
||||||
|
build_deps_fedora=('binutils' 'python3')
|
||||||
|
build_deps_arch=('binutils' 'python')
|
||||||
|
build_deps_opensuse=('binutils' 'python3')
|
||||||
|
build_deps_altlinux=('binutils' 'python3')
|
||||||
|
|
||||||
|
sources=(
|
||||||
|
"https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${version}_amd64.deb?~archive=false&~name=claude-desktop.deb"
|
||||||
|
"local:///claude-tray-orange.png"
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
sources_arm64=(
|
||||||
|
"https://downloads.claude.ai/claude-desktop/apt/stable/pool/main/c/claude-desktop/claude-desktop_${version}_arm64.deb?~archive=false&~name=claude-desktop.deb"
|
||||||
|
"local:///claude-tray-orange.png"
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums=(
|
||||||
|
'sha256:1096a8063956f8430fdbe504bb1c5e02985f31d0f45d082e4966e5d30ea7e3ac'
|
||||||
|
'sha256:be51081c0e0b2eec3489c25da38194dccf68fe7445928b32c30e1b8051eb557b'
|
||||||
|
'sha256:40efe7a2755d02c9fe13f98cae18705e2d31e5bbb24816ebbd4951c5e3a56b3f'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums_arm64=(
|
||||||
|
'sha256:37dd5dc1b0bfcb3192561acbd33cb59037806fe9b95221a3ddf38244203196f1'
|
||||||
|
'sha256:be51081c0e0b2eec3489c25da38194dccf68fe7445928b32c30e1b8051eb557b'
|
||||||
|
'sha256:40efe7a2755d02c9fe13f98cae18705e2d31e5bbb24816ebbd4951c5e3a56b3f'
|
||||||
|
)
|
||||||
|
|
||||||
|
scripts=(
|
||||||
|
['postinstall']='postinstall.sh'
|
||||||
|
['postremove']='postremove.sh'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}"
|
||||||
|
|
||||||
|
mkdir -p "${srcdir}/extracted"
|
||||||
|
ar x claude-desktop.deb
|
||||||
|
tar -xf data.tar.* -C "${srcdir}/extracted"
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/lib"
|
||||||
|
cp -a "${srcdir}/extracted/usr/lib/claude-desktop" "${pkgdir}/usr/lib/"
|
||||||
|
chmod 0755 "${pkgdir}/usr/lib/claude-desktop/chrome-sandbox"
|
||||||
|
chmod 755 \
|
||||||
|
"${pkgdir}/usr/lib/claude-desktop/claude-desktop" \
|
||||||
|
"${pkgdir}/usr/lib/claude-desktop/resources/chrome-native-host" \
|
||||||
|
"${pkgdir}/usr/lib/claude-desktop/resources/cowork-linux-helper" \
|
||||||
|
"${pkgdir}/usr/lib/claude-desktop/resources/virtiofsd"
|
||||||
|
|
||||||
|
# Сохраняем штатный tray-глиф Claude, меняя только его цвет.
|
||||||
|
for icon_name in TrayIconLinux.png TrayIconLinux-Dark.png; do
|
||||||
|
install -Dm644 "${srcdir}/claude-tray-orange.png" \
|
||||||
|
"${pkgdir}/usr/lib/claude-desktop/resources/${icon_name}"
|
||||||
|
done
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/share"
|
||||||
|
cp -a "${srcdir}/extracted/usr/share/applications" "${pkgdir}/usr/share/"
|
||||||
|
cp -a "${srcdir}/extracted/usr/share/icons" "${pkgdir}/usr/share/"
|
||||||
|
|
||||||
|
desktop_file="$(find "${pkgdir}/usr/share/applications" -maxdepth 1 -type f -name "*.desktop" | head -1)"
|
||||||
|
[[ -n "${desktop_file}" ]] || {
|
||||||
|
echo "Claude desktop file not found" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
sed -i \
|
||||||
|
-e '0,/^Name=/{s/^Name=.*/Name=Claude\nName[ru]=Claude/}' \
|
||||||
|
-e 's/^Categories=.*/Categories=Development;/' \
|
||||||
|
"${desktop_file}"
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/bin"
|
||||||
|
ln -sfn /usr/lib/claude-desktop/claude-desktop "${pkgdir}/usr/bin/claude-desktop"
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/share/licenses/claude-desktop"
|
||||||
|
install-license "${srcdir}/LICENSE" "claude-desktop/LICENSE.nivora"
|
||||||
|
install -Dm644 "${srcdir}/extracted/usr/share/doc/claude-desktop/copyright" \
|
||||||
|
"${pkgdir}/usr/share/licenses/claude-desktop/copyright"
|
||||||
|
install -Dm644 "${srcdir}/extracted/usr/lib/claude-desktop/LICENSES.chromium.html" \
|
||||||
|
"${pkgdir}/usr/share/licenses/claude-desktop/LICENSES.chromium.html"
|
||||||
|
install -Dm644 "${srcdir}/extracted/usr/lib/claude-desktop/resources/virtiofsd.LICENSE-APACHE" \
|
||||||
|
"${pkgdir}/usr/share/licenses/claude-desktop/virtiofsd.LICENSE-APACHE"
|
||||||
|
install -Dm644 "${srcdir}/extracted/usr/lib/claude-desktop/resources/virtiofsd.LICENSE-BSD-3-Clause" \
|
||||||
|
"${pkgdir}/usr/share/licenses/claude-desktop/virtiofsd.LICENSE-BSD-3-Clause"
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find-binary
|
||||||
|
files-find-desktop
|
||||||
|
files-find-license
|
||||||
|
files-find \
|
||||||
|
"/usr/lib/claude-desktop/**/*" \
|
||||||
|
"/usr/share/icons/hicolor/*/apps/claude-desktop.png"
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -1,5 +1,5 @@
|
|||||||
name='codex'
|
name='codex'
|
||||||
version=26.721.31836
|
version=26.721.81911
|
||||||
release=1
|
release=1
|
||||||
summary='Unofficial Linux repack of the Codex desktop app'
|
summary='Unofficial Linux repack of the Codex desktop app'
|
||||||
summary_ru='Неофициальная Linux-перепаковка десктопного приложения Codex'
|
summary_ru='Неофициальная Linux-перепаковка десктопного приложения Codex'
|
||||||
@@ -51,7 +51,7 @@ sources=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
checksums=(
|
checksums=(
|
||||||
'sha256:f48c0ae3fca556d66525b863dd009a0bd0702115517f83c39f8a44cf4d128eb3'
|
'sha256:87798af5884c55a1faab57c8fef818a827a9f0243241c94d19a467d8216aef31'
|
||||||
'sha256:8cde2dac642947cdfab23d302056ef81b574cc7f5684f25f7116f80411ec551c'
|
'sha256:8cde2dac642947cdfab23d302056ef81b574cc7f5684f25f7116f80411ec551c'
|
||||||
'sha256:fab36489be4f1e92591d2ebcd28a96a95f788b5d1ba87824985623ab7df5e3f4'
|
'sha256:fab36489be4f1e92591d2ebcd28a96a95f788b5d1ba87824985623ab7df5e3f4'
|
||||||
'sha256:9259dc4b9ae217855d55414b2266db08d9b40c5b0cdbca20a183234ff55ba006'
|
'sha256:9259dc4b9ae217855d55414b2266db08d9b40c5b0cdbca20a183234ff55ba006'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Инварианты
|
## Инварианты
|
||||||
|
|
||||||
- В репозитории ровно 19 каталогов с `Staplerfile`.
|
- В репозитории ровно 24 каталога с `Staplerfile`.
|
||||||
- Каталог совпадает с `name` и командой в README.
|
- Каталог совпадает с `name` и командой в README.
|
||||||
- Upstream-версия не меняется из-за патча рецепта; для этого повышается `release`.
|
- Upstream-версия не меняется из-за патча рецепта; для этого повышается `release`.
|
||||||
- Desktop-id, AppStream component-id, units и пути данных не меняются без отдельной миграции.
|
- Desktop-id, AppStream component-id, units и пути данных не меняются без отдельной миграции.
|
||||||
@@ -17,10 +17,12 @@ Stapler сам добавляет текущее `name` в generated `Provides`
|
|||||||
| Package ID | Основание |
|
| Package ID | Основание |
|
||||||
|:--|:--|
|
|:--|:--|
|
||||||
| `clash-verge-rev` | Upstream-репозиторий и release title: Clash Verge Rev |
|
| `clash-verge-rev` | Upstream-репозиторий и release title: Clash Verge Rev |
|
||||||
| `claude-desktop` | Upstream DEB: `Package: claude-desktop`; desktop-id `com.anthropic.Claude` сохранён |
|
| `claude` | Upstream DEB: `Package: claude-desktop`; desktop-id `com.anthropic.Claude` сохранён; старое имя пакета `claude-desktop` заменяется |
|
||||||
| `codex` | Отображаемое имя `Codex`; команда и desktop-id `codex-app` сохранены |
|
| `codex` | Отображаемое имя `Codex`; команда и desktop-id `codex-app` сохранены |
|
||||||
| `github-desktop` | Официальный upstream `desktop/desktop`; Linux-сборка без стороннего форка |
|
| `github-desktop` | Официальный upstream `desktop/desktop`; Linux-сборка без стороннего форка |
|
||||||
| `nivora-stplr` | Собственный helper Nivora |
|
| `max` | Upstream package name `max`; версия хранится как `VERSION~BUILD` (совпадает с номером сборки в имени deb-файла, как у ALT eepm) для воспроизводимости; пакет всегда запускает бинарник через Firejail (`/etc/firejail/max.profile`), `/usr/bin/max` — не симлинк, а обёртка с `exec firejail` |
|
||||||
|
| `nivora-cli` | Многоязычная оболочка Nivora для Stapler |
|
||||||
|
| `telegram` | Upstream-тарбол не даёт своего package ID; desktop-id `org.telegram.desktop` сохранён; каталог и package ID переименованы с `telegram-desktop`. В отличие от `claude`/`claude-desktop`, `replaces` не включает старое имя (это разрешено только для `claude` в `validate_repo.py`) — у кого установлен `telegram-desktop`, нужно вручную `stplr install telegram` и `stplr remove telegram-desktop` |
|
||||||
|
|
||||||
## Локальные проверки
|
## Локальные проверки
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# ClaudeAlt
|
||||||
|
|
||||||
|
Самостоятельная вторая установка Claude, не входящая в пакет
|
||||||
|
`claude`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo stplr install nivora/claude-alt
|
||||||
|
```
|
||||||
|
|
||||||
|
Использует собственные runtime, профиль и desktop-идентичность. Иконки Nivora
|
||||||
|
переносятся без изменений. `claude` и `claude-alt` можно устанавливать,
|
||||||
|
обновлять и удалять независимо друг от друга.
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
# Claude Desktop
|
# Claude
|
||||||
|
|
||||||
Пакет `claude-desktop` переупаковывает DEB из APT-источника Anthropic и сохраняет upstream
|
Пакет `claude` переупаковывает DEB из APT-источника Anthropic и сохраняет upstream
|
||||||
desktop-id `com.anthropic.Claude`.
|
desktop-id `com.anthropic.Claude`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo stplr install nivora/claude-desktop
|
sudo stplr install nivora/claude
|
||||||
```
|
```
|
||||||
|
|
||||||
## Два независимых приложения
|
При установке новый пакет заменяет прежнее имя `nivora/claude-desktop`.
|
||||||
|
Исполняемая команда `/usr/bin/claude-desktop` сохраняется, чтобы не
|
||||||
|
конфликтовать с Claude Code CLI, использующим команду `claude`.
|
||||||
|
|
||||||
- `claude-desktop` запускает основное приложение Claude.
|
## Два независимых пакета
|
||||||
- `claude-alt` и `claude-code-alt` запускают отдельное приложение ClaudeAlt.
|
|
||||||
- `claude-desktop-account2` — дополнительное имя запуска ClaudeAlt.
|
|
||||||
- Команда `claude` не создаётся, чтобы не конфликтовать с Claude Code CLI.
|
|
||||||
|
|
||||||
ClaudeAlt имеет отдельные executable/resources tree, Electron `productName`, Wayland `app_id`,
|
`claude-alt` устанавливается отдельной командой и имеет собственные
|
||||||
|
executable/resources tree, Electron `productName`, Wayland `app_id`,
|
||||||
X11 `WM_CLASS`, desktop-файл, Chromium-профиль, Cowork VM socket, оконную и
|
X11 `WM_CLASS`, desktop-файл, Chromium-профиль, Cowork VM socket, оконную и
|
||||||
tray-иконки. В системном лотке используется штатный глиф Claude: оранжевый у
|
tray-иконки. В системном лотке используется штатный глиф Claude: оранжевый у
|
||||||
основного приложения и бирюзовый у ClaudeAlt. Большие app-иконки окон при этом
|
основного приложения и бирюзовый у ClaudeAlt. Большие app-иконки окон при этом
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
# Nivora CLI
|
||||||
|
|
||||||
|
Nivora CLI — компактная многоязычная оболочка для Stapler. Она упрощает
|
||||||
|
установку, удаление, обновление и поиск пакетов, управление репозиториями и
|
||||||
|
диагностику системы.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo stplr install nivora/nivora-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## Интерактивный режим
|
||||||
|
|
||||||
|
Команда `nv` без аргументов открывает компактное меню:
|
||||||
|
|
||||||
|
```text
|
||||||
|
╭─ NIVORA ─────────────────────────────╮
|
||||||
|
│ Простое управление пакетами Stapler │
|
||||||
|
╰──────────────────────────────────────╯
|
||||||
|
|
||||||
|
Пакеты
|
||||||
|
[i] Установить nvi
|
||||||
|
[e] Удалить nve
|
||||||
|
[u] Обновить nvu
|
||||||
|
[s] Найти nvs
|
||||||
|
[q] Информация nvqi
|
||||||
|
[a] Все пакеты nvqa
|
||||||
|
|
||||||
|
Система
|
||||||
|
[r] Обновить репозитории nvr
|
||||||
|
[l] Репозитории nvrl
|
||||||
|
[f] Исправить nvf
|
||||||
|
[d] Диагностика nvd
|
||||||
|
```
|
||||||
|
|
||||||
|
В конвейере или другом неинтерактивном окружении `nv` выводит обычную справку.
|
||||||
|
|
||||||
|
## Короткие команды
|
||||||
|
|
||||||
|
| Команда | Операция Stapler |
|
||||||
|
|:--|:--|
|
||||||
|
| `nvi package` | установить `nivora/package` |
|
||||||
|
| `nve package` | удалить `nivora/package` |
|
||||||
|
| `nvu` | обновить установленные пакеты |
|
||||||
|
| `nvs query` | найти пакет |
|
||||||
|
| `nvqi package` | показать информацию о пакете |
|
||||||
|
| `nvqa` | показать каталог пакетов |
|
||||||
|
| `nvr` | обновить индексы репозиториев |
|
||||||
|
| `nvrl` | показать подключённые репозитории |
|
||||||
|
| `nvf` | исправить состояние Stapler |
|
||||||
|
| `nvd` | проверить окружение |
|
||||||
|
| `nvc` | показать или изменить конфигурацию Stapler |
|
||||||
|
|
||||||
|
Основная команда принимает и полные названия операций:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nv install codex
|
||||||
|
nv search editor
|
||||||
|
nv info codex
|
||||||
|
nv repo list
|
||||||
|
```
|
||||||
|
|
||||||
|
## Репозитории
|
||||||
|
|
||||||
|
Короткое имя автоматически получает префикс `nivora`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nvi codex # stplr install nivora/codex
|
||||||
|
nvi other/package # stplr install other/package
|
||||||
|
```
|
||||||
|
|
||||||
|
Репозиторий можно изменить или отключить:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nvi --repo other package
|
||||||
|
nvi --repo none package
|
||||||
|
NIVORA_REPO=other nvi package
|
||||||
|
```
|
||||||
|
|
||||||
|
Локальные пути и файлы пакетов никогда не получают префикс.
|
||||||
|
|
||||||
|
## Язык и оформление
|
||||||
|
|
||||||
|
Русский или английский язык выбирается по системной локали. Явное
|
||||||
|
переопределение:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nv --lang en help
|
||||||
|
NIVORA_LANG=ru nvd
|
||||||
|
```
|
||||||
|
|
||||||
|
Цветной вывод включается только для терминала. Его можно отключить стандартной
|
||||||
|
переменной `NO_COLOR`, параметром `--no-color` или значением
|
||||||
|
`NIVORA_COLOR=never`.
|
||||||
|
|
||||||
|
## Безопасность
|
||||||
|
|
||||||
|
Изменяющие систему операции запускаются через `sudo`. Другую команду повышения
|
||||||
|
привилегий можно задать в `NIVORA_SUDO`. Аргументы передаются массивом без
|
||||||
|
вычисления shell-строк. Параметр `--dry-run` показывает итоговую команду без её
|
||||||
|
выполнения.
|
||||||
|
|
||||||
|
| Переменная | Назначение |
|
||||||
|
|:--|:--|
|
||||||
|
| `NIVORA_LANG` | язык интерфейса: `ru` или `en` |
|
||||||
|
| `NIVORA_REPO` | репозиторий коротких имён |
|
||||||
|
| `NIVORA_SUDO` | команда повышения привилегий |
|
||||||
|
| `NIVORA_COLOR` | режим цвета; `never` отключает цвет |
|
||||||
|
| `NIVORA_QUIET=1` | не печатать запускаемую команду |
|
||||||
|
| `NO_COLOR` | стандартное отключение цвета |
|
||||||
|
|
||||||
|
Автодополнение для Bash, Fish или Zsh генерируется командой
|
||||||
|
`nv completion <shell>`.
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
# Nivora Stapler Helper
|
|
||||||
|
|
||||||
`nivora-stplr` добавляет короткие команды для Stapler.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo stplr install nivora/nivora-stplr
|
|
||||||
```
|
|
||||||
|
|
||||||
## Команды
|
|
||||||
|
|
||||||
| Alias | Вызов Stapler |
|
|
||||||
|:--|:--|
|
|
||||||
| `sli` | `sudo stplr install` |
|
|
||||||
| `slr` | `sudo stplr remove` |
|
|
||||||
| `slu` | `sudo stplr up` |
|
|
||||||
| `slf` | `sudo stplr fix` |
|
|
||||||
| `slref` | `sudo stplr refresh` |
|
|
||||||
| `sls` | `stplr search` |
|
|
||||||
| `slii` | `stplr info` |
|
|
||||||
| `sll` | `stplr list` |
|
|
||||||
| `sl` | Диспетчер тех же команд |
|
|
||||||
|
|
||||||
Примеры:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sli --repo nivora parsec
|
|
||||||
slii nivora/codex
|
|
||||||
slu --clean
|
|
||||||
```
|
|
||||||
|
|
||||||
Короткое имя пакета не привязывается к Nivora по умолчанию. Префикс задаётся явно:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export NIVORA_STPLR_REPO=nivora
|
|
||||||
```
|
|
||||||
|
|
||||||
| Переменная | Назначение |
|
|
||||||
|:--|:--|
|
|
||||||
| `NIVORA_STPLR_REPO` | Префикс для коротких package names |
|
|
||||||
| `NIVORA_STPLR_SUDO` | Команда повышения привилегий, по умолчанию `sudo` |
|
|
||||||
| `NIVORA_STPLR_QUIET=1` | Не печатать команду перед запуском |
|
|
||||||
|
|
||||||
Helper не передаёт произвольные shell-строки через `sudo`.
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
Сведения о лицензии пакета max
|
||||||
|
|
||||||
|
Лицензия: Custom (проприетарная).
|
||||||
|
Исходный продукт: https://max.ru/
|
||||||
|
Официальный deb-репозиторий: https://download.max.ru/linux/deb/
|
||||||
|
|
||||||
|
Нюансы пакета:
|
||||||
|
- Пакет перепаковывает официальный Linux deb-артефакт MAX Messenger Client
|
||||||
|
из deb-репозитория max.ru; отдельного публичного репозитория исходников
|
||||||
|
или GitHub-релиза у продукта нет.
|
||||||
|
- Приложение собрано на Qt6 и распространяется полностью самодостаточным
|
||||||
|
бандлом (собственные библиотеки Qt в `lib64/`).
|
||||||
|
- Пакет запускает приложение только через Firejail-песочницу (профиль
|
||||||
|
`/etc/firejail/max.profile`): домашний каталог пользователя виден
|
||||||
|
приложению только через отдельные `~/.config/max`, `~/.cache/max`,
|
||||||
|
`~/.local/share/max`; capabilities сброшены, seccomp включён,
|
||||||
|
системная D-Bus недоступна. Отдельный процесс `crashpad_handler`
|
||||||
|
(сбор и отправка крэш-дампов) заблокирован явным `blacklist`, чтобы
|
||||||
|
ограничить исходящую телеметрию, не относящуюся к функциям обмена
|
||||||
|
сообщениями.
|
||||||
|
- Полная гарантия отсутствия любой сетевой телеметрии невозможна:
|
||||||
|
трафик самого мессенджера к серверам max.ru неотличим от служебного
|
||||||
|
на уровне песочницы. Firejail ограничивает доступ к системе и файлам,
|
||||||
|
а не содержимое протокола приложения.
|
||||||
|
- Для полноценной работы требуется учетная запись, привязанная к
|
||||||
|
российскому номеру телефона.
|
||||||
|
- Использование мессенджера, учетной записи и сетевых функций
|
||||||
|
регулируется условиями MAX.
|
||||||
|
- Пакет помечен как несвободный через `nonfree=1`.
|
||||||
|
|
||||||
|
Официальные условия:
|
||||||
|
https://legal.max.ru/ps
|
||||||
|
https://legal.max.ru/pp
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
name='max'
|
||||||
|
version='26.24.0~75261'
|
||||||
|
release=1
|
||||||
|
summary='MAX messenger client, sandboxed with Firejail'
|
||||||
|
summary_ru='Клиент мессенджера MAX в песочнице Firejail'
|
||||||
|
group='Networking/Instant messaging'
|
||||||
|
desc='MAX is the Russian state-affiliated instant messaging client. This package always launches it inside a Firejail sandbox that hides the rest of the home directory and blocks the standalone crash-report uploader, since the app has no independent security track record and no reason to see the whole system.'
|
||||||
|
desc_ru='MAX — российский государственно-аффилированный клиент мгновенных сообщений. Пакет всегда запускает его в песочнице Firejail, которая скрывает остальной домашний каталог и блокирует отдельный процесс отправки крэш-дампов — у приложения нет независимой истории аудита безопасности и нет причин видеть всю систему.'
|
||||||
|
homepage='https://max.ru/'
|
||||||
|
maintainer='max.ru <https://max.ru/>'
|
||||||
|
|
||||||
|
architectures=('amd64')
|
||||||
|
|
||||||
|
license=('Custom')
|
||||||
|
nonfree=1
|
||||||
|
nonfree_msg='MAX является проприетарным приложением. Использование мессенджера, учетной записи и сетевых функций регулируется условиями MAX.'
|
||||||
|
nonfree_url='https://legal.max.ru/ps'
|
||||||
|
|
||||||
|
provides=()
|
||||||
|
replaces=('max')
|
||||||
|
conflicts=()
|
||||||
|
|
||||||
|
auto_reqprov_method="dirty"
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
deps=('firejail')
|
||||||
|
deps_debian=('firejail' 'libxcb-xinerama0' 'libxcb-composite0' 'libxcb-ewmh2' 'libva-x11-2' 'libva-drm2' 'libvdpau1' 'libnotify4' 'libxcb-dri2-0' 'libopengl0' 'libxcb-cursor0' 'libxkbcommon-x11-0' 'libxcb-icccm4' 'libxcb-keysyms1' 'libxss1' 'libglib2.0-0' 'gsettings-desktop-schemas' 'ca-certificates')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('firejail' 'libxcb' 'libva' 'libvdpau' 'libnotify' 'libglvnd-opengl' 'xcb-util-cursor' 'libxkbcommon-x11' 'xcb-util-wm' 'xcb-util-keysyms' 'libXScrnSaver' 'glib2' 'gsettings-desktop-schemas' 'ca-certificates')
|
||||||
|
deps_arch=('firejail' 'libxcb' 'libva' 'libvdpau' 'libnotify' 'libglvnd' 'xcb-util-cursor' 'libxkbcommon-x11' 'xcb-util-wm' 'xcb-util-keysyms' 'libxss' 'glib2' 'gsettings-desktop-schemas' 'ca-certificates')
|
||||||
|
deps_opensuse=('firejail' 'libxcb1' 'libva2' 'libvdpau1' 'libnotify4' 'libxcb-cursor0' 'libxkbcommon-x11-0' 'xcb-util-wm0' 'xcb-util-keysyms0' 'libXss1' 'libglib-2_0-0' 'gsettings-desktop-schemas' 'ca-certificates')
|
||||||
|
deps_altlinux=('firejail' 'libxcb' 'libxcbutil-cursor' 'libxcbutil-icccm' 'libxcbutil-keysyms' 'libXScrnSaver' 'libva' 'libvdpau' 'libnotify' 'libOpenGL' 'libxkbcommon-x11' 'glib2' 'gsettings-desktop-schemas' 'ca-certificates')
|
||||||
|
|
||||||
|
opt_deps=()
|
||||||
|
opt_deps_debian=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
|
||||||
|
opt_deps_ubuntu=("${opt_deps_debian[@]}")
|
||||||
|
opt_deps_fedora=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
|
||||||
|
opt_deps_arch=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
|
||||||
|
opt_deps_opensuse=('desktop-file-utils' 'hicolor-icon-theme' 'pipewire')
|
||||||
|
opt_deps_altlinux=('desktop-file-utils' 'icon-theme-hicolor' 'pipewire')
|
||||||
|
|
||||||
|
build_deps=('binutils')
|
||||||
|
|
||||||
|
sources=(
|
||||||
|
"https://download.max.ru/linux/deb/pool/main/m/max/MAX-26.24.0.75261.deb?~archive=false&~name=max.deb"
|
||||||
|
'local:///max.desktop'
|
||||||
|
'local:///max.profile'
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums=(
|
||||||
|
'sha256:7151aa2559e5fe22dd4dd6cf037b5d5cd38d302f84e49d4c4be94e1c4fe1f7d5'
|
||||||
|
'sha256:80ec5c0f4777ab00c433c25ffa70ef23d1752785e6584288d189518b8b43d613'
|
||||||
|
'sha256:cf8c986f7f1a9841be33b43cfd8e34e6c75dac6ffea07aad07869177fc7768c7'
|
||||||
|
'sha256:ddfcad273084c8b5690f6276fb29d8990ff4a7114db8a89b3f46255f8675e6b6'
|
||||||
|
)
|
||||||
|
|
||||||
|
scripts=(
|
||||||
|
['postinstall']='postinstall.sh'
|
||||||
|
['postremove']='postremove.sh'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}"
|
||||||
|
|
||||||
|
mkdir -p "${srcdir}/extracted"
|
||||||
|
ar x max.deb
|
||||||
|
tar -xf data.tar.* -C "${srcdir}/extracted"
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/share"
|
||||||
|
cp -a "${srcdir}/extracted/usr/share/max" "${pkgdir}/usr/share/max"
|
||||||
|
install -Dm644 "${srcdir}/extracted/usr/share/pixmaps/max.png" \
|
||||||
|
"${pkgdir}/usr/share/pixmaps/max.png"
|
||||||
|
|
||||||
|
for icon in "${srcdir}"/extracted/usr/share/icons/hicolor/*/apps/max.png; do
|
||||||
|
size="$(basename "$(dirname "$(dirname "$icon")")")"
|
||||||
|
install -Dm644 "$icon" \
|
||||||
|
"${pkgdir}/usr/share/icons/hicolor/${size}/apps/max.png"
|
||||||
|
done
|
||||||
|
|
||||||
|
install -Dm644 max.profile "${pkgdir}/etc/firejail/max.profile"
|
||||||
|
|
||||||
|
# The desktop file and every other launch path go through this wrapper —
|
||||||
|
# MAX never runs unsandboxed regardless of how it's started.
|
||||||
|
install -Dm755 /dev/stdin "${pkgdir}/usr/bin/max" <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
exec firejail --profile=max -- /usr/share/max/bin/max "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
install -Dm644 max.desktop "${pkgdir}/usr/share/applications/max.desktop"
|
||||||
|
|
||||||
|
install-license "${srcdir}/LICENSE" "max/LICENSE.nivora"
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find-binary
|
||||||
|
files-find-desktop
|
||||||
|
files-find-license
|
||||||
|
files-find \
|
||||||
|
"/etc/firejail/max.profile" \
|
||||||
|
"/usr/share/max/**/*" \
|
||||||
|
"/usr/share/pixmaps/max.png" \
|
||||||
|
"/usr/share/icons/hicolor/*/apps/max.png"
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Terminal=false
|
||||||
|
Name=MAX
|
||||||
|
Exec=/usr/bin/max %U
|
||||||
|
Icon=max
|
||||||
|
MimeType=x-scheme-handler/max;
|
||||||
|
Comment=MAX Messenger Client Application
|
||||||
|
Comment[ru]=Клиентское приложение мессенджера MAX
|
||||||
|
StartupWMClass=max
|
||||||
|
Categories=Chat;Network;InstantMessaging;Qt;
|
||||||
|
Keywords=max;chat;im;messaging;messenger;sms;
|
||||||
|
DBusActivatable=false
|
||||||
|
SingleMainWindow=true
|
||||||
|
X-GNOME-UsesNotifications=true
|
||||||
|
X-GNOME-SingleWindow=true
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# Firejail profile for MAX Messenger (Nivora package)
|
||||||
|
# MAX is a proprietary Russian messenger; this profile keeps it away from
|
||||||
|
# the rest of the user's files and system, and blocks its standalone
|
||||||
|
# crash-report uploader.
|
||||||
|
|
||||||
|
include max.local
|
||||||
|
include globals.local
|
||||||
|
|
||||||
|
noblacklist ${HOME}/.config/max
|
||||||
|
noblacklist ${HOME}/.cache/max
|
||||||
|
noblacklist ${HOME}/.local/share/max
|
||||||
|
|
||||||
|
include disable-common.inc
|
||||||
|
include disable-devel.inc
|
||||||
|
include disable-exec.inc
|
||||||
|
include disable-interpreters.inc
|
||||||
|
include disable-programs.inc
|
||||||
|
include landlock-common.inc
|
||||||
|
|
||||||
|
mkdir ${HOME}/.config/max
|
||||||
|
mkdir ${HOME}/.cache/max
|
||||||
|
mkdir ${HOME}/.local/share/max
|
||||||
|
whitelist ${HOME}/.config/max
|
||||||
|
whitelist ${HOME}/.cache/max
|
||||||
|
whitelist ${HOME}/.local/share/max
|
||||||
|
include whitelist-common.inc
|
||||||
|
include whitelist-run-common.inc
|
||||||
|
include whitelist-usr-share-common.inc
|
||||||
|
include whitelist-var-common.inc
|
||||||
|
|
||||||
|
caps.drop all
|
||||||
|
netfilter
|
||||||
|
nodvd
|
||||||
|
nogroups
|
||||||
|
nonewprivs
|
||||||
|
noroot
|
||||||
|
notv
|
||||||
|
nou2f
|
||||||
|
protocol unix,inet,inet6
|
||||||
|
seccomp
|
||||||
|
restrict-namespaces
|
||||||
|
|
||||||
|
disable-mnt
|
||||||
|
private-dev
|
||||||
|
private-tmp
|
||||||
|
|
||||||
|
# Chromium/Qt-style standalone crash uploader: no messaging function, only
|
||||||
|
# phones home with crash dumps. Block it outright rather than trust a
|
||||||
|
# network-level filter.
|
||||||
|
blacklist /usr/share/max/bin/crashpad_handler
|
||||||
|
blacklist /usr/share/max/bin/max-service/bin/crashpad_handler
|
||||||
|
|
||||||
|
dbus-system none
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
optional_refresh() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
if ! "$@"; then
|
||||||
|
echo "Предупреждение: не удалось обновить ${label}." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш иконок" gtk-update-icon-cache -f -q /usr/share/icons/hicolor
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v kbuildsycoca6 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
|
||||||
|
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v firejail >/dev/null 2>&1; then
|
||||||
|
echo "Предупреждение: firejail не найден в PATH — MAX запускается только через firejail, пакет firejail должен быть установлен." >&2
|
||||||
|
fi
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
optional_refresh() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
if ! "$@"; then
|
||||||
|
echo "Предупреждение: не удалось обновить ${label}." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш иконок" gtk-update-icon-cache -f -q /usr/share/icons/hicolor
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v kbuildsycoca6 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
|
||||||
|
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
|
||||||
|
fi
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include = "../stapler-repo.toml"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name='netbird'
|
name='netbird'
|
||||||
version=0.75.0
|
version=0.76.0
|
||||||
release=1
|
release=1
|
||||||
summary='WireGuard-based mesh VPN client'
|
summary='WireGuard-based mesh VPN client'
|
||||||
summary_ru='Mesh VPN-клиент на базе WireGuard'
|
summary_ru='Mesh VPN-клиент на базе WireGuard'
|
||||||
@@ -48,7 +48,7 @@ sources_arm64=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
checksums=(
|
checksums=(
|
||||||
'sha256:b65f65d7f32831639ebdd44c241e7a2310287723b64dbc03c93292853042ee6f'
|
'sha256:0fdc5ee0336c71d58223c5ea92019b062d8bc2d5a73dbc4692c6d2313307a0f4'
|
||||||
'sha256:71b133636e91eb67f221f64592f64fa04a3b2337f4d616be36492efae0cff643'
|
'sha256:71b133636e91eb67f221f64592f64fa04a3b2337f4d616be36492efae0cff643'
|
||||||
'sha256:abd8064281462a4ce12c2fdf2e9436d9ae6932ff3b366668a175f2a556169012'
|
'sha256:abd8064281462a4ce12c2fdf2e9436d9ae6932ff3b366668a175f2a556169012'
|
||||||
'sha256:bb5c44ab330db0d63a82b582f2c508681a6922ea65f3bf2becaeed87693215b1'
|
'sha256:bb5c44ab330db0d63a82b582f2c508681a6922ea65f3bf2becaeed87693215b1'
|
||||||
@@ -56,7 +56,7 @@ checksums=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
checksums_arm64=(
|
checksums_arm64=(
|
||||||
'sha256:9e57e854da0bbaf392cc6f99e37db75809e21c3effde0fca9f3bc9dc90245c02'
|
'sha256:b8f0f8cb47df28f9ec0061c38eba5c96af43b25f49f4f28c544919f34f34cbe8'
|
||||||
'sha256:71b133636e91eb67f221f64592f64fa04a3b2337f4d616be36492efae0cff643'
|
'sha256:71b133636e91eb67f221f64592f64fa04a3b2337f4d616be36492efae0cff643'
|
||||||
'sha256:abd8064281462a4ce12c2fdf2e9436d9ae6932ff3b366668a175f2a556169012'
|
'sha256:abd8064281462a4ce12c2fdf2e9436d9ae6932ff3b366668a175f2a556169012'
|
||||||
'sha256:bb5c44ab330db0d63a82b582f2c508681a6922ea65f3bf2becaeed87693215b1'
|
'sha256:bb5c44ab330db0d63a82b582f2c508681a6922ea65f3bf2becaeed87693215b1'
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
package_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
repo_root="$(cd "${package_dir}/.." && pwd)"
|
||||||
|
exec "${repo_root}/tools/package_updates.sh" check "$(basename "$package_dir")"
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
Сведения о лицензии пакета Nivora CLI
|
||||||
|
|
||||||
|
Лицензия: MIT.
|
||||||
|
Исходный проект: https://github.com/Cheviiot/Nivora
|
||||||
|
|
||||||
|
Нюансы пакета:
|
||||||
|
- Пакет устанавливает оболочку Stapler с командами `nv`, `nvi`, `nve`, `nvu`, `nvs`, `nvqi`, `nvqa`, `nvr`, `nvrl`, `nvf`, `nvd` и `nvc`.
|
||||||
|
- Nivora CLI не заменяет Stapler: все операции выполняются через системную команду `stplr`.
|
||||||
|
- Через команду повышения привилегий запускаются только `install`, `remove`, `up`, `fix` и `refresh`.
|
||||||
|
- Команды чтения `search`, `info` и `list` выполняются без повышения привилегий.
|
||||||
|
- Префикс репозитория задается через `--repo <name>` или `NIVORA_REPO`; по умолчанию используется репозиторий `nivora`.
|
||||||
|
- Пути вида `repo/package` не изменяются.
|
||||||
|
- Nivora CLI не исполняет произвольные shell-строки через `sudo`.
|
||||||
|
|
||||||
|
Полный официальный текст MIT:
|
||||||
|
https://opensource.org/licenses/MIT
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
name='nivora-cli'
|
||||||
|
version='1.0.0'
|
||||||
|
release=1
|
||||||
|
summary='Friendly multilingual command shell for Stapler'
|
||||||
|
summary_ru='Удобная многоязычная оболочка для Stapler'
|
||||||
|
desc='Nivora CLI is a compact bilingual command shell for everyday Stapler package management, repository administration, diagnostics, interactive navigation and shell completion.'
|
||||||
|
desc_ru='Nivora CLI — компактная двуязычная оболочка для управления пакетами и репозиториями Stapler, диагностики, интерактивной навигации и автодополнения.'
|
||||||
|
group='System/Configuration/Packaging'
|
||||||
|
homepage='https://github.com/Cheviiot/Nivora'
|
||||||
|
maintainer='Cheviiot <https://github.com/Cheviiot>'
|
||||||
|
|
||||||
|
architectures=('all')
|
||||||
|
license=('MIT')
|
||||||
|
|
||||||
|
provides=()
|
||||||
|
replaces=('nivora-cli')
|
||||||
|
conflicts=()
|
||||||
|
|
||||||
|
auto_reqprov_method='dirty'
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
deps=()
|
||||||
|
deps_debian=('bash' 'sudo')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('bash' 'sudo')
|
||||||
|
deps_arch=('bash' 'sudo')
|
||||||
|
deps_altlinux=('bash' 'sudo')
|
||||||
|
deps_opensuse=('bash' 'sudo')
|
||||||
|
|
||||||
|
sources=(
|
||||||
|
'local:///nivora'
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums=(
|
||||||
|
'sha256:438a5b3b73cd8f69108174b25e647b0f8013b3c16f4fcd5ca9e9769fd19f98b7'
|
||||||
|
'sha256:16f1438f500706ac85b363c2549b392daef3a920b24139fca6b30f5648a7801a'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
install -Dm755 "${srcdir}/nivora" "${pkgdir}/usr/bin/nv"
|
||||||
|
|
||||||
|
shortcut=''
|
||||||
|
for shortcut in nvi nve nvu nvs nvqi nvqa nvr nvrl nvf nvd nvc; do
|
||||||
|
ln -sfn nv "${pkgdir}/usr/bin/${shortcut}"
|
||||||
|
done
|
||||||
|
|
||||||
|
install-license "${srcdir}/LICENSE" 'nivora-cli/LICENSE.nivora'
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find-binary
|
||||||
|
files-find-license
|
||||||
|
}
|
||||||
@@ -0,0 +1,546 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
readonly NIVORA_VERSION='1.0.0'
|
||||||
|
readonly DEFAULT_REPOSITORY='nivora'
|
||||||
|
|
||||||
|
language="${NIVORA_LANG:-}"
|
||||||
|
repository="${NIVORA_REPO:-${DEFAULT_REPOSITORY}}"
|
||||||
|
dry_run=0
|
||||||
|
color_mode="${NIVORA_COLOR:-auto}"
|
||||||
|
|
||||||
|
detect_language() {
|
||||||
|
[[ -n "$language" ]] && return
|
||||||
|
case "${LC_ALL:-${LC_MESSAGES:-${LANG:-en}}}" in
|
||||||
|
ru* | RU*) language='ru' ;;
|
||||||
|
*) language='en' ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
message() {
|
||||||
|
local key="$1"
|
||||||
|
case "${language}:${key}" in
|
||||||
|
ru:title) printf 'Простое управление пакетами Stapler' ;;
|
||||||
|
ru:usage) printf 'Использование' ;;
|
||||||
|
ru:packages) printf 'Пакеты' ;;
|
||||||
|
ru:system) printf 'Система' ;;
|
||||||
|
ru:install) printf 'Установить' ;;
|
||||||
|
ru:remove) printf 'Удалить' ;;
|
||||||
|
ru:upgrade) printf 'Обновить' ;;
|
||||||
|
ru:search) printf 'Найти' ;;
|
||||||
|
ru:info) printf 'Информация' ;;
|
||||||
|
ru:all_packages) printf 'Все пакеты' ;;
|
||||||
|
ru:refresh) printf 'Обновить репозитории' ;;
|
||||||
|
ru:repositories) printf 'Репозитории' ;;
|
||||||
|
ru:fix) printf 'Исправить' ;;
|
||||||
|
ru:doctor) printf 'Диагностика' ;;
|
||||||
|
ru:config) printf 'Конфигурация' ;;
|
||||||
|
ru:help) printf 'Справка' ;;
|
||||||
|
ru:exit) printf 'Выход' ;;
|
||||||
|
ru:choose) printf 'Выберите действие' ;;
|
||||||
|
ru:package_prompt) printf 'Имя пакета' ;;
|
||||||
|
ru:query_prompt) printf 'Поисковый запрос' ;;
|
||||||
|
ru:unknown_command) printf 'неизвестная команда' ;;
|
||||||
|
ru:unknown_choice) printf 'нет такого пункта' ;;
|
||||||
|
ru:missing_argument) printf 'необходим аргумент' ;;
|
||||||
|
ru:invalid_language) printf 'поддерживаются языки ru и en' ;;
|
||||||
|
ru:invalid_repository) printf 'некорректное имя репозитория' ;;
|
||||||
|
ru:stapler_missing) printf 'команда stplr не найдена' ;;
|
||||||
|
ru:privilege_missing) printf 'команда повышения привилегий не найдена' ;;
|
||||||
|
ru:running) printf 'Выполняется' ;;
|
||||||
|
ru:preview) printf 'Предпросмотр' ;;
|
||||||
|
ru:diagnostics) printf 'Диагностика окружения' ;;
|
||||||
|
ru:ready) printf 'Система готова к работе' ;;
|
||||||
|
ru:problems) printf 'Обнаружены проблемы' ;;
|
||||||
|
ru:available) printf 'доступен' ;;
|
||||||
|
ru:missing) printf 'не найден' ;;
|
||||||
|
ru:language) printf 'Язык' ;;
|
||||||
|
ru:repository) printf 'Репозиторий' ;;
|
||||||
|
ru:privileges) printf 'Привилегии' ;;
|
||||||
|
ru:commands) printf 'Короткие команды' ;;
|
||||||
|
ru:options) printf 'Параметры' ;;
|
||||||
|
ru:examples) printf 'Примеры' ;;
|
||||||
|
en:title) printf 'Simple Stapler package management' ;;
|
||||||
|
en:usage) printf 'Usage' ;;
|
||||||
|
en:packages) printf 'Packages' ;;
|
||||||
|
en:system) printf 'System' ;;
|
||||||
|
en:install) printf 'Install' ;;
|
||||||
|
en:remove) printf 'Remove' ;;
|
||||||
|
en:upgrade) printf 'Upgrade' ;;
|
||||||
|
en:search) printf 'Search' ;;
|
||||||
|
en:info) printf 'Information' ;;
|
||||||
|
en:all_packages) printf 'All packages' ;;
|
||||||
|
en:refresh) printf 'Refresh repositories' ;;
|
||||||
|
en:repositories) printf 'Repositories' ;;
|
||||||
|
en:fix) printf 'Repair' ;;
|
||||||
|
en:doctor) printf 'Diagnostics' ;;
|
||||||
|
en:config) printf 'Configuration' ;;
|
||||||
|
en:help) printf 'Help' ;;
|
||||||
|
en:exit) printf 'Exit' ;;
|
||||||
|
en:choose) printf 'Choose an action' ;;
|
||||||
|
en:package_prompt) printf 'Package name' ;;
|
||||||
|
en:query_prompt) printf 'Search query' ;;
|
||||||
|
en:unknown_command) printf 'unknown command' ;;
|
||||||
|
en:unknown_choice) printf 'unknown choice' ;;
|
||||||
|
en:missing_argument) printf 'an argument is required' ;;
|
||||||
|
en:invalid_language) printf 'supported languages are ru and en' ;;
|
||||||
|
en:invalid_repository) printf 'invalid repository name' ;;
|
||||||
|
en:stapler_missing) printf 'stplr command was not found' ;;
|
||||||
|
en:privilege_missing) printf 'privilege command was not found' ;;
|
||||||
|
en:running) printf 'Running' ;;
|
||||||
|
en:preview) printf 'Preview' ;;
|
||||||
|
en:diagnostics) printf 'Environment diagnostics' ;;
|
||||||
|
en:ready) printf 'The system is ready' ;;
|
||||||
|
en:problems) printf 'Problems found' ;;
|
||||||
|
en:available) printf 'available' ;;
|
||||||
|
en:missing) printf 'missing' ;;
|
||||||
|
en:language) printf 'Language' ;;
|
||||||
|
en:repository) printf 'Repository' ;;
|
||||||
|
en:privileges) printf 'Privileges' ;;
|
||||||
|
en:commands) printf 'Short commands' ;;
|
||||||
|
en:options) printf 'Options' ;;
|
||||||
|
en:examples) printf 'Examples' ;;
|
||||||
|
*) printf '%s' "$key" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_style() {
|
||||||
|
if [[ "$color_mode" == 'never' || -n "${NO_COLOR:-}" || ! -t 1 ]]; then
|
||||||
|
bold=''; dim=''; cyan=''; blue=''; green=''; red=''; reset=''
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
bold=$'\033[1m'
|
||||||
|
dim=$'\033[2m'
|
||||||
|
cyan=$'\033[38;5;44m'
|
||||||
|
blue=$'\033[38;5;75m'
|
||||||
|
green=$'\033[38;5;78m'
|
||||||
|
red=$'\033[38;5;203m'
|
||||||
|
reset=$'\033[0m'
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf '%s%sNivora:%s %s\n' "$bold" "$red" "$reset" "$*" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_settings() {
|
||||||
|
case "$language" in
|
||||||
|
ru | en) ;;
|
||||||
|
*)
|
||||||
|
local invalid_language="$language"
|
||||||
|
language='en'
|
||||||
|
fail "$(message invalid_language): ${invalid_language}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [[ "$repository" != 'none' &&
|
||||||
|
! "$repository" =~ ^[[:alnum:]_.-]+$ ]]; then
|
||||||
|
fail "$(message invalid_repository): ${repository}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_options() {
|
||||||
|
arguments=()
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--lang)
|
||||||
|
[[ "$#" -ge 2 ]] || fail "$(message missing_argument): --lang"
|
||||||
|
language="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--lang=*)
|
||||||
|
language="${1#--lang=}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--repo)
|
||||||
|
[[ "$#" -ge 2 ]] || fail "$(message missing_argument): --repo"
|
||||||
|
repository="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--repo=*)
|
||||||
|
repository="${1#--repo=}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--dry-run)
|
||||||
|
dry_run=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-color)
|
||||||
|
color_mode='never'
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
arguments+=("$@")
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
arguments+=("$1")
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
setup_style
|
||||||
|
validate_settings
|
||||||
|
}
|
||||||
|
|
||||||
|
print_header() {
|
||||||
|
printf '%s%s╭─ NIVORA ─────────────────────────────╮%s\n' "$bold" "$cyan" "$reset"
|
||||||
|
if [[ "$language" == 'ru' ]]; then
|
||||||
|
printf '%s%s│%s Простое управление пакетами Stapler %s%s│%s\n' \
|
||||||
|
"$cyan" "$bold" "$reset" "$bold" "$cyan" "$reset"
|
||||||
|
else
|
||||||
|
printf '%s%s│%s Simple Stapler package management %s%s│%s\n' \
|
||||||
|
"$cyan" "$bold" "$reset" "$bold" "$cyan" "$reset"
|
||||||
|
fi
|
||||||
|
printf '%s%s╰──────────────────────────────────────╯%s\n' "$bold" "$cyan" "$reset"
|
||||||
|
}
|
||||||
|
|
||||||
|
menu_row() {
|
||||||
|
local key="$1"
|
||||||
|
local label="$2"
|
||||||
|
local shortcut="$3"
|
||||||
|
local padding=$((23 - ${#label}))
|
||||||
|
[[ "$padding" -lt 1 ]] && padding=1
|
||||||
|
printf ' %s[%s]%s %s' "$cyan" "$key" "$reset" "$label"
|
||||||
|
printf '%*s' "$padding" ''
|
||||||
|
printf '%s%s%s\n' "$dim" "$shortcut" "$reset"
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive_menu() {
|
||||||
|
if [[ ! -t 0 || ! -t 1 ]]; then
|
||||||
|
show_help
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_header
|
||||||
|
printf '\n %s%s%s\n' "$bold" "$(message packages)" "$reset"
|
||||||
|
menu_row i "$(message install)" nvi
|
||||||
|
menu_row e "$(message remove)" nve
|
||||||
|
menu_row u "$(message upgrade)" nvu
|
||||||
|
menu_row s "$(message search)" nvs
|
||||||
|
menu_row q "$(message info)" nvqi
|
||||||
|
menu_row a "$(message all_packages)" nvqa
|
||||||
|
printf '\n %s%s%s\n' "$bold" "$(message system)" "$reset"
|
||||||
|
menu_row r "$(message refresh)" nvr
|
||||||
|
menu_row l "$(message repositories)" nvrl
|
||||||
|
menu_row f "$(message fix)" nvf
|
||||||
|
menu_row d "$(message doctor)" nvd
|
||||||
|
local help_label
|
||||||
|
help_label="$(message help)"
|
||||||
|
printf '\n %s[h]%s %s' "$cyan" "$reset" "$help_label"
|
||||||
|
printf '%*s' "$((23 - ${#help_label}))" ''
|
||||||
|
printf '%s[x]%s %s\n\n' "$cyan" "$reset" "$(message exit)"
|
||||||
|
printf '%s › ' "$(message choose)"
|
||||||
|
read -r choice
|
||||||
|
case "$choice" in
|
||||||
|
i) prompt_and_dispatch install package ;;
|
||||||
|
e) prompt_and_dispatch remove package ;;
|
||||||
|
u) dispatch upgrade ;;
|
||||||
|
s) prompt_and_dispatch search query ;;
|
||||||
|
q) prompt_and_dispatch info package ;;
|
||||||
|
a) dispatch list ;;
|
||||||
|
r) dispatch refresh ;;
|
||||||
|
l) dispatch repo-list ;;
|
||||||
|
f) dispatch fix ;;
|
||||||
|
d) doctor ;;
|
||||||
|
h) show_help ;;
|
||||||
|
x | q!) return ;;
|
||||||
|
*) fail "$(message unknown_choice): ${choice}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_and_dispatch() {
|
||||||
|
local command_name="$1"
|
||||||
|
local prompt_type="$2"
|
||||||
|
local value
|
||||||
|
if [[ "$prompt_type" == 'package' ]]; then
|
||||||
|
printf '%s › ' "$(message package_prompt)"
|
||||||
|
else
|
||||||
|
printf '%s › ' "$(message query_prompt)"
|
||||||
|
fi
|
||||||
|
read -r value
|
||||||
|
[[ -n "$value" ]] || fail "$(message missing_argument): ${command_name}"
|
||||||
|
dispatch "$command_name" "$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
print_header
|
||||||
|
if [[ "$language" == 'ru' ]]; then
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
${bold}$(message usage)${reset}
|
||||||
|
nv интерактивное меню
|
||||||
|
nv <команда> [аргументы] выполнить команду
|
||||||
|
|
||||||
|
${bold}$(message commands)${reset}
|
||||||
|
${cyan}nvi${reset} <пакет...> установить ${cyan}nvr${reset} обновить репозитории
|
||||||
|
${cyan}nve${reset} <пакет...> удалить ${cyan}nvrl${reset} показать репозитории
|
||||||
|
${cyan}nvu${reset} обновить пакеты ${cyan}nvf${reset} исправить Stapler
|
||||||
|
${cyan}nvs${reset} <запрос> найти ${cyan}nvd${reset} запустить диагностику
|
||||||
|
${cyan}nvqi${reset} <пакет> информация ${cyan}nvc${reset} конфигурация Stapler
|
||||||
|
${cyan}nvqa${reset} каталог пакетов
|
||||||
|
|
||||||
|
${bold}$(message options)${reset}
|
||||||
|
--repo <имя|none> репозиторий коротких имён (по умолчанию: nivora)
|
||||||
|
--lang <ru|en> язык интерфейса
|
||||||
|
--dry-run показать команду без выполнения
|
||||||
|
--no-color отключить цвета
|
||||||
|
|
||||||
|
${bold}$(message examples)${reset}
|
||||||
|
nvi codex
|
||||||
|
nvs editor
|
||||||
|
nvqi codex
|
||||||
|
nv --repo none install other/package
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
${bold}$(message usage)${reset}
|
||||||
|
nv interactive menu
|
||||||
|
nv <command> [arguments] run a command
|
||||||
|
|
||||||
|
${bold}$(message commands)${reset}
|
||||||
|
${cyan}nvi${reset} <package...> install ${cyan}nvr${reset} refresh repositories
|
||||||
|
${cyan}nve${reset} <package...> remove ${cyan}nvrl${reset} list repositories
|
||||||
|
${cyan}nvu${reset} upgrade packages ${cyan}nvf${reset} repair Stapler
|
||||||
|
${cyan}nvs${reset} <query> search ${cyan}nvd${reset} run diagnostics
|
||||||
|
${cyan}nvqi${reset} <package> information ${cyan}nvc${reset} configure Stapler
|
||||||
|
${cyan}nvqa${reset} package catalog
|
||||||
|
|
||||||
|
${bold}$(message options)${reset}
|
||||||
|
--repo <name|none> repository for short names (default: nivora)
|
||||||
|
--lang <ru|en> interface language
|
||||||
|
--dry-run print the command without running it
|
||||||
|
--no-color disable colors
|
||||||
|
|
||||||
|
${bold}$(message examples)${reset}
|
||||||
|
nvi codex
|
||||||
|
nvs editor
|
||||||
|
nvqi codex
|
||||||
|
nv --repo none install other/package
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
need_stapler() {
|
||||||
|
command -v stplr >/dev/null 2>&1 || fail "$(message stapler_missing)"
|
||||||
|
}
|
||||||
|
|
||||||
|
privilege_command() {
|
||||||
|
[[ "$EUID" -eq 0 ]] && return
|
||||||
|
local command_name="${NIVORA_SUDO:-sudo}"
|
||||||
|
command -v "$command_name" >/dev/null 2>&1 ||
|
||||||
|
fail "$(message privilege_missing): ${command_name}"
|
||||||
|
printf '%s\n' "$command_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_package_name() {
|
||||||
|
local value="$1"
|
||||||
|
[[ -n "$value" &&
|
||||||
|
"$value" != -* &&
|
||||||
|
"$value" != */* &&
|
||||||
|
"$value" != ./* &&
|
||||||
|
"$value" != ../* &&
|
||||||
|
"$value" != /* &&
|
||||||
|
"$value" != *.rpm &&
|
||||||
|
"$value" != *.deb &&
|
||||||
|
"$value" != *.pkg.tar.* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_packages() {
|
||||||
|
local argument
|
||||||
|
for argument in "$@"; do
|
||||||
|
if [[ "$repository" != 'none' ]] && is_package_name "$argument"; then
|
||||||
|
printf '%s/%s\n' "$repository" "$argument"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$argument"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
print_command() {
|
||||||
|
local label
|
||||||
|
if [[ "$dry_run" -eq 1 ]]; then
|
||||||
|
label="$(message preview)"
|
||||||
|
else
|
||||||
|
label="$(message running)"
|
||||||
|
fi
|
||||||
|
printf '%s%s%s%s %s›%s' "$bold" "$blue" "$label" "$reset" "$cyan" "$reset" >&2
|
||||||
|
printf ' %q' "$@" >&2
|
||||||
|
printf '\n' >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
run_stapler() {
|
||||||
|
local access="$1"
|
||||||
|
shift
|
||||||
|
need_stapler
|
||||||
|
|
||||||
|
local -a command=()
|
||||||
|
local privilege
|
||||||
|
if [[ "$access" == 'privileged' ]]; then
|
||||||
|
privilege="$(privilege_command)"
|
||||||
|
[[ -n "$privilege" ]] && command+=("$privilege")
|
||||||
|
fi
|
||||||
|
command+=(stplr "$@")
|
||||||
|
|
||||||
|
[[ "${NIVORA_QUIET:-0}" == '1' ]] || print_command "${command[@]}"
|
||||||
|
[[ "$dry_run" -eq 1 ]] && return
|
||||||
|
exec "${command[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_arguments() {
|
||||||
|
local command_name="$1"
|
||||||
|
local count="$2"
|
||||||
|
[[ "$count" -gt 0 ]] || fail "$(message missing_argument): ${command_name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
doctor() {
|
||||||
|
local failures=0
|
||||||
|
local privilege="${NIVORA_SUDO:-sudo}"
|
||||||
|
printf '%s%s%s\n\n' "$bold" "$(message diagnostics)" "$reset"
|
||||||
|
|
||||||
|
if command -v stplr >/dev/null 2>&1; then
|
||||||
|
printf ' %s●%s %-14s %s\n' "$green" "$reset" 'Stapler' "$(message available)"
|
||||||
|
else
|
||||||
|
printf ' %s●%s %-14s %s\n' "$red" "$reset" 'Stapler' "$(message missing)"
|
||||||
|
failures=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$EUID" -eq 0 ]] || command -v "$privilege" >/dev/null 2>&1; then
|
||||||
|
printf ' %s●%s %-14s %s\n' \
|
||||||
|
"$green" "$reset" "$(message privileges)" \
|
||||||
|
"$([[ "$EUID" -eq 0 ]] && printf 'root' || printf '%s' "$privilege")"
|
||||||
|
else
|
||||||
|
printf ' %s●%s %-14s %s\n' \
|
||||||
|
"$red" "$reset" "$(message privileges)" "$(message missing)"
|
||||||
|
failures=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf ' %s●%s %-14s %s\n' "$green" "$reset" "$(message language)" "$language"
|
||||||
|
printf ' %s●%s %-14s %s\n\n' \
|
||||||
|
"$green" "$reset" "$(message repository)" "$repository"
|
||||||
|
|
||||||
|
if [[ "$failures" -eq 0 ]]; then
|
||||||
|
printf '%s✓ %s%s\n' "$green" "$(message ready)" "$reset"
|
||||||
|
else
|
||||||
|
printf '%s✗ %s%s\n' "$red" "$(message problems)" "$reset"
|
||||||
|
fi
|
||||||
|
return "$failures"
|
||||||
|
}
|
||||||
|
|
||||||
|
completion() {
|
||||||
|
local shell="${1:-}"
|
||||||
|
case "$shell" in
|
||||||
|
bash)
|
||||||
|
cat <<'EOF'
|
||||||
|
_nivora() {
|
||||||
|
local commands='install remove upgrade search info list refresh repo-list fix doctor config completion version help'
|
||||||
|
if (( COMP_CWORD == 1 )); then
|
||||||
|
COMPREPLY=($(compgen -W "$commands" -- "${COMP_WORDS[COMP_CWORD]}"))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
complete -F _nivora nv
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
fish)
|
||||||
|
cat <<'EOF'
|
||||||
|
complete -c nv -f -n '__fish_use_subcommand' -a 'install remove upgrade search info list refresh repo-list fix doctor config completion version help'
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
zsh)
|
||||||
|
cat <<'EOF'
|
||||||
|
#compdef nv
|
||||||
|
_arguments '1:command:(install remove upgrade search info list refresh repo-list fix doctor config completion version help)' '*::argument:->arguments'
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
*) fail "$(message missing_argument): completion <bash|fish|zsh>" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch() {
|
||||||
|
local command_name="${1:-help}"
|
||||||
|
[[ "$#" -gt 0 ]] && shift
|
||||||
|
|
||||||
|
case "$command_name" in
|
||||||
|
install | i)
|
||||||
|
require_arguments "$command_name" "$#"
|
||||||
|
local -a packages=()
|
||||||
|
mapfile -t packages < <(normalize_packages "$@")
|
||||||
|
run_stapler privileged install "${packages[@]}"
|
||||||
|
;;
|
||||||
|
remove | erase | e)
|
||||||
|
require_arguments "$command_name" "$#"
|
||||||
|
local -a packages=()
|
||||||
|
mapfile -t packages < <(normalize_packages "$@")
|
||||||
|
run_stapler privileged remove "${packages[@]}"
|
||||||
|
;;
|
||||||
|
upgrade | update | u) run_stapler privileged up "$@" ;;
|
||||||
|
search | s)
|
||||||
|
require_arguments "$command_name" "$#"
|
||||||
|
run_stapler user search "$@"
|
||||||
|
;;
|
||||||
|
info | query-info | qi)
|
||||||
|
require_arguments "$command_name" "$#"
|
||||||
|
local -a packages=()
|
||||||
|
mapfile -t packages < <(normalize_packages "$@")
|
||||||
|
run_stapler user info "${packages[@]}"
|
||||||
|
;;
|
||||||
|
list | packages | query-all | qa) run_stapler user list "$@" ;;
|
||||||
|
refresh | r) run_stapler privileged refresh "$@" ;;
|
||||||
|
repo-list | rl) run_stapler user repo list "$@" ;;
|
||||||
|
repo)
|
||||||
|
if [[ "$#" -eq 0 ]]; then
|
||||||
|
run_stapler user repo list
|
||||||
|
elif [[ "${1:-}" == 'list' || "${1:-}" == 'ls' ]]; then
|
||||||
|
run_stapler user repo "$@"
|
||||||
|
else
|
||||||
|
run_stapler privileged repo "$@"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
fix | f) run_stapler privileged fix "$@" ;;
|
||||||
|
doctor | d) doctor ;;
|
||||||
|
config | c)
|
||||||
|
if [[ "$#" -eq 0 ]]; then
|
||||||
|
run_stapler user config show
|
||||||
|
else
|
||||||
|
run_stapler user config "$@"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
completion) completion "$@" ;;
|
||||||
|
support) run_stapler user support "$@" ;;
|
||||||
|
version | v | --version)
|
||||||
|
printf 'Nivora CLI %s\n' "$NIVORA_VERSION"
|
||||||
|
command -v stplr >/dev/null 2>&1 && stplr version
|
||||||
|
;;
|
||||||
|
help | h | -h | --help) show_help ;;
|
||||||
|
*) fail "$(message unknown_command): ${command_name}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
detect_language
|
||||||
|
setup_style
|
||||||
|
parse_options "$@"
|
||||||
|
set -- "${arguments[@]}"
|
||||||
|
|
||||||
|
case "$(basename "$0")" in
|
||||||
|
nv)
|
||||||
|
if [[ "$#" -eq 0 ]]; then interactive_menu; else dispatch "$@"; fi
|
||||||
|
;;
|
||||||
|
nvi) dispatch install "$@" ;;
|
||||||
|
nve) dispatch remove "$@" ;;
|
||||||
|
nvu) dispatch upgrade "$@" ;;
|
||||||
|
nvs) dispatch search "$@" ;;
|
||||||
|
nvqi) dispatch info "$@" ;;
|
||||||
|
nvqa) dispatch list "$@" ;;
|
||||||
|
nvr) dispatch refresh "$@" ;;
|
||||||
|
nvrl) dispatch repo-list "$@" ;;
|
||||||
|
nvf) dispatch fix "$@" ;;
|
||||||
|
nvd) doctor ;;
|
||||||
|
nvc) dispatch config "$@" ;;
|
||||||
|
nivora) dispatch "$@" ;;
|
||||||
|
*) fail "$(message unknown_command): $(basename "$0")" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include = "../stapler-repo.toml"
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
Сведения о лицензии пакета Nivora Stapler Helper
|
|
||||||
|
|
||||||
Лицензия: MIT.
|
|
||||||
Исходный проект: https://github.com/Cheviiot/Nivora
|
|
||||||
|
|
||||||
Нюансы пакета:
|
|
||||||
- Пакет устанавливает CLI-helper для Stapler с командами `sl`, `sli`, `slr`, `slu`, `slf`, `slref`, `sls`, `slii` и `sll`.
|
|
||||||
- Helper не заменяет Stapler: все операции выполняются через системную команду `stplr`.
|
|
||||||
- Через команду повышения привилегий запускаются только `install`, `remove`, `up`, `fix` и `refresh`.
|
|
||||||
- Команды чтения `search`, `info` и `list` выполняются без повышения привилегий.
|
|
||||||
- Префикс репозитория задается через `--repo <name>` или `NIVORA_STPLR_REPO`; по умолчанию короткие имена не привязаны к одному репозиторию.
|
|
||||||
- Пути вида `repo/package` не изменяются.
|
|
||||||
- Helper не исполняет произвольные shell-строки через `sudo`.
|
|
||||||
|
|
||||||
Полный официальный текст MIT:
|
|
||||||
https://opensource.org/licenses/MIT
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
name='nivora-stplr'
|
|
||||||
version='0.3.0'
|
|
||||||
release=1
|
|
||||||
summary='Short command helper for Stapler'
|
|
||||||
summary_ru='Короткие команды для Stapler'
|
|
||||||
desc='Nivora Stapler Helper provides short commands for common Stapler operations across configured repositories and elevates only operations that modify packages or caches.'
|
|
||||||
desc_ru='Nivora Stapler Helper добавляет короткие команды для типовых операций Stapler и повышает привилегии только для изменения пакетов и кэша.'
|
|
||||||
group='System/Configuration/Packaging'
|
|
||||||
homepage='https://github.com/Cheviiot/Nivora'
|
|
||||||
maintainer='Cheviiot <https://github.com/Cheviiot>'
|
|
||||||
|
|
||||||
architectures=('all')
|
|
||||||
license=('MIT')
|
|
||||||
|
|
||||||
provides=()
|
|
||||||
replaces=('nivora-stplr')
|
|
||||||
conflicts=()
|
|
||||||
|
|
||||||
auto_reqprov_method='dirty'
|
|
||||||
auto_req=0
|
|
||||||
auto_prov=0
|
|
||||||
|
|
||||||
deps=()
|
|
||||||
deps_debian=('bash' 'sudo')
|
|
||||||
deps_ubuntu=("${deps_debian[@]}")
|
|
||||||
deps_fedora=('bash' 'sudo')
|
|
||||||
deps_arch=('bash' 'sudo')
|
|
||||||
deps_altlinux=('bash' 'sudo')
|
|
||||||
deps_opensuse=('bash' 'sudo')
|
|
||||||
|
|
||||||
sources=(
|
|
||||||
'local:///nivora-stplr'
|
|
||||||
'local:///LICENSE'
|
|
||||||
)
|
|
||||||
|
|
||||||
checksums=(
|
|
||||||
'sha256:7b0c2a69aed30bc39ac5546aabd0cb82d45b857a52408b4326ad1fd667684ecb'
|
|
||||||
'sha256:c5674e6873211a8ea0f08ee3a950f809c9145c60750746dafff9aee7e1c21cf1'
|
|
||||||
)
|
|
||||||
|
|
||||||
package() {
|
|
||||||
install -Dm755 "${srcdir}/nivora-stplr" "${pkgdir}/usr/bin/sl"
|
|
||||||
|
|
||||||
shortcut=''
|
|
||||||
for shortcut in sli slr slu slf slref sls slii sll; do
|
|
||||||
ln -sfn sl "${pkgdir}/usr/bin/${shortcut}"
|
|
||||||
done
|
|
||||||
|
|
||||||
install-license "${srcdir}/LICENSE" 'nivora-stplr/LICENSE.nivora'
|
|
||||||
}
|
|
||||||
|
|
||||||
files() {
|
|
||||||
files-find-binary
|
|
||||||
files-find-license
|
|
||||||
}
|
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
repo_prefix="${NIVORA_STPLR_REPO:-}"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<'EOF'
|
|
||||||
Nivora Stapler Helper
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
sl <command> [args...]
|
|
||||||
sli <package> [stplr args...] sudo stplr install <package>
|
|
||||||
slr <package> [stplr args...] sudo stplr remove <package>
|
|
||||||
slu [stplr args...] sudo stplr up
|
|
||||||
slf [stplr args...] sudo stplr fix
|
|
||||||
slref [stplr args...] sudo stplr refresh
|
|
||||||
sls <query> [stplr args...] stplr search <query>
|
|
||||||
slii <package> [stplr args...] stplr info <package>
|
|
||||||
sll [stplr args...] stplr list
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
install, in, i install package with sudo
|
|
||||||
remove, rm, r remove package with sudo
|
|
||||||
up, upgrade, u upgrade installed packages with sudo
|
|
||||||
fix, f run stplr fix with sudo
|
|
||||||
refresh, ref refresh repositories with sudo
|
|
||||||
search, s search packages
|
|
||||||
info, show show package info
|
|
||||||
list, ls list repository packages
|
|
||||||
help show this help
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--repo <name> prefix short package names with repository, e.g. sli --repo nivora parsec
|
|
||||||
|
|
||||||
Environment:
|
|
||||||
NIVORA_STPLR_REPO optional repository prefix for short names, default: disabled
|
|
||||||
NIVORA_STPLR_SUDO privilege command, default: sudo
|
|
||||||
NIVORA_STPLR_QUIET=1 do not print command before execution
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
die() {
|
|
||||||
echo "nivora-stplr: $*" >&2
|
|
||||||
exit 2
|
|
||||||
}
|
|
||||||
|
|
||||||
need_stplr() {
|
|
||||||
command -v stplr >/dev/null 2>&1 || die "команда stplr не найдена"
|
|
||||||
}
|
|
||||||
|
|
||||||
sudo_cmd() {
|
|
||||||
if [[ "${EUID}" -eq 0 ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
local command_name="${NIVORA_STPLR_SUDO:-sudo}"
|
|
||||||
command -v "${command_name}" >/dev/null 2>&1 || die "команда ${command_name} не найдена"
|
|
||||||
printf '%s\n' "${command_name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
is_package_token() {
|
|
||||||
local value="$1"
|
|
||||||
|
|
||||||
[[ -n "${value}" ]] || return 1
|
|
||||||
[[ "${value}" == -* ]] && return 1
|
|
||||||
[[ "${value}" == */* ]] && return 1
|
|
||||||
[[ "${value}" == ./* || "${value}" == ../* || "${value}" == /* ]] && return 1
|
|
||||||
[[ "${value}" == *.rpm || "${value}" == *.deb || "${value}" == *.pkg.tar.* ]] && return 1
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize_package() {
|
|
||||||
local value="$1"
|
|
||||||
|
|
||||||
if [[ -n "${repo_prefix}" ]] && is_package_token "${value}"; then
|
|
||||||
printf '%s/%s\n' "${repo_prefix}" "${value}"
|
|
||||||
else
|
|
||||||
printf '%s\n' "${value}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize_package_args() {
|
|
||||||
local arg
|
|
||||||
|
|
||||||
for arg in "$@"; do
|
|
||||||
normalize_package "${arg}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
extract_repo_option() {
|
|
||||||
local -n output_ref="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
output_ref=()
|
|
||||||
while [[ "$#" -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--repo)
|
|
||||||
[[ "$#" -ge 2 ]] || die "для --repo нужно имя репозитория"
|
|
||||||
repo_prefix="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--repo=*)
|
|
||||||
repo_prefix="${1#--repo=}"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
output_ref+=("$1")
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
print_and_exec() {
|
|
||||||
local -a command=("$@")
|
|
||||||
|
|
||||||
if [[ "${NIVORA_STPLR_QUIET:-0}" != "1" ]]; then
|
|
||||||
printf '=>'
|
|
||||||
printf ' %q' "${command[@]}"
|
|
||||||
printf '\n'
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "${command[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
run_stplr() {
|
|
||||||
local mode="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
need_stplr
|
|
||||||
|
|
||||||
local -a command=()
|
|
||||||
if [[ "${mode}" == "sudo" ]]; then
|
|
||||||
local privilege
|
|
||||||
privilege="$(sudo_cmd)"
|
|
||||||
if [[ -n "${privilege}" ]]; then
|
|
||||||
command+=("${privilege}")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
command+=(stplr "$@")
|
|
||||||
print_and_exec "${command[@]}"
|
|
||||||
}
|
|
||||||
|
|
||||||
require_args() {
|
|
||||||
local command_name="$1"
|
|
||||||
local count="$2"
|
|
||||||
|
|
||||||
if [[ "${count}" -eq 0 ]]; then
|
|
||||||
die "для команды ${command_name} нужен аргумент"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch() {
|
|
||||||
local command_name="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
case "${command_name}" in
|
|
||||||
install | in | i)
|
|
||||||
require_args "${command_name}" "$#"
|
|
||||||
local -a args=()
|
|
||||||
extract_repo_option args "$@"
|
|
||||||
require_args "${command_name}" "${#args[@]}"
|
|
||||||
mapfile -t normalized < <(normalize_package_args "${args[@]}")
|
|
||||||
run_stplr sudo install "${normalized[@]}"
|
|
||||||
;;
|
|
||||||
remove | rm | r | erase | delete | del)
|
|
||||||
require_args "${command_name}" "$#"
|
|
||||||
local -a args=()
|
|
||||||
extract_repo_option args "$@"
|
|
||||||
require_args "${command_name}" "${#args[@]}"
|
|
||||||
mapfile -t normalized < <(normalize_package_args "${args[@]}")
|
|
||||||
run_stplr sudo remove "${normalized[@]}"
|
|
||||||
;;
|
|
||||||
up | upgrade | u)
|
|
||||||
run_stplr sudo up "$@"
|
|
||||||
;;
|
|
||||||
fix | f)
|
|
||||||
run_stplr sudo fix "$@"
|
|
||||||
;;
|
|
||||||
refresh | ref)
|
|
||||||
run_stplr sudo refresh "$@"
|
|
||||||
;;
|
|
||||||
search | s)
|
|
||||||
require_args "${command_name}" "$#"
|
|
||||||
run_stplr user search "$@"
|
|
||||||
;;
|
|
||||||
info | show)
|
|
||||||
require_args "${command_name}" "$#"
|
|
||||||
local -a args=()
|
|
||||||
extract_repo_option args "$@"
|
|
||||||
require_args "${command_name}" "${#args[@]}"
|
|
||||||
mapfile -t normalized < <(normalize_package_args "${args[@]}")
|
|
||||||
run_stplr user info "${normalized[@]}"
|
|
||||||
;;
|
|
||||||
list | ls | l)
|
|
||||||
run_stplr user list "$@"
|
|
||||||
;;
|
|
||||||
version | support)
|
|
||||||
run_stplr user "${command_name}" "$@"
|
|
||||||
;;
|
|
||||||
help | -h | --help | "")
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
die "неизвестная команда: ${command_name}. Запустите: sl help"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local invoked
|
|
||||||
invoked="$(basename "$0")"
|
|
||||||
|
|
||||||
case "${invoked}" in
|
|
||||||
sli) dispatch install "$@" ;;
|
|
||||||
slr) dispatch remove "$@" ;;
|
|
||||||
slu) dispatch up "$@" ;;
|
|
||||||
slf) dispatch fix "$@" ;;
|
|
||||||
slref) dispatch refresh "$@" ;;
|
|
||||||
sls) dispatch search "$@" ;;
|
|
||||||
slii) dispatch info "$@" ;;
|
|
||||||
sll) dispatch list "$@" ;;
|
|
||||||
sl)
|
|
||||||
if [[ "$#" -eq 0 ]]; then
|
|
||||||
usage
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
local command_name="$1"
|
|
||||||
shift
|
|
||||||
dispatch "${command_name}" "$@"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
die "неизвестное имя запуска: ${invoked}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name='opencode'
|
name='opencode'
|
||||||
version=1.18.4
|
version=1.18.10
|
||||||
release=1
|
release=1
|
||||||
summary='Open source AI coding agent desktop app'
|
summary='Open source AI coding agent desktop app'
|
||||||
summary_ru='Десктопное приложение AI-агента OpenCode'
|
summary_ru='Десктопное приложение AI-агента OpenCode'
|
||||||
@@ -50,12 +50,12 @@ sources_arm64=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
checksums=(
|
checksums=(
|
||||||
'sha256:a67bc47a98ded10275e7a8f32fa3e16480b55996cd52232da91450432b4d6599'
|
'sha256:ebc1f7650eb132ee8cb3cfc29bd2ae4d64d9d69ec85b799201602417c31e3f00'
|
||||||
'sha256:5c888de95824a9a5752d1ee3de95e80200eb057eec4078df892a95ac34333888'
|
'sha256:5c888de95824a9a5752d1ee3de95e80200eb057eec4078df892a95ac34333888'
|
||||||
)
|
)
|
||||||
|
|
||||||
checksums_arm64=(
|
checksums_arm64=(
|
||||||
'sha256:09bd2be9951ba5a7a333db818de49524edc6c98fedcca20d13a4a0f1c6c5b9e1'
|
'sha256:d7ee7a8c28989c858e2beffcf32cedc12610500fbfb72aa419436e1682475ce1'
|
||||||
'sha256:5c888de95824a9a5752d1ee3de95e80200eb057eec4078df892a95ac34333888'
|
'sha256:5c888de95824a9a5752d1ee3de95e80200eb057eec4078df892a95ac34333888'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name='tailscale'
|
name='tailscale'
|
||||||
version='1.98.9'
|
version=1.98.10
|
||||||
release=3
|
release=1
|
||||||
summary='Mesh VPN built on WireGuard'
|
summary='Mesh VPN built on WireGuard'
|
||||||
summary_ru='Mesh VPN на базе WireGuard'
|
summary_ru='Mesh VPN на базе WireGuard'
|
||||||
group='Networking/Other'
|
group='Networking/Other'
|
||||||
@@ -44,15 +44,15 @@ sources_arm64=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
checksums=(
|
checksums=(
|
||||||
'11be30ad301d48f84ff52fec34f8a2f78eb3e3dee1be4e9624d19fccc8df5540'
|
'sha256:52490ce0832b245857e2afef7426d6ae5a4b49fb391412833cc95729bd23f7de'
|
||||||
'fc0e166481e2f97c21dca773ad4bfe673842268935ce1628c14b96af98e70555'
|
'sha256:fc0e166481e2f97c21dca773ad4bfe673842268935ce1628c14b96af98e70555'
|
||||||
'3c7a7d6d7f09890d5e682901acaeb12bda9542fc6450a709c9dc296a91e726a5'
|
'sha256:3c7a7d6d7f09890d5e682901acaeb12bda9542fc6450a709c9dc296a91e726a5'
|
||||||
)
|
)
|
||||||
|
|
||||||
checksums_arm64=(
|
checksums_arm64=(
|
||||||
'fa554ee808d7d07ee8e3ebbc0215ea087157e2a0abbf408e6e18ea7532554db6'
|
'sha256:d74a84e07cb1948d9f09a23ae161417c6127e562949773705c95d0762be2809d'
|
||||||
'fc0e166481e2f97c21dca773ad4bfe673842268935ce1628c14b96af98e70555'
|
'sha256:fc0e166481e2f97c21dca773ad4bfe673842268935ce1628c14b96af98e70555'
|
||||||
'3c7a7d6d7f09890d5e682901acaeb12bda9542fc6450a709c9dc296a91e726a5'
|
'sha256:3c7a7d6d7f09890d5e682901acaeb12bda9542fc6450a709c9dc296a91e726a5'
|
||||||
)
|
)
|
||||||
|
|
||||||
scripts=(
|
scripts=(
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
package_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
repo_root="$(cd "${package_dir}/.." && pwd)"
|
||||||
|
exec "${repo_root}/tools/package_updates.sh" check "$(basename "$package_dir")"
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
Сведения о лицензии пакета Telegram Desktop
|
||||||
|
|
||||||
|
Лицензия: GPL-3.0-only (с отдельным разрешением на линковку с OpenSSL).
|
||||||
|
Исходный проект: https://github.com/telegramdesktop/tdesktop
|
||||||
|
Официальный сайт: https://desktop.telegram.org/
|
||||||
|
Условия использования сервиса: https://telegram.org/tos
|
||||||
|
|
||||||
|
Нюансы пакета:
|
||||||
|
- Пакет перепаковывает официальный статически собранный Linux-архив
|
||||||
|
Telegram Desktop (`tsetup.<version>.tar.xz`), публикуемый Telegram напрямую
|
||||||
|
и через официальные релизы `telegramdesktop/tdesktop` на GitHub.
|
||||||
|
- Собственный код Telegram Desktop распространяется на условиях GNU GPL
|
||||||
|
версии 3 с отдельным разрешением на линковку с OpenSSL; часть bundled-
|
||||||
|
зависимостей (Qt, ffmpeg и другие) распространяется на собственных
|
||||||
|
условиях соответствующих проектов.
|
||||||
|
- Учетные записи, серверы, боты, Premium-подписка и прочие сетевые функции
|
||||||
|
Telegram в пакет не входят и регулируются условиями Telegram.
|
||||||
|
- Локальные данные, кэш и сессии создаются приложением в домашнем каталоге
|
||||||
|
пользователя после запуска и не поставляются внутри пакета.
|
||||||
|
- Пакет добавляет команду `telegram-desktop` и использует официальные
|
||||||
|
desktop-id `org.telegram.desktop`.
|
||||||
|
|
||||||
|
Полный официальный текст GPL-3.0:
|
||||||
|
https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
name='telegram'
|
||||||
|
version=7.0.6
|
||||||
|
release=1
|
||||||
|
summary='Official Telegram messaging client'
|
||||||
|
summary_ru='Официальный клиент мессенджера Telegram'
|
||||||
|
group='Networking/Instant messaging'
|
||||||
|
desc='Telegram Desktop is the official Telegram messaging client with cloud-synced chats, voice and video calls, and no limits on file size or media history.'
|
||||||
|
desc_ru='Telegram Desktop — официальный клиент мессенджера Telegram с облачной синхронизацией чатов, голосовыми и видеозвонками и без ограничений на размер файлов и историю медиа.'
|
||||||
|
homepage='https://desktop.telegram.org/'
|
||||||
|
maintainer='Telegram Messenger LLP <https://github.com/telegramdesktop/tdesktop>'
|
||||||
|
|
||||||
|
architectures=('amd64')
|
||||||
|
|
||||||
|
license=('GPL-3.0-only')
|
||||||
|
|
||||||
|
provides=()
|
||||||
|
replaces=('telegram')
|
||||||
|
conflicts=()
|
||||||
|
|
||||||
|
auto_reqprov_method="dirty"
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
deps=()
|
||||||
|
deps_debian=('libc6' 'libglib2.0-0t64 | libglib2.0-0' 'libfontconfig1' 'libfreetype6' 'libharfbuzz0b' 'libpng16-16' 'libpcre2-8-0' 'libbrotli1' 'libbz2-1.0' 'libblkid1' 'libmount1' 'libselinux1' 'libffi8' 'libexpat1' 'libgraphite2-3' 'zlib1g' 'libx11-6' 'hicolor-icon-theme')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('glibc' 'glib2' 'fontconfig' 'freetype' 'harfbuzz' 'libpng' 'pcre2' 'brotli' 'bzip2-libs' 'libblkid' 'libmount' 'libselinux' 'libffi' 'expat' 'graphite2' 'zlib' 'libX11' 'hicolor-icon-theme')
|
||||||
|
deps_arch=('glibc' 'glib2' 'fontconfig' 'freetype2' 'harfbuzz' 'libpng' 'pcre2' 'brotli' 'bzip2' 'util-linux-libs' 'libselinux' 'libffi' 'expat' 'graphite' 'zlib' 'libx11' 'hicolor-icon-theme')
|
||||||
|
deps_opensuse=('glibc' 'libglib-2_0-0' 'libfontconfig1' 'libfreetype6' 'libharfbuzz0' 'libpng16-16' 'libpcre2-8-0' 'libbrotli1' 'libbz2-1' 'libblkid1' 'libmount1' 'libselinux1' 'libffi8' 'libexpat1' 'libgraphite2-3' 'libz1' 'libX11-6' 'hicolor-icon-theme')
|
||||||
|
deps_altlinux=('glibc' 'glib2' 'libfontconfig1' 'libfreetype' 'libharfbuzz' 'libpng16' 'libpcre2' 'libbrotlicommon' 'libbrotlidec' 'bzlib' 'libblkid' 'libmount' 'libselinux' 'libffi8' 'libexpat' 'libgraphite2' 'zlib' 'libX11' 'icon-theme-hicolor')
|
||||||
|
|
||||||
|
opt_deps=()
|
||||||
|
opt_deps_debian=('xdg-utils' 'libayatana-appindicator3-1 | libappindicator3-1' 'ca-certificates' 'libasound2t64 | libasound2 | pulseaudio' 'libgl1' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk | xdg-desktop-portal-gnome | xdg-desktop-portal-kde' 'pipewire')
|
||||||
|
opt_deps_ubuntu=("${opt_deps_debian[@]}")
|
||||||
|
opt_deps_fedora=('xdg-utils' 'libappindicator-gtk3' 'ca-certificates' 'alsa-lib' 'pulseaudio-libs' 'mesa-libGL' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk' 'pipewire')
|
||||||
|
opt_deps_arch=('xdg-utils' 'libappindicator-gtk3' 'ca-certificates' 'alsa-lib' 'pulseaudio' 'libglvnd' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk' 'pipewire')
|
||||||
|
opt_deps_opensuse=('xdg-utils' 'libappindicator3-1' 'ca-certificates' 'libasound2' 'libpulse0' 'Mesa-libGL1' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk' 'pipewire')
|
||||||
|
opt_deps_altlinux=('xdg-utils' 'libappindicator-gtk3' 'ca-certificates' 'libalsa' 'libGL' 'xdg-desktop-portal' 'xdg-desktop-portal-gtk' 'pipewire')
|
||||||
|
|
||||||
|
sources=(
|
||||||
|
"https://td.telegram.org/tlinux/tsetup.${version}.tar.xz?~archive=false&~name=tsetup.tar.xz"
|
||||||
|
'local:///org.telegram.desktop.desktop'
|
||||||
|
'local:///telegram-desktop.png'
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums=(
|
||||||
|
'sha256:a9463f13c5f479e1dd951629ab9aa3686386cade4eb61138e0141db2efcfad6d'
|
||||||
|
'sha256:8ceb3f6aea1003f84f1b5757cd857f8237b294bb18456e5e0e54d96e6fff04ba'
|
||||||
|
'sha256:3fb1400c7dc9bbc3b5cb3ffedcbf4a9b09c53e28b57a7ff33a8a6b9048864090'
|
||||||
|
'sha256:f3ad1b5ecdc1c9e5ab3719a0b084a3e0b4fc87ad424fbf81043df9637be3d1f5'
|
||||||
|
)
|
||||||
|
|
||||||
|
scripts=(
|
||||||
|
['postinstall']='postinstall.sh'
|
||||||
|
['postremove']='postremove.sh'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}"
|
||||||
|
|
||||||
|
tar --no-same-owner --no-same-permissions -xJf tsetup.tar.xz
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/opt/telegram-desktop"
|
||||||
|
install -Dm755 "Telegram/Telegram" "${pkgdir}/opt/telegram-desktop/Telegram"
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/bin"
|
||||||
|
ln -sfn /opt/telegram-desktop/Telegram "${pkgdir}/usr/bin/telegram-desktop"
|
||||||
|
|
||||||
|
# Telegram's own Launcher::ComputeExternalUpdater() (SourceFiles/core/
|
||||||
|
# launcher.cpp) looks for a file under <exe-dir>/externalupdater.d/ that
|
||||||
|
# contains a line matching its own full executable path; if found, it
|
||||||
|
# calls SetUpdaterDisabledAtStartup(), which is the *documented* way for
|
||||||
|
# distro/repo packagers to tell Telegram "I manage updates, not you".
|
||||||
|
# This one flag fixes two things at once: it makes InstallLauncher() skip
|
||||||
|
# self-writing a shadow ~/.local/share/applications/*.desktop and D-Bus
|
||||||
|
# .service file on every launch, and it makes QGuiApplication's
|
||||||
|
# desktopFileName() (the Wayland app_id used to match the running window
|
||||||
|
# to an icon) use the plain "org.telegram.desktop" id instead of a
|
||||||
|
# per-install-path hashed one — which is what was breaking the
|
||||||
|
# taskbar/window icon even after the shadow-file duplicate was silenced.
|
||||||
|
install -Dm644 /dev/stdin \
|
||||||
|
"${pkgdir}/opt/telegram-desktop/externalupdater.d/nivora" <<'EOF'
|
||||||
|
/opt/telegram-desktop/Telegram
|
||||||
|
EOF
|
||||||
|
|
||||||
|
install-desktop org.telegram.desktop.desktop
|
||||||
|
install -Dm644 telegram-desktop.png \
|
||||||
|
"${pkgdir}/usr/share/icons/hicolor/256x256/apps/org.telegram.desktop.png"
|
||||||
|
|
||||||
|
install-license LICENSE "telegram/LICENSE.nivora"
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find-binary
|
||||||
|
files-find-desktop
|
||||||
|
files-find-license
|
||||||
|
files-find \
|
||||||
|
"/opt/telegram-desktop/**/*" \
|
||||||
|
"/usr/share/icons/hicolor/256x256/apps/org.telegram.desktop.png"
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Telegram
|
||||||
|
Comment=New era of messaging
|
||||||
|
TryExec=telegram-desktop
|
||||||
|
Exec=telegram-desktop -- %U
|
||||||
|
Icon=org.telegram.desktop
|
||||||
|
Terminal=false
|
||||||
|
StartupWMClass=TelegramDesktop
|
||||||
|
Type=Application
|
||||||
|
Categories=Chat;Network;InstantMessaging;Qt;
|
||||||
|
MimeType=x-scheme-handler/tg;x-scheme-handler/tonsite;
|
||||||
|
Keywords=tg;chat;im;messaging;messenger;sms;tdesktop;
|
||||||
|
Actions=quit;
|
||||||
|
DBusActivatable=false
|
||||||
|
SingleMainWindow=true
|
||||||
|
X-GNOME-UsesNotifications=true
|
||||||
|
X-GNOME-SingleWindow=true
|
||||||
|
|
||||||
|
[Desktop Action quit]
|
||||||
|
Exec=telegram-desktop -quit
|
||||||
|
Name=Quit Telegram
|
||||||
|
Icon=application-exit
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
optional_refresh() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
if ! "$@"; then
|
||||||
|
echo "Предупреждение: не удалось обновить ${label}." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
|
||||||
|
fi
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш иконок" \
|
||||||
|
gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor
|
||||||
|
fi
|
||||||
|
if command -v kbuildsycoca6 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
|
||||||
|
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
|
||||||
|
fi
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
optional_refresh() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
if ! "$@"; then
|
||||||
|
echo "Предупреждение: не удалось обновить ${label}." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
|
||||||
|
fi
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш иконок" \
|
||||||
|
gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor
|
||||||
|
fi
|
||||||
|
if command -v kbuildsycoca6 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
|
||||||
|
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
|
||||||
|
fi
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include = "../stapler-repo.toml"
|
||||||
|
After Width: | Height: | Size: 20 KiB |
@@ -2,10 +2,12 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
launcher="${repo_root}/claude-desktop/claude-alt"
|
launcher="${repo_root}/claude-alt/claude-alt"
|
||||||
icon="${repo_root}/claude-desktop/claude-alt.png"
|
icon="${repo_root}/claude/claude-alt.png"
|
||||||
primary_tray_icon="${repo_root}/claude-desktop/claude-tray-orange.png"
|
primary_tray_icon="${repo_root}/claude/claude-tray-orange.png"
|
||||||
alternate_tray_icon="${repo_root}/claude-desktop/claude-alt-tray-turquoise.png"
|
alternate_tray_icon="${repo_root}/claude/claude-alt-tray-turquoise.png"
|
||||||
|
primary_recipe="${repo_root}/claude/Staplerfile"
|
||||||
|
alternate_recipe="${repo_root}/claude-alt/Staplerfile"
|
||||||
temp_dir="$(mktemp -d)"
|
temp_dir="$(mktemp -d)"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
@@ -14,6 +16,15 @@ cleanup() {
|
|||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
if grep -Eq '/usr/lib/claude-alt|com\\.anthropic\\.ClaudeAlt|claude-alt\\.png' \
|
||||||
|
"$primary_recipe"; then
|
||||||
|
echo 'claude-desktop must not ship ClaudeAlt files' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
grep -Fq 'python3 patch-asar.py' "$alternate_recipe"
|
||||||
|
grep -Fq 'com.anthropic.ClaudeAlt.desktop' "$alternate_recipe"
|
||||||
|
python3 -m py_compile "${repo_root}/claude-alt/patch-asar.py"
|
||||||
|
|
||||||
mkdir -p "${temp_dir}/bin" "${temp_dir}/home"
|
mkdir -p "${temp_dir}/bin" "${temp_dir}/home"
|
||||||
log="${temp_dir}/launch.log"
|
log="${temp_dir}/launch.log"
|
||||||
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
||||||
temp_dir="$(mktemp -d)"
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
find "$temp_dir" -mindepth 1 -delete
|
|
||||||
rmdir "$temp_dir"
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
mkdir -p "${temp_dir}/bin"
|
|
||||||
log="${temp_dir}/commands.log"
|
|
||||||
|
|
||||||
cat >"${temp_dir}/bin/stplr" <<'EOF'
|
|
||||||
#!/bin/bash
|
|
||||||
printf 'stplr' >>"$NIVORA_TEST_LOG"
|
|
||||||
printf ' %s' "$@" >>"$NIVORA_TEST_LOG"
|
|
||||||
printf '\n' >>"$NIVORA_TEST_LOG"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat >"${temp_dir}/bin/test-sudo" <<'EOF'
|
|
||||||
#!/bin/bash
|
|
||||||
printf 'sudo' >>"$NIVORA_TEST_LOG"
|
|
||||||
printf ' %s' "$@" >>"$NIVORA_TEST_LOG"
|
|
||||||
printf '\n' >>"$NIVORA_TEST_LOG"
|
|
||||||
exec "$@"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod 0755 "${temp_dir}/bin/"*
|
|
||||||
for alias in sli slii sl; do
|
|
||||||
ln -s "$repo_root/nivora-stplr/nivora-stplr" "${temp_dir}/bin/${alias}"
|
|
||||||
done
|
|
||||||
|
|
||||||
export NIVORA_TEST_LOG="$log"
|
|
||||||
export NIVORA_STPLR_SUDO=test-sudo
|
|
||||||
export NIVORA_STPLR_QUIET=1
|
|
||||||
export PATH="${temp_dir}/bin:${PATH}"
|
|
||||||
|
|
||||||
sli --repo nivora parsec --clean
|
|
||||||
slii nivora/codex
|
|
||||||
|
|
||||||
cat >"${temp_dir}/expected" <<'EOF'
|
|
||||||
sudo stplr install nivora/parsec --clean
|
|
||||||
stplr install nivora/parsec --clean
|
|
||||||
stplr info nivora/codex
|
|
||||||
EOF
|
|
||||||
|
|
||||||
diff -u "${temp_dir}/expected" "$log"
|
|
||||||
echo 'OK: Nivora helper'
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
temp_dir="$(mktemp -d)"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
find "$temp_dir" -mindepth 1 -delete
|
||||||
|
rmdir "$temp_dir"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
mkdir -p "${temp_dir}/bin"
|
||||||
|
log="${temp_dir}/commands.log"
|
||||||
|
|
||||||
|
cat >"${temp_dir}/bin/stplr" <<'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
printf 'stplr' >>"$NIVORA_TEST_LOG"
|
||||||
|
printf ' %s' "$@" >>"$NIVORA_TEST_LOG"
|
||||||
|
printf '\n' >>"$NIVORA_TEST_LOG"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat >"${temp_dir}/bin/test-sudo" <<'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
printf 'sudo' >>"$NIVORA_TEST_LOG"
|
||||||
|
printf ' %s' "$@" >>"$NIVORA_TEST_LOG"
|
||||||
|
printf '\n' >>"$NIVORA_TEST_LOG"
|
||||||
|
exec "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 0755 "${temp_dir}/bin/"*
|
||||||
|
for alias in nv nvi nve nvu nvs nvqi nvqa nvr nvrl nvf nvd nvc; do
|
||||||
|
ln -s "${repo_root}/nivora-cli/nivora" "${temp_dir}/bin/${alias}"
|
||||||
|
done
|
||||||
|
|
||||||
|
export NIVORA_TEST_LOG="$log"
|
||||||
|
export NIVORA_SUDO='test-sudo'
|
||||||
|
export NIVORA_QUIET=1
|
||||||
|
export PATH="${temp_dir}/bin:${PATH}"
|
||||||
|
|
||||||
|
nvi codex --clean
|
||||||
|
nve other/package
|
||||||
|
nvu
|
||||||
|
nvs editor
|
||||||
|
nvqi --json codex
|
||||||
|
nvqa --installed
|
||||||
|
nvr
|
||||||
|
nvrl
|
||||||
|
nvf
|
||||||
|
nvc
|
||||||
|
nv --repo none install local-name
|
||||||
|
|
||||||
|
cat >"${temp_dir}/expected" <<'EOF'
|
||||||
|
sudo stplr install nivora/codex --clean
|
||||||
|
stplr install nivora/codex --clean
|
||||||
|
sudo stplr remove other/package
|
||||||
|
stplr remove other/package
|
||||||
|
sudo stplr up
|
||||||
|
stplr up
|
||||||
|
stplr search editor
|
||||||
|
stplr info --json nivora/codex
|
||||||
|
stplr list --installed
|
||||||
|
sudo stplr refresh
|
||||||
|
stplr refresh
|
||||||
|
stplr repo list
|
||||||
|
sudo stplr fix
|
||||||
|
stplr fix
|
||||||
|
stplr config show
|
||||||
|
sudo stplr install local-name
|
||||||
|
stplr install local-name
|
||||||
|
EOF
|
||||||
|
|
||||||
|
diff -u "${temp_dir}/expected" "$log"
|
||||||
|
|
||||||
|
nv --lang en --help >"${temp_dir}/help-en"
|
||||||
|
nv --lang ru --help >"${temp_dir}/help-ru"
|
||||||
|
nv --lang ru completion fish >"${temp_dir}/completion"
|
||||||
|
nvd --lang en >"${temp_dir}/doctor"
|
||||||
|
NIVORA_QUIET=0 nv --lang en --dry-run install codex \
|
||||||
|
>"${temp_dir}/preview-stdout" 2>"${temp_dir}/preview"
|
||||||
|
|
||||||
|
grep -q 'Simple Stapler package management' "${temp_dir}/help-en"
|
||||||
|
grep -q 'Простое управление пакетами Stapler' "${temp_dir}/help-ru"
|
||||||
|
grep -q 'nvi.*установить' "${temp_dir}/help-ru"
|
||||||
|
grep -q '__fish_use_subcommand' "${temp_dir}/completion"
|
||||||
|
grep -q 'The system is ready' "${temp_dir}/doctor"
|
||||||
|
grep -q 'Preview.*test-sudo stplr install nivora/codex' "${temp_dir}/preview"
|
||||||
|
[[ ! -s "${temp_dir}/preview-stdout" ]]
|
||||||
|
|
||||||
|
if nv --lang de help >"${temp_dir}/invalid-out" 2>"${temp_dir}/invalid"; then
|
||||||
|
echo 'Ожидалась ошибка для неподдерживаемого языка' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
grep -q 'supported languages are ru and en' "${temp_dir}/invalid"
|
||||||
|
|
||||||
|
echo 'OK: Nivora CLI'
|
||||||
@@ -13,6 +13,7 @@ grep -Fq 'compatibility_desktop=' "$recipe"
|
|||||||
grep -Fq 'canonical_desktop=' "$recipe"
|
grep -Fq 'canonical_desktop=' "$recipe"
|
||||||
grep -Fq "sed -i '/^NoDisplay=true\$/d'" "$recipe"
|
grep -Fq "sed -i '/^NoDisplay=true\$/d'" "$recipe"
|
||||||
grep -Fq "sed -i '/^\\[Desktop Entry\\]\$/a NoDisplay=true'" "$recipe"
|
grep -Fq "sed -i '/^\\[Desktop Entry\\]\$/a NoDisplay=true'" "$recipe"
|
||||||
|
grep -Fq 'StartupWMClass=Yandex-browser' "$recipe"
|
||||||
grep -Fq 'update_codecs' "$postinstall"
|
grep -Fq 'update_codecs' "$postinstall"
|
||||||
|
|
||||||
if grep -Eq '/etc/(cron|xdg/autostart)' "$recipe"; then
|
if grep -Eq '/etc/(cron|xdg/autostart)' "$recipe"; then
|
||||||
|
|||||||
@@ -7,18 +7,23 @@ readonly -a PACKAGES=(
|
|||||||
balena-etcher
|
balena-etcher
|
||||||
chatbox
|
chatbox
|
||||||
clash-verge-rev
|
clash-verge-rev
|
||||||
claude-desktop
|
claude-alt
|
||||||
|
claude
|
||||||
codex
|
codex
|
||||||
fisher
|
fisher
|
||||||
github-desktop
|
github-desktop
|
||||||
happ
|
happ
|
||||||
|
max
|
||||||
netbird
|
netbird
|
||||||
nivora-stplr
|
nivora-cli
|
||||||
opencode
|
opencode
|
||||||
parsec
|
parsec
|
||||||
pineconemc
|
pineconemc
|
||||||
tailscale
|
tailscale
|
||||||
|
telegram
|
||||||
ventoy
|
ventoy
|
||||||
|
vintner
|
||||||
|
vk-messenger
|
||||||
vual
|
vual
|
||||||
yandex-browser-stable
|
yandex-browser-stable
|
||||||
)
|
)
|
||||||
@@ -211,6 +216,51 @@ latest_yandex_browser() {
|
|||||||
printf '%s\n' "$version"
|
printf '%s\n' "$version"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
latest_max() {
|
||||||
|
local filename ver build
|
||||||
|
filename="$(
|
||||||
|
curl --retry 3 --retry-delay 2 --retry-all-errors \
|
||||||
|
--connect-timeout 30 --max-time 120 -fsSL \
|
||||||
|
'https://download.max.ru/linux/deb/dists/stable/main/binary-amd64/Packages.gz' |
|
||||||
|
gzip -dc |
|
||||||
|
awk '
|
||||||
|
/^Package: max$/ { selected = 1; next }
|
||||||
|
/^Package: / { selected = 0 }
|
||||||
|
selected && /^Filename: / { print $2 }
|
||||||
|
' |
|
||||||
|
sort -V |
|
||||||
|
tail -1
|
||||||
|
)"
|
||||||
|
[[ -n "$filename" ]] || die 'cannot determine latest MAX version'
|
||||||
|
filename="$(basename "$filename")"
|
||||||
|
filename="${filename#MAX-}"
|
||||||
|
filename="${filename%.deb}"
|
||||||
|
ver="${filename%.*}"
|
||||||
|
build="${filename##*.}"
|
||||||
|
[[ -n "$ver" && -n "$build" ]] || die 'cannot parse latest MAX filename'
|
||||||
|
printf '%s~%s\n' "$ver" "$build"
|
||||||
|
}
|
||||||
|
|
||||||
|
latest_vk_messenger() {
|
||||||
|
local temp_dir version
|
||||||
|
temp_dir="$(mktemp -d)"
|
||||||
|
curl --retry 3 --retry-delay 2 --retry-all-errors \
|
||||||
|
--connect-timeout 30 --max-time 300 -fsSL \
|
||||||
|
-o "${temp_dir}/vk-messenger.deb" \
|
||||||
|
'https://upload.object2.vk-apps.com/vk-me-desktop-dev-5837a06d-5f28-484a-ac22-045903cb1b1a/latest/vk-messenger.deb'
|
||||||
|
(
|
||||||
|
cd "$temp_dir"
|
||||||
|
ar x vk-messenger.deb
|
||||||
|
tar -xOf control.tar.* ./control
|
||||||
|
) >"${temp_dir}/control"
|
||||||
|
version="$(awk '$1 == "Version:" {print $2; exit}' "${temp_dir}/control")"
|
||||||
|
version="${version%-*}"
|
||||||
|
[[ -n "$version" ]] || die 'cannot determine latest VK Messenger version'
|
||||||
|
printf '%s\n' "$version"
|
||||||
|
find "$temp_dir" -mindepth 1 -delete
|
||||||
|
rmdir "$temp_dir"
|
||||||
|
}
|
||||||
|
|
||||||
latest_version() {
|
latest_version() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
adwyra) github_latest_release Cheviiot/Adwyra ;;
|
adwyra) github_latest_release Cheviiot/Adwyra ;;
|
||||||
@@ -218,20 +268,24 @@ latest_version() {
|
|||||||
balena-etcher) github_latest_release balena-io/etcher ;;
|
balena-etcher) github_latest_release balena-io/etcher ;;
|
||||||
chatbox) latest_chatbox ;;
|
chatbox) latest_chatbox ;;
|
||||||
clash-verge-rev) github_latest_release clash-verge-rev/clash-verge-rev ;;
|
clash-verge-rev) github_latest_release clash-verge-rev/clash-verge-rev ;;
|
||||||
claude-desktop) latest_claude_desktop ;;
|
claude | claude-alt) latest_claude_desktop ;;
|
||||||
codex) github_latest_release Boria138/codex-app-linux ;;
|
codex) github_latest_release Boria138/codex-app-linux ;;
|
||||||
fisher) github_latest_release jorgebucaran/fisher ;;
|
fisher) github_latest_release jorgebucaran/fisher ;;
|
||||||
github-desktop)
|
github-desktop)
|
||||||
github_latest_release desktop/desktop | sed 's/^release-//'
|
github_latest_release desktop/desktop | sed 's/^release-//'
|
||||||
;;
|
;;
|
||||||
happ) github_latest_release Happ-proxy/happ-desktop ;;
|
happ) github_latest_release Happ-proxy/happ-desktop ;;
|
||||||
|
max) latest_max ;;
|
||||||
netbird) github_latest_release netbirdio/netbird ;;
|
netbird) github_latest_release netbirdio/netbird ;;
|
||||||
nivora-stplr) current_version nivora-stplr ;;
|
nivora-cli) current_version nivora-cli ;;
|
||||||
opencode) github_latest_release anomalyco/opencode ;;
|
opencode) github_latest_release anomalyco/opencode ;;
|
||||||
parsec) latest_parsec ;;
|
parsec) latest_parsec ;;
|
||||||
pineconemc) github_latest_release ElyPrismLauncher/Launcher ;;
|
pineconemc) github_latest_release ElyPrismLauncher/Launcher ;;
|
||||||
tailscale) latest_tailscale ;;
|
tailscale) latest_tailscale ;;
|
||||||
|
telegram) github_latest_release telegramdesktop/tdesktop ;;
|
||||||
ventoy) github_latest_release ventoy/Ventoy ;;
|
ventoy) github_latest_release ventoy/Ventoy ;;
|
||||||
|
vintner) github_latest_release Cheviiot/vintner ;;
|
||||||
|
vk-messenger) latest_vk_messenger ;;
|
||||||
vual) github_latest_release Cheviiot/Vual ;;
|
vual) github_latest_release Cheviiot/Vual ;;
|
||||||
yandex-browser-stable) latest_yandex_browser ;;
|
yandex-browser-stable) latest_yandex_browser ;;
|
||||||
*) die "unknown package: $1" ;;
|
*) die "unknown package: $1" ;;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ if [[ "${#python_files[@]}" -gt 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
python3 -m unittest discover -s tests -p 'test_*.py' -v
|
python3 -m unittest discover -s tests -p 'test_*.py' -v
|
||||||
bash tests/test_helper.sh
|
bash tests/test_nivora_cli.sh
|
||||||
bash tests/test_claude_alt.sh
|
bash tests/test_claude_alt.sh
|
||||||
bash tests/test_codex_computer_use.sh
|
bash tests/test_codex_computer_use.sh
|
||||||
bash tests/test_happ_theme.sh
|
bash tests/test_happ_theme.sh
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ def main() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
for package in package_dirs:
|
for package in package_dirs:
|
||||||
command = f"stplr install nivora/{package}"
|
command = f"`stplr install nivora/{package}`"
|
||||||
version, architectures = package_metadata(package)
|
version, architectures = package_metadata(package)
|
||||||
matching_lines = [
|
matching_lines = [
|
||||||
index
|
index
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ esac
|
|||||||
# package | command | persistent state marker | desktop/unit | icon
|
# package | command | persistent state marker | desktop/unit | icon
|
||||||
readonly -a lifecycle_packages=(
|
readonly -a lifecycle_packages=(
|
||||||
'clash-verge-rev|/usr/bin/clash-verge|/home/nivora-test/.local/share/io.github.clash-verge-rev.clash-verge-rev/nivora-lifecycle-state|/usr/share/applications/Clash Verge.desktop|/usr/share/icons/hicolor/128x128/apps/clash-verge.png'
|
'clash-verge-rev|/usr/bin/clash-verge|/home/nivora-test/.local/share/io.github.clash-verge-rev.clash-verge-rev/nivora-lifecycle-state|/usr/share/applications/Clash Verge.desktop|/usr/share/icons/hicolor/128x128/apps/clash-verge.png'
|
||||||
'claude-desktop|/usr/bin/claude-desktop|/home/nivora-test/.config/Claude/nivora-lifecycle-state|/usr/share/applications/com.anthropic.Claude.desktop|/usr/share/icons/hicolor/128x128/apps/claude-desktop.png'
|
'claude|/usr/bin/claude-desktop|/home/nivora-test/.config/Claude/nivora-lifecycle-state|/usr/share/applications/com.anthropic.Claude.desktop|/usr/share/icons/hicolor/128x128/apps/claude-desktop.png'
|
||||||
'codex|/usr/bin/codex-app|/home/nivora-test/.codex/nivora-lifecycle-state|/usr/share/applications/codex-app.desktop|/usr/share/icons/hicolor/512x512/apps/codex-app.png'
|
'codex|/usr/bin/codex-app|/home/nivora-test/.codex/nivora-lifecycle-state|/usr/share/applications/codex-app.desktop|/usr/share/icons/hicolor/512x512/apps/codex-app.png'
|
||||||
'nivora-stplr|/usr/bin/sl|/home/nivora-test/.config/nivora-stplr/nivora-lifecycle-state|-|-'
|
'nivora-cli|/usr/bin/nv|/home/nivora-test/.config/nivora-cli/nivora-lifecycle-state|-|-'
|
||||||
'opencode|/usr/bin/opencode-desktop|/home/nivora-test/.config/opencode/nivora-lifecycle-state|/usr/share/applications/opencode-desktop.desktop|/usr/share/icons/hicolor/128x128/apps/ai.opencode.desktop.png'
|
'opencode|/usr/bin/opencode-desktop|/home/nivora-test/.config/opencode/nivora-lifecycle-state|/usr/share/applications/opencode-desktop.desktop|/usr/share/icons/hicolor/128x128/apps/ai.opencode.desktop.png'
|
||||||
'tailscale|/usr/bin/tailscale|/var/lib/tailscale/nivora-lifecycle-state|/usr/lib/systemd/system/tailscaled.service|-'
|
'tailscale|/usr/bin/tailscale|/var/lib/tailscale/nivora-lifecycle-state|/usr/lib/systemd/system/tailscaled.service|-'
|
||||||
'netbird|/usr/bin/netbird|/var/lib/netbird/nivora-lifecycle-state|/usr/lib/systemd/system/netbird.service|-'
|
'netbird|/usr/bin/netbird|/var/lib/netbird/nivora-lifecycle-state|/usr/lib/systemd/system/netbird.service|-'
|
||||||
|
|||||||
@@ -17,18 +17,23 @@ EXPECTED_PACKAGES = (
|
|||||||
"balena-etcher",
|
"balena-etcher",
|
||||||
"chatbox",
|
"chatbox",
|
||||||
"clash-verge-rev",
|
"clash-verge-rev",
|
||||||
"claude-desktop",
|
"claude",
|
||||||
|
"claude-alt",
|
||||||
"codex",
|
"codex",
|
||||||
"fisher",
|
"fisher",
|
||||||
"github-desktop",
|
"github-desktop",
|
||||||
"happ",
|
"happ",
|
||||||
|
"max",
|
||||||
"netbird",
|
"netbird",
|
||||||
"nivora-stplr",
|
"nivora-cli",
|
||||||
"opencode",
|
"opencode",
|
||||||
"parsec",
|
"parsec",
|
||||||
"pineconemc",
|
"pineconemc",
|
||||||
"tailscale",
|
"tailscale",
|
||||||
|
"telegram",
|
||||||
"ventoy",
|
"ventoy",
|
||||||
|
"vintner",
|
||||||
|
"vk-messenger",
|
||||||
"vual",
|
"vual",
|
||||||
"yandex-browser-stable",
|
"yandex-browser-stable",
|
||||||
)
|
)
|
||||||
@@ -42,11 +47,12 @@ REQUIRED_ROOT_FILES = {
|
|||||||
Path("stapler-repo.toml"),
|
Path("stapler-repo.toml"),
|
||||||
Path("docs/maintenance.md"),
|
Path("docs/maintenance.md"),
|
||||||
Path("docs/security-model.md"),
|
Path("docs/security-model.md"),
|
||||||
Path("docs/packages/claude-desktop.md"),
|
Path("docs/packages/claude.md"),
|
||||||
|
Path("docs/packages/claude-alt.md"),
|
||||||
Path("docs/packages/codex.md"),
|
Path("docs/packages/codex.md"),
|
||||||
Path("docs/packages/github-desktop.md"),
|
Path("docs/packages/github-desktop.md"),
|
||||||
Path("docs/packages/opencode.md"),
|
Path("docs/packages/opencode.md"),
|
||||||
Path("docs/packages/nivora-stplr.md"),
|
Path("docs/packages/nivora-cli.md"),
|
||||||
Path("docs/packages/ventoy.md"),
|
Path("docs/packages/ventoy.md"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +170,13 @@ def validate_package(package: str, errors: list[str]) -> dict[str, object]:
|
|||||||
|
|
||||||
if provides != [] or conflicts != []:
|
if provides != [] or conflicts != []:
|
||||||
errors.append(f"{package}: provides/conflicts must not contain binary aliases")
|
errors.append(f"{package}: provides/conflicts must not contain binary aliases")
|
||||||
if replaces != [package]:
|
expected_replaces = [package]
|
||||||
errors.append(f"{package}: replaces must contain only its own base package name")
|
if package == "claude":
|
||||||
|
expected_replaces.append("claude-desktop")
|
||||||
|
if replaces != expected_replaces:
|
||||||
|
errors.append(
|
||||||
|
f"{package}: replaces must be {expected_replaces}, got {replaces}"
|
||||||
|
)
|
||||||
|
|
||||||
if "package()" not in text or "files()" not in text:
|
if "package()" not in text or "files()" not in text:
|
||||||
errors.append(f"{package}: package() or files() is missing")
|
errors.append(f"{package}: package() or files() is missing")
|
||||||
@@ -239,7 +250,7 @@ def validate_readme(metadata: dict[str, dict[str, object]], errors: list[str]) -
|
|||||||
errors.append("README.md: catalog must contain exactly six categories")
|
errors.append("README.md: catalog must contain exactly six categories")
|
||||||
|
|
||||||
for package, values in metadata.items():
|
for package, values in metadata.items():
|
||||||
command = f"stplr install nivora/{package}"
|
command = f"`stplr install nivora/{package}`"
|
||||||
catalog_rows = [
|
catalog_rows = [
|
||||||
line for line in text.splitlines() if line.startswith("|") and command in line
|
line for line in text.splitlines() if line.startswith("|") and command in line
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -93,17 +93,23 @@ for package in "${packages[@]}"; do
|
|||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$package" == 'claude-desktop' ]]; then
|
if [[ "$package" == 'claude' ]]; then
|
||||||
|
for forbidden_path in \
|
||||||
|
/usr/bin/claude-alt \
|
||||||
|
/usr/lib/claude-alt/claude-alt-bin \
|
||||||
|
/usr/share/applications/com.anthropic.ClaudeAlt.desktop; do
|
||||||
|
contains_path "$forbidden_path" && {
|
||||||
|
echo "${package}: обнаружен компонент отдельного пакета ClaudeAlt: ${forbidden_path}" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$package" == 'claude-alt' ]]; then
|
||||||
for required_path in \
|
for required_path in \
|
||||||
/usr/bin/claude-alt \
|
/usr/bin/claude-alt \
|
||||||
/usr/bin/claude-desktop-account2 \
|
|
||||||
/usr/lib/claude-desktop/resources/TrayIconLinux.png \
|
|
||||||
/usr/lib/claude-desktop/resources/TrayIconLinux-Dark.png \
|
|
||||||
/usr/lib/claude-alt/claude-alt-bin \
|
/usr/lib/claude-alt/claude-alt-bin \
|
||||||
/usr/lib/claude-alt/resources/app.asar \
|
/usr/lib/claude-alt/resources/app.asar \
|
||||||
/usr/lib/claude-alt/resources/icon.png \
|
|
||||||
/usr/lib/claude-alt/resources/TrayIconLinux.png \
|
|
||||||
/usr/lib/claude-alt/resources/TrayIconLinux-Dark.png \
|
|
||||||
/usr/share/applications/com.anthropic.ClaudeAlt.desktop \
|
/usr/share/applications/com.anthropic.ClaudeAlt.desktop \
|
||||||
/usr/share/icons/hicolor/512x512/apps/claude-alt.png; do
|
/usr/share/icons/hicolor/512x512/apps/claude-alt.png; do
|
||||||
contains_path "$required_path" || {
|
contains_path "$required_path" || {
|
||||||
@@ -111,10 +117,6 @@ for package in "${packages[@]}"; do
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
contains_path '/usr/share/applications/claude-desktop-account2.desktop' && {
|
|
||||||
echo "${package}: обнаружен устаревший desktop-файл второго профиля" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$package" == 'balena-etcher' ]]; then
|
if [[ "$package" == 'balena-etcher' ]]; then
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
package_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
repo_root="$(cd "${package_dir}/.." && pwd)"
|
||||||
|
exec "${repo_root}/tools/package_updates.sh" check "$(basename "$package_dir")"
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Cheviiot
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
This license covers vintner's own source code. It does not cover the
|
||||||
|
Microsoft Visual C++ Build Tools / Windows SDK that `vintner download`
|
||||||
|
fetches and unpacks, which remain governed by Microsoft's own license terms.
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
name='vintner'
|
||||||
|
version=0.5.0
|
||||||
|
release=1
|
||||||
|
summary='Cross compile with MSVC on Linux via Wine'
|
||||||
|
summary_ru='Кросс-компиляция с MSVC на Linux через Wine'
|
||||||
|
group='Development/Tools'
|
||||||
|
desc='vintner is a single-binary tool for cross compiling with the real MSVC toolchain on Linux via Wine. Once you run its download/install subcommands, cl, link, lib, rc, midl, mc, mt, dumpbin, msbuild, nmake, ml, ml64, armasm, armasm64, cmd and findstr all work as drop-in commands, exactly like on Windows, or can be invoked directly as "vintner cl", "vintner msbuild", etc. without touching PATH. Supports building real KMDF/UMDF drivers via the Windows Driver Kit (--with-wdk), legacy D3DX9 code via the DirectX SDK (--with-dxsdk), old PlatformToolset-pinned .vcxproj files against the one installed compiler, resumes interrupted downloads, and "vintner doctor" diagnoses a broken wine/toolchain setup. Its own CLI is available in English and Russian.'
|
||||||
|
desc_ru='vintner — однобинарный инструмент для кросс-компиляции с реальным MSVC на Linux через Wine. После выполнения его подкоманд download/install команды cl, link, lib, rc, midl, mc, mt, dumpbin, msbuild, nmake, ml, ml64, armasm, armasm64, cmd и findstr работают как обычные команды, точно как в Windows, либо вызываются напрямую как «vintner cl», «vintner msbuild» и т.д., не трогая PATH. Поддерживает сборку настоящих KMDF/UMDF-драйверов через Windows Driver Kit (--with-wdk), устаревший код D3DX9 через DirectX SDK (--with-dxsdk), старые .vcxproj с закреплённым PlatformToolset против единственного установленного компилятора, докачивает прерванные загрузки, а «vintner doctor» диагностирует неисправную настройку wine/toolchain. Сам CLI доступен на английском и русском.'
|
||||||
|
homepage='https://github.com/Cheviiot/vintner'
|
||||||
|
maintainer='Cheviiot <https://github.com/Cheviiot>'
|
||||||
|
|
||||||
|
architectures=('amd64' 'arm64')
|
||||||
|
|
||||||
|
license=('MIT')
|
||||||
|
|
||||||
|
provides=()
|
||||||
|
replaces=('vintner')
|
||||||
|
conflicts=()
|
||||||
|
|
||||||
|
auto_reqprov_method="dirty"
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
# wine/msitools/git/cabextract are needed at runtime by `vintner
|
||||||
|
# download`/`install` and by the tool wrappers themselves, not just at
|
||||||
|
# build time. cabextract is only exercised by --with-dxsdk, but kept a
|
||||||
|
# hard dep for the same reason msitools is: small, no heavy transitive
|
||||||
|
# deps, and simpler than making package deps conditional on a flag.
|
||||||
|
deps=()
|
||||||
|
deps_debian=('wine' 'msitools' 'git' 'cabextract')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('wine' 'msitools' 'git' 'cabextract')
|
||||||
|
deps_arch=('wine' 'msitools' 'git' 'cabextract')
|
||||||
|
deps_opensuse=('wine' 'msitools' 'git' 'cabextract')
|
||||||
|
deps_altlinux=('wine' 'msitools' 'git' 'cabextract')
|
||||||
|
|
||||||
|
build_deps=('binutils')
|
||||||
|
|
||||||
|
# Prebuilt by vintner's own CI (.github/workflows/release.yml) and
|
||||||
|
# published to its GitHub Releases; renamed to a common local name so
|
||||||
|
# package() doesn't need to branch on architecture.
|
||||||
|
sources=(
|
||||||
|
"https://github.com/Cheviiot/vintner/releases/download/v${version}/vintner-linux-amd64?~archive=false&~name=vintner"
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
sources_arm64=(
|
||||||
|
"https://github.com/Cheviiot/vintner/releases/download/v${version}/vintner-linux-arm64?~archive=false&~name=vintner"
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums=(
|
||||||
|
'sha256:c06edc2c6469f3a6bac63bd2a1e811f6fe03cc05c49871413a8f58d5e382732a'
|
||||||
|
'sha256:e377b84adc5315cf372c3d80ecbd3008402d8b07f248e711c7553784e0c33168'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums_arm64=(
|
||||||
|
'sha256:4ddb97ad6c193058589564f99781b3ef5e5725d243d3c1cbb895b81c35799144'
|
||||||
|
'sha256:e377b84adc5315cf372c3d80ecbd3008402d8b07f248e711c7553784e0c33168'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}"
|
||||||
|
chmod +x "${srcdir}/vintner"
|
||||||
|
install-binary "${srcdir}/vintner"
|
||||||
|
install-license "${srcdir}/LICENSE" "vintner/LICENSE"
|
||||||
|
"${srcdir}/vintner" completion bash | install-completion bash vintner
|
||||||
|
"${srcdir}/vintner" completion zsh | install-completion zsh vintner
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find-binary
|
||||||
|
files-find-license
|
||||||
|
files-find "/usr/share/bash-completion/completions/vintner"
|
||||||
|
files-find "/usr/share/zsh/site-functions/_vintner"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
package_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
repo_root="$(cd "${package_dir}/.." && pwd)"
|
||||||
|
exec "${repo_root}/tools/package_updates.sh" check "$(basename "$package_dir")"
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
Сведения о лицензии пакета vk-messenger
|
||||||
|
|
||||||
|
Лицензия: Custom (проприетарная).
|
||||||
|
Исходный продукт: https://vk.me/app
|
||||||
|
Официальный deb/rpm-артефакт: https://vk.me/app (объектное хранилище VK)
|
||||||
|
|
||||||
|
Нюансы пакета:
|
||||||
|
- Пакет перепаковывает официальный Linux-артефакт VK Messenger, распространяемый
|
||||||
|
напрямую с vk.me — отдельного публичного репозитория или GitHub-релиза
|
||||||
|
у продукта нет, поэтому используется прямая ссылка на объектное хранилище VK.
|
||||||
|
- Приложение собрано на Electron/Chromium; лицензии этих компонентов
|
||||||
|
устанавливаются рядом с остальными лицензиями пакета.
|
||||||
|
- Для полноценной работы требуется учетная запись VK ID.
|
||||||
|
- Использование мессенджера, учетной записи и сетевых функций регулируется
|
||||||
|
условиями VK.
|
||||||
|
- Пакет помечен как несвободный через `nonfree=1`.
|
||||||
|
|
||||||
|
Официальные условия:
|
||||||
|
https://vk.com/terms
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
name='vk-messenger'
|
||||||
|
version='6.0.57'
|
||||||
|
release=1
|
||||||
|
summary='VK Messenger client'
|
||||||
|
summary_ru='Официальный клиент VK Messenger'
|
||||||
|
group='Networking/Instant messaging'
|
||||||
|
desc='VK Messenger is the official VK instant messaging client, distributed as an Electron desktop application directly from vk.me.'
|
||||||
|
desc_ru='VK Messenger — официальный клиент мессенджера VK, распространяемый в виде Electron-приложения напрямую с vk.me.'
|
||||||
|
homepage='https://vk.me/app'
|
||||||
|
maintainer='VK Support <support@vk.com>'
|
||||||
|
|
||||||
|
architectures=('amd64')
|
||||||
|
|
||||||
|
license=('Custom')
|
||||||
|
nonfree=1
|
||||||
|
nonfree_msg='VK Messenger является проприетарным приложением VK. Использование мессенджера, учетной записи VK ID и сетевых функций регулируется условиями VK.'
|
||||||
|
nonfree_url='https://vk.com/terms'
|
||||||
|
|
||||||
|
provides=()
|
||||||
|
replaces=('vk-messenger')
|
||||||
|
conflicts=()
|
||||||
|
|
||||||
|
auto_reqprov_method="dirty"
|
||||||
|
auto_req=0
|
||||||
|
auto_prov=0
|
||||||
|
|
||||||
|
deps=()
|
||||||
|
deps_debian=('libc6' 'libglib2.0-0t64 | libglib2.0-0' 'libgtk-3-0t64 | libgtk-3-0' 'libnotify4' 'libnss3' 'libxss1' 'libxtst6' 'xdg-utils' 'libatspi2.0-0' 'libuuid1' 'libsecret-1-0' 'libasound2t64 | libasound2 | pulseaudio' 'libgbm1' 'libdrm2' 'pulseaudio | pulseaudio-utils | pipewire-pulse')
|
||||||
|
deps_ubuntu=("${deps_debian[@]}")
|
||||||
|
deps_fedora=('glibc' 'glib2' 'gtk3' 'libnotify' 'nss' 'libXScrnSaver' 'libXtst' 'xdg-utils' 'at-spi2-core' 'libuuid' 'libsecret' 'alsa-lib' 'mesa-libgbm' 'libdrm' 'pulseaudio-utils')
|
||||||
|
deps_arch=('glibc' 'glib2' 'gtk3' 'libnotify' 'nss' 'libxss' 'libxtst' 'xdg-utils' 'at-spi2-core' 'libutil-linux' 'libsecret' 'alsa-lib' 'libgbm' 'libdrm' 'libpulse')
|
||||||
|
deps_opensuse=('glibc' 'libglib-2_0-0' 'gtk3' 'libnotify4' 'mozilla-nss' 'libXss1' 'libXtst6' 'xdg-utils' 'at-spi2-core' 'libuuid1' 'libsecret-1-0' 'libasound2' 'libgbm1' 'libdrm2' 'pulseaudio-utils')
|
||||||
|
deps_altlinux=('glibc' 'glib2' 'libgtk+3' 'libnotify' 'libnss' 'libXScrnSaver' 'libXtst' 'xdg-utils' 'libat-spi2-core' 'libuuid' 'libsecret' 'libalsa' 'libgbm' 'libdrm' 'pulseaudio-utils')
|
||||||
|
|
||||||
|
opt_deps=()
|
||||||
|
opt_deps_debian=('libayatana-appindicator3-1 | libappindicator3-1')
|
||||||
|
opt_deps_ubuntu=("${opt_deps_debian[@]}")
|
||||||
|
opt_deps_fedora=('libappindicator-gtk3')
|
||||||
|
opt_deps_arch=('libappindicator-gtk3')
|
||||||
|
opt_deps_opensuse=('libappindicator3-1')
|
||||||
|
opt_deps_altlinux=('libappindicator-gtk3')
|
||||||
|
|
||||||
|
build_deps=('binutils')
|
||||||
|
|
||||||
|
sources=(
|
||||||
|
"https://upload.object2.vk-apps.com/vk-me-desktop-dev-5837a06d-5f28-484a-ac22-045903cb1b1a/latest/vk-messenger.deb?~archive=false&~name=vk-messenger.deb"
|
||||||
|
'local:///LICENSE'
|
||||||
|
)
|
||||||
|
|
||||||
|
checksums=(
|
||||||
|
'sha256:cb4fa7a8fb3c6af5c432696e4653751393c9c5c655b6bf0e2d944ff7483ec784'
|
||||||
|
'sha256:ab672f11775fc2a579a2001bef3c8b75d78159a67e004dd55339befe98f9e232'
|
||||||
|
)
|
||||||
|
|
||||||
|
scripts=(
|
||||||
|
['postinstall']='postinstall.sh'
|
||||||
|
['postremove']='postremove.sh'
|
||||||
|
)
|
||||||
|
|
||||||
|
package() {
|
||||||
|
cd "${srcdir}"
|
||||||
|
|
||||||
|
mkdir -p "${srcdir}/extracted"
|
||||||
|
ar x vk-messenger.deb
|
||||||
|
tar -xf data.tar.* -C "${srcdir}/extracted"
|
||||||
|
|
||||||
|
# Upstream's own installer uses the literal (Cyrillic, spaced) product name
|
||||||
|
# as the /opt directory, not a clean slug — find it rather than hardcode it.
|
||||||
|
opt_src="$(find "${srcdir}/extracted/opt" -mindepth 1 -maxdepth 1 -type d | head -1)"
|
||||||
|
[[ -n "$opt_src" ]] || { echo "не найден каталог /opt/* внутри vk-messenger.deb" >&2; exit 1; }
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/opt/vk-messenger"
|
||||||
|
cp -a "${opt_src}/." "${pkgdir}/opt/vk-messenger/"
|
||||||
|
chmod 0755 "${pkgdir}/opt/vk-messenger/chrome-sandbox"
|
||||||
|
|
||||||
|
install -dm755 "${pkgdir}/usr/bin"
|
||||||
|
ln -sfn /opt/vk-messenger/vk-messenger "${pkgdir}/usr/bin/vk-messenger"
|
||||||
|
|
||||||
|
install -Dm644 "${srcdir}/extracted/usr/share/applications/vk-messenger.desktop" \
|
||||||
|
"${pkgdir}/usr/share/applications/vk-messenger.desktop"
|
||||||
|
|
||||||
|
for icon in "${srcdir}"/extracted/usr/share/icons/hicolor/*/apps/vk-messenger.*; do
|
||||||
|
size="$(basename "$(dirname "$(dirname "$icon")")")"
|
||||||
|
install -Dm644 "$icon" \
|
||||||
|
"${pkgdir}/usr/share/icons/hicolor/${size}/apps/$(basename "$icon")"
|
||||||
|
done
|
||||||
|
|
||||||
|
install-license "${srcdir}/LICENSE" "vk-messenger/LICENSE.nivora"
|
||||||
|
install -Dm644 "${opt_src}/LICENSE.electron.txt" \
|
||||||
|
"${pkgdir}/usr/share/licenses/vk-messenger/LICENSE.electron.txt"
|
||||||
|
install -Dm644 "${opt_src}/LICENSES.chromium.html" \
|
||||||
|
"${pkgdir}/usr/share/licenses/vk-messenger/LICENSES.chromium.html"
|
||||||
|
}
|
||||||
|
|
||||||
|
files() {
|
||||||
|
files-find-binary
|
||||||
|
files-find-desktop
|
||||||
|
files-find-license
|
||||||
|
files-find \
|
||||||
|
"/opt/vk-messenger/**/*" \
|
||||||
|
"/usr/share/icons/hicolor/*/apps/vk-messenger.*"
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
optional_refresh() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
if ! "$@"; then
|
||||||
|
echo "Предупреждение: не удалось обновить ${label}." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
sandbox=/opt/vk-messenger/chrome-sandbox
|
||||||
|
if [[ ! -f "$sandbox" ]]; then
|
||||||
|
echo "Ошибка: не найден Electron sandbox: ${sandbox}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -L /proc/self/ns/user ]] && command -v unshare >/dev/null 2>&1 \
|
||||||
|
&& unshare --user true 2>/dev/null; then
|
||||||
|
chmod 0755 "$sandbox"
|
||||||
|
else
|
||||||
|
chmod 4755 "$sandbox"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш иконок" gtk-update-icon-cache -f -q /usr/share/icons/hicolor
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v kbuildsycoca6 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
|
||||||
|
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
|
||||||
|
fi
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
optional_refresh() {
|
||||||
|
local label=$1
|
||||||
|
shift
|
||||||
|
if ! "$@"; then
|
||||||
|
echo "Предупреждение: не удалось обновить ${label}." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v update-desktop-database >/dev/null 2>&1; then
|
||||||
|
optional_refresh "desktop-базу" update-desktop-database -q /usr/share/applications
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш иконок" gtk-update-icon-cache -f -q /usr/share/icons/hicolor
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v kbuildsycoca6 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca6 --noincremental
|
||||||
|
elif command -v kbuildsycoca5 >/dev/null 2>&1; then
|
||||||
|
optional_refresh "кэш KDE" kbuildsycoca5 --noincremental
|
||||||
|
fi
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
include = "../stapler-repo.toml"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name='yandex-browser-stable'
|
name='yandex-browser-stable'
|
||||||
version='26.4.1.1110'
|
version=26.6.1.1003
|
||||||
release=3
|
release=1
|
||||||
summary='Fast and secure Chromium-based web browser from Yandex'
|
summary='Fast and secure Chromium-based web browser from Yandex'
|
||||||
summary_ru='Быстрый и безопасный браузер Яндекса на основе Chromium'
|
summary_ru='Быстрый и безопасный браузер Яндекса на основе Chromium'
|
||||||
group='Networking/WWW'
|
group='Networking/WWW'
|
||||||
@@ -79,7 +79,7 @@ sources=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
checksums=(
|
checksums=(
|
||||||
'sha256:27c8570c68a5e1b475304aaa4e8accefbc21e150b644a9cbc998ed32d952c8ba'
|
'sha256:740006518ea877303b70a69e063dcc8531fe05b4d1582f270b783e22a83cf852'
|
||||||
'sha256:36fb82bc8a2bb99eea41807712d9abf810edd562fa521955444e2dbef26ff40d'
|
'sha256:36fb82bc8a2bb99eea41807712d9abf810edd562fa521955444e2dbef26ff40d'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -110,6 +110,9 @@ package() {
|
|||||||
canonical_desktop="${pkgdir}/usr/share/applications/ru.yandex.desktop.browser.desktop"
|
canonical_desktop="${pkgdir}/usr/share/applications/ru.yandex.desktop.browser.desktop"
|
||||||
sed -i '/^NoDisplay=true$/d' "${compatibility_desktop}" "${canonical_desktop}"
|
sed -i '/^NoDisplay=true$/d' "${compatibility_desktop}" "${canonical_desktop}"
|
||||||
sed -i '/^\[Desktop Entry\]$/a NoDisplay=true' "${compatibility_desktop}"
|
sed -i '/^\[Desktop Entry\]$/a NoDisplay=true' "${compatibility_desktop}"
|
||||||
|
sed -i '/^StartupWMClass=/d' "${canonical_desktop}"
|
||||||
|
sed -i '/^\[Desktop Entry\]$/a StartupWMClass=Yandex-browser' \
|
||||||
|
"${canonical_desktop}"
|
||||||
cp -a "${srcdir}/extracted/usr/share/appdata" "${pkgdir}/usr/share/"
|
cp -a "${srcdir}/extracted/usr/share/appdata" "${pkgdir}/usr/share/"
|
||||||
cp -a "${srcdir}/extracted/usr/share/gnome-control-center" \
|
cp -a "${srcdir}/extracted/usr/share/gnome-control-center" \
|
||||||
"${pkgdir}/usr/share/"
|
"${pkgdir}/usr/share/"
|
||||||
|
|||||||