mirror of
https://github.com/Cheviiot/Nivora.git
synced 2026-08-03 15:51:12 +00:00
feat: create autonomous Nivora package repository
Maintain a validated cross-distribution package catalog. Automate upstream updates, isolated builds, diagnostics, and direct publication. Build the official GitHub Desktop sources for Linux with working OAuth.
This commit is contained in:
Executable
+6
@@ -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,21 @@
|
||||
Сведения о лицензии пакета Parsec
|
||||
|
||||
Лицензия: Custom.
|
||||
Официальная страница загрузки: https://parsec.app/downloads
|
||||
Источник Linux-пакета: https://builds.parsec.app/package/parsec-linux.deb
|
||||
|
||||
Нюансы пакета:
|
||||
- Пакет перепаковывает официальный deb-артефакт Parsec для Linux.
|
||||
- Parsec является проприетарным приложением Unity Technologies SF.
|
||||
- Использование клиента, учетной записи, удаленного доступа и сетевых функций регулируется условиями Parsec/Unity.
|
||||
- Пакет устанавливает клиентский бинарник `/usr/bin/parsecd` и runtime-данные `/usr/share/parsec`; учетная запись и удаленные хосты в пакет не входят.
|
||||
- Команда `/usr/bin/parsecd` запускается через wrapper Nivora, который перед стартом Parsec включает `client_immersive` в пользовательском `~/.parsec/config.json` или, если JSON поврежден, в `~/.parsec/config.txt`. Это нужно, чтобы системные сочетания клавиш, включая переключение раскладки, уходили в удаленную систему, а не меняли локальную раскладку клиента.
|
||||
- Wrapper учитывает новый формат Parsec 150-89+: если `config.json` является массивом, настройка записывается в объект второго элемента, без удаления существующих параметров. Если пользователь уже включил полный immersive mode через `client_immersive=1`, wrapper сохраняет это значение.
|
||||
- Для обычного запуска без URL wrapper дополнительно передает `client_immersive=2` через command-line advanced setting. Запуски с `parsec://...` deep-link не переписываются, чтобы не ломать подключение по ссылке.
|
||||
- Если нужно вернуть полностью upstream-поведение запуска, используйте `PARSEC_NIVORA_IMMERSIVE=0 parsecd` или измените значение `client_immersive` вручную в настройках Parsec.
|
||||
- Для совместимости на ALT пакет явно требует `libjpeg8` и `libavcodec61`.
|
||||
- Пакет помечен как несвободный через `nonfree=1`.
|
||||
|
||||
Справочные ссылки:
|
||||
- https://parsec.app/terms
|
||||
- https://unity.com/legal/privacy-policy
|
||||
@@ -0,0 +1,81 @@
|
||||
name='parsec'
|
||||
version='150-104a'
|
||||
release=3
|
||||
summary='Low-latency remote desktop and game streaming client'
|
||||
summary_ru='Клиент удаленного рабочего стола и игрового стриминга с низкой задержкой'
|
||||
group='Networking/Remote access'
|
||||
desc='Parsec is a proprietary low-latency remote desktop and game streaming client distributed as an official Linux deb package for Ubuntu 22.04 LTS Desktop.'
|
||||
desc_ru='Parsec — проприетарный клиент удаленного рабочего стола и игрового стриминга с низкой задержкой, распространяемый официальным deb-пакетом для Ubuntu 22.04 LTS Desktop.'
|
||||
homepage='https://parsec.app/downloads'
|
||||
maintainer='Unity Technologies SF <https://parsec.app/>'
|
||||
|
||||
architectures=('amd64')
|
||||
|
||||
license=('Custom')
|
||||
nonfree=1
|
||||
nonfree_msg='Parsec является проприетарным приложением Unity Technologies SF. Использование клиента, учетной записи, удаленного доступа и сетевых функций регулируется условиями Parsec/Unity.'
|
||||
nonfree_url='https://parsec.app/terms'
|
||||
|
||||
provides=()
|
||||
replaces=('parsec')
|
||||
conflicts=()
|
||||
|
||||
auto_reqprov_method="dirty"
|
||||
auto_req=0
|
||||
auto_prov=0
|
||||
|
||||
deps=()
|
||||
deps_debian=('libc6' 'libgcc-s1 | libgcc1' 'libstdc++6' 'libudev1' 'libssl3 | libssl1.1' 'libx11-6' 'libxcursor1' 'libxi6' 'libsm6' 'libgl1' 'libasound2' 'libjpeg8 | libjpeg-turbo8' 'libpng16-16' 'libcurl4' 'libavcodec61 | libavcodec60 | libavcodec59 | libavcodec58 | libavcodec57' 'libxrandr2' 'libvulkan1')
|
||||
deps_ubuntu=("${deps_debian[@]}")
|
||||
deps_fedora=('glibc' 'libgcc' 'libstdc++' 'systemd-libs' 'openssl-libs' 'libX11' 'libXcursor' 'libXi' 'libSM' 'mesa-libGL' 'alsa-lib' 'libjpeg-turbo' 'libpng' 'libcurl' 'ffmpeg-libs' 'libXrandr' 'vulkan-loader')
|
||||
deps_arch=('glibc' 'gcc-libs' 'systemd-libs' 'openssl' 'libx11' 'libxcursor' 'libxi' 'libsm' 'libglvnd' 'alsa-lib' 'libjpeg-turbo' 'libpng' 'curl' 'ffmpeg' 'libxrandr' 'vulkan-icd-loader')
|
||||
deps_opensuse=('glibc' 'libgcc_s1' 'libstdc++6' 'libudev1' 'libopenssl3' 'libX11-6' 'libXcursor1' 'libXi6' 'libSM6' 'Mesa-libGL1' 'libasound2' 'libjpeg8' 'libpng16-16' 'libcurl4' 'libavcodec61' 'libXrandr2' 'libvulkan1')
|
||||
deps_altlinux=('glibc' 'libgcc1' 'libstdc++6' 'libudev0' 'libssl3' 'libX11' 'libXcursor' 'libXi' 'libSM' 'libGL' 'libalsa' 'libjpeg8' 'libpng16' 'libcurl' 'libavcodec61' 'libXrandr' 'libvulkan1')
|
||||
|
||||
build_deps=('binutils')
|
||||
|
||||
sources=(
|
||||
"https://builds.parsec.app/package/parsec-linux.deb?~archive=false&~name=parsec.deb"
|
||||
"local:///parsecd-wrapper"
|
||||
'local:///LICENSE'
|
||||
)
|
||||
|
||||
checksums=(
|
||||
'sha256:c8a4407713d72dcb1c59f082977e81e1b9e8ffd679d0666882cde4c8a0821dd2'
|
||||
'sha256:2830871d7499ac00b70197ea11f2c132382059b4ad8718eb73bdcb28ad13a113'
|
||||
'sha256:d8df7db0c861a3308e59beaabe617703e0e24a92d569044432e8b2c539f1fb6c'
|
||||
)
|
||||
|
||||
scripts=(
|
||||
['postinstall']='postinstall.sh'
|
||||
['postremove']='postremove.sh'
|
||||
)
|
||||
|
||||
package() {
|
||||
cd "${srcdir}"
|
||||
|
||||
mkdir -p "${srcdir}/extracted"
|
||||
ar x parsec.deb
|
||||
tar -xf data.tar.* -C "${srcdir}/extracted"
|
||||
|
||||
install -Dm755 "${srcdir}/extracted/usr/bin/parsecd" "${pkgdir}/usr/lib/parsec/parsecd"
|
||||
install -Dm755 parsecd-wrapper "${pkgdir}/usr/bin/parsecd"
|
||||
install -Dm644 "${srcdir}/extracted/usr/share/applications/parsecd.desktop" "${pkgdir}/usr/share/applications/parsecd.desktop"
|
||||
sed -i 's/^Categories=.*/Categories=Network;RemoteAccess;/' \
|
||||
"${pkgdir}/usr/share/applications/parsecd.desktop"
|
||||
install -Dm644 "${srcdir}/extracted/usr/share/icons/hicolor/256x256/apps/parsecd.png" "${pkgdir}/usr/share/icons/hicolor/256x256/apps/parsecd.png"
|
||||
|
||||
mkdir -p "${pkgdir}/usr/share/parsec"
|
||||
cp -a "${srcdir}/extracted/usr/share/parsec/." "${pkgdir}/usr/share/parsec/"
|
||||
install-license "${srcdir}/LICENSE" "parsec/LICENSE.nivora"
|
||||
}
|
||||
|
||||
files() {
|
||||
files-find-binary
|
||||
files-find-desktop
|
||||
files-find-license
|
||||
files-find \
|
||||
"/usr/lib/parsec/parsecd" \
|
||||
"/usr/share/icons/hicolor/256x256/apps/parsecd.png" \
|
||||
"/usr/share/parsec/**/*"
|
||||
}
|
||||
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
real_binary='/usr/lib/parsec/parsecd'
|
||||
parsec_home="${PARSEC_CONFIG_HOME:-${HOME}/.parsec}"
|
||||
config_txt="${parsec_home}/config.txt"
|
||||
config_json="${parsec_home}/config.json"
|
||||
json_notice='See https://parsec.app/config for documentation and example. JSON must be valid before saving or file be will be erased.'
|
||||
|
||||
immersive_enabled() {
|
||||
case "${PARSEC_NIVORA_IMMERSIVE:-1}" in
|
||||
0 | false | no | off) return 1 ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
set_config_txt_immersive() {
|
||||
mkdir -p "${parsec_home}"
|
||||
touch "${config_txt}"
|
||||
|
||||
if grep -Eq '^[[:space:]]*client_immersive[[:space:]]*=' "${config_txt}"; then
|
||||
sed -i -E 's/^[[:space:]]*client_immersive[[:space:]]*=.*/client_immersive=2/' "${config_txt}"
|
||||
else
|
||||
printf '\nclient_immersive=2\n' >>"${config_txt}"
|
||||
fi
|
||||
}
|
||||
|
||||
set_config_json_immersive() {
|
||||
command -v python3 >/dev/null 2>&1 || return 1
|
||||
|
||||
mkdir -p "${parsec_home}"
|
||||
python3 - "${config_json}" "${json_notice}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(sys.argv[1])
|
||||
notice = sys.argv[2]
|
||||
data = [notice, {}]
|
||||
|
||||
if path.exists() and path.stat().st_size:
|
||||
try:
|
||||
with path.open(encoding="utf-8") as fh:
|
||||
data = json.load(fh)
|
||||
except json.JSONDecodeError:
|
||||
raise SystemExit(2)
|
||||
|
||||
if isinstance(data, dict):
|
||||
settings = data
|
||||
elif isinstance(data, list):
|
||||
while len(data) < 2:
|
||||
data.append({})
|
||||
if not isinstance(data[0], str):
|
||||
data[0] = notice
|
||||
if not isinstance(data[1], dict):
|
||||
data[1] = {}
|
||||
settings = data[1]
|
||||
else:
|
||||
data = [notice, {}]
|
||||
settings = data[1]
|
||||
|
||||
current = settings.get("client_immersive")
|
||||
value = None
|
||||
if isinstance(current, dict):
|
||||
value = current.get("value")
|
||||
|
||||
if value in (1, 2, "1", "2"):
|
||||
immersive_value = int(value)
|
||||
else:
|
||||
immersive_value = 2
|
||||
settings["client_immersive"] = {"value": immersive_value}
|
||||
|
||||
tmp = path.with_suffix(path.suffix + ".tmp")
|
||||
with tmp.open("w", encoding="utf-8") as fh:
|
||||
json.dump(data, fh, ensure_ascii=False, indent=2, sort_keys=True)
|
||||
fh.write("\n")
|
||||
tmp.replace(path)
|
||||
print(immersive_value)
|
||||
PY
|
||||
}
|
||||
|
||||
immersive_value=2
|
||||
|
||||
if immersive_enabled; then
|
||||
if ! immersive_value="$(set_config_json_immersive)"; then
|
||||
set_config_txt_immersive
|
||||
immersive_value=2
|
||||
fi
|
||||
else
|
||||
exec "${real_binary}" "$@"
|
||||
fi
|
||||
|
||||
for arg in "$@"; do
|
||||
if [[ "${arg}" == *client_immersive=* ]]; then
|
||||
exec "${real_binary}" "$@"
|
||||
fi
|
||||
done
|
||||
|
||||
if (($# == 0)); then
|
||||
exec "${real_binary}" "client_immersive=${immersive_value}"
|
||||
fi
|
||||
|
||||
if [[ "$1" == *=* ]]; then
|
||||
first_arg="client_immersive=${immersive_value}:${1}"
|
||||
shift
|
||||
exec "${real_binary}" "${first_arg}" "$@"
|
||||
fi
|
||||
|
||||
exec "${real_binary}" "$@"
|
||||
Executable
+23
@@ -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 -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
|
||||
Executable
+23
@@ -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 -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"
|
||||
Reference in New Issue
Block a user