Compare commits
94 Commits
Author | SHA1 | Date | |
---|---|---|---|
c88478a450 | |||
3e61fec67c | |||
6f484a1169 | |||
dddcb9b7b0 | |||
b03d94e48b | |||
f92bd7089a | |||
eb2356458c | |||
131f455eff | |||
1e52d30f4c | |||
40ec0ac6e1 | |||
443e481561 | |||
c892310f69 | |||
750513b119 | |||
ce1836b646 | |||
56b9f3211c | |||
fae63e28f9 | |||
c632ddb354 | |||
76234bf00d | |||
f8c510ab9f | |||
849a08a791 | |||
952dd26f5f | |||
080c9f42ff | |||
3c3ee286ce | |||
d0d8930491 | |||
93508647e0 | |||
6135e55f92 | |||
2b7c2bbbb3 | |||
afe35f407e | |||
c51d1d9202 | |||
b46dd41ada | |||
f623cba5c0 | |||
e552663442 | |||
7bbceb76c9 | |||
bd6e3bbe27 | |||
0d917190ab | |||
83b8f3b047 | |||
3483cf57f8 | |||
efa4f59403 | |||
c59ed6d505 | |||
2bbc308810 | |||
5ca34a572a | |||
67e63d1831 | |||
0bfe88beed | |||
3ce9f0db35 | |||
469a05105a | |||
70aca61750 | |||
4b35f5e4e6 | |||
7770675a8d | |||
bd79d56776 | |||
fff8b777fe | |||
6bee268ea9 | |||
4b53e819d8 | |||
6c0e8aeb3f | |||
cbc6b9f452 | |||
c705c25613 | |||
8f4b021a93 | |||
5e7d4033e4 | |||
4ac2432770 | |||
3c37310f0d | |||
d300ab197b | |||
eb2cc3c1e6 | |||
7a3acfe5c1 | |||
9cf8af08ab | |||
86940e8962 | |||
db244204c7 | |||
9cb0a5e9ad | |||
1a57ccdb83 | |||
615cd83fb7 | |||
27e2f54653 | |||
af57165c89 | |||
3770c82240 | |||
2dff463303 | |||
9085e38454 | |||
a7d016abc9 | |||
4a5cca2d0f | |||
71000fd3cd | |||
71968bbe13 | |||
29c1a31066 | |||
8f94b61a0e | |||
ae8e2d2807 | |||
0fa288b8a2 | |||
dcac0b9ee5 | |||
4e6e1f524a | |||
47a9b9a96c | |||
9bb14312bd | |||
88b8d2fbf3 | |||
04523775f1 | |||
adc4a42800 | |||
81651af20d | |||
f04ebbaf14 | |||
be1a137eab | |||
719a5b7fe7 | |||
e05bb07f23 | |||
ec053f7e6a |
57
.gitea/workflows/e2e-tests.yaml
Normal file
57
.gitea/workflows/e2e-tests.yaml
Normal file
@ -0,0 +1,57 @@
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 The ALR Authors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
name: E2E
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: altlinux.space/maks1ms/actions-container-runner:latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: https://github.com/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: https://github.com/actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Cache Podman images
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.local/share/containers/storage
|
||||
/var/lib/containers/storage
|
||||
key: ${{ runner.os }}-primes
|
||||
|
||||
- name: Run E2E tests
|
||||
env:
|
||||
DOCKER_HOST: unix:///tmp/podman.sock
|
||||
IGNORE_ROOT_CHECK: 1
|
||||
run: |
|
||||
podman system service -t 0 unix:///tmp/podman.sock &
|
||||
make e2e-test
|
49
.gitea/workflows/pre-commit.yaml
Normal file
49
.gitea/workflows/pre-commit.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 The ALR Authors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
name: Pre-commit
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: https://github.com/actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: https://github.com/actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Set up Python for pre-commit
|
||||
uses: https://github.com/actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
- name: Install deps
|
||||
run: apt-get update && apt-get install -y gettext bc
|
||||
|
||||
- run: pip install pre-commit
|
||||
- run: pre-commit install
|
||||
- run: pre-commit run --all-files
|
67
.gitea/workflows/release.yaml
Normal file
67
.gitea/workflows/release.yaml
Normal file
@ -0,0 +1,67 @@
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 The ALR Authors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
name: Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
changelog:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout this repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Get Changes between Tags
|
||||
id: changes
|
||||
uses: simbo/changes-between-tags-action@v1
|
||||
|
||||
- name: Set version
|
||||
run: |
|
||||
version=$(echo "${GITHUB_REF##*/}" | sed 's/^v//')
|
||||
echo "Version - $version"
|
||||
echo "VERSION=$version" >> $GITHUB_ENV
|
||||
|
||||
- name: Build alr binary
|
||||
run: |
|
||||
CGO_ENABLED=0 go build -ldflags "-X gitea.plemya-x.ru/Plemya-x/ALR/internal/config.Version=${{ env.VERSION }}" -o alr
|
||||
|
||||
- name: Create tar.gz
|
||||
run: |
|
||||
mkdir -p ./out/completion
|
||||
cp alr ./out
|
||||
cp scripts/completion/bash ./out/completion/alr
|
||||
cp scripts/completion/zsh ./out/completion/_alr
|
||||
|
||||
( cd out && tar -czvf ../alr-${{ env.VERSION }}-linux-x86_64.tar.gz * )
|
||||
|
||||
- name: Release
|
||||
uses: akkuman/gitea-release-action@v1
|
||||
with:
|
||||
body: ${{ steps.changes.outputs.changes }}
|
||||
files: |-
|
||||
alr-${{ env.VERSION }}-linux-x86_64.tar.gz
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,3 +8,6 @@
|
||||
.gigaide
|
||||
|
||||
*.out
|
||||
|
||||
e2e-tests/alr
|
||||
commit_msg.txt
|
@ -1,5 +1,5 @@
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 Евгений Храмов
|
||||
# Copyright (C) 2025 The ALR Authors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -47,4 +47,4 @@ issues:
|
||||
# TODO: remove
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "SA1019:"
|
||||
text: "SA1019: interp.ExecHandler"
|
118
.goreleaser.yaml
118
.goreleaser.yaml
@ -1,118 +0,0 @@
|
||||
# This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
# It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
#
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 Евгений Храмов
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
builds:
|
||||
- id: alr
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
binary: alr
|
||||
ldflags:
|
||||
- -X gitea.plemya-x.ru/xpamych/ALR/src/branch/master/internal/config.Version={{.Version}}
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
- 386
|
||||
- arm64
|
||||
- arm
|
||||
- riscv64
|
||||
archives:
|
||||
- name_template: >-
|
||||
{{- .ProjectName}}-
|
||||
{{- .Version}}-
|
||||
{{- .Os}}-
|
||||
{{- if .Arch | eq "amd64"}}x86_64
|
||||
{{- else if .Arch | eq "386"}}i386
|
||||
{{- else if .Arch | eq "arm64"}}aarch64
|
||||
{{- else }}{{ .Arch }}{{ end -}}
|
||||
files:
|
||||
- scripts/completion/*
|
||||
nfpms:
|
||||
- id: alr
|
||||
package_name: linux-user-repository
|
||||
file_name_template: >-
|
||||
{{- .PackageName}}-
|
||||
{{- .Version}}-
|
||||
{{- .Os}}-
|
||||
{{- if .Arch | eq "amd64"}}x86_64
|
||||
{{- else if .Arch | eq "386"}}i386
|
||||
{{- else if .Arch | eq "arm64"}}aarch64
|
||||
{{- else }}{{ .Arch }}{{ end -}}
|
||||
description: "Any Linux Repository"
|
||||
homepage: 'https://gitea.plemya-x.ru/xpamych/ALR'
|
||||
maintainer: 'Евгений Храмов <xpamych@yandex.ru>'
|
||||
license: GPLv3
|
||||
formats:
|
||||
- apk
|
||||
- deb
|
||||
- rpm
|
||||
- archlinux
|
||||
provides:
|
||||
- linux-user-repository
|
||||
conflicts:
|
||||
- linux-user-repository
|
||||
recommends:
|
||||
- aria2
|
||||
contents:
|
||||
- src: scripts/completion/bash
|
||||
dst: /usr/share/bash-completion/completions/alr
|
||||
- src: scripts/completion/zsh
|
||||
dst: /usr/share/zsh/site-functions/_alr
|
||||
aurs:
|
||||
- name: linux-user-repository-bin
|
||||
homepage: 'https://gitea.plemya-x.ru/xpamych/ALR'
|
||||
description: "Any Linux Repository"
|
||||
maintainers:
|
||||
- 'Евгений Храмов <xpamych@yandex.ru>'
|
||||
license: GPLv3
|
||||
private_key: '{{ .Env.AUR_KEY }}'
|
||||
git_url: 'ssh://aur@aur.archlinux.org/linux-user-repository-bin.git'
|
||||
provides:
|
||||
- alr
|
||||
conflicts:
|
||||
- alr
|
||||
depends:
|
||||
- sudo
|
||||
- pacman
|
||||
optdepends:
|
||||
- 'aria2: for downloading torrent sources'
|
||||
package: |-
|
||||
# binaries
|
||||
install -Dm755 ./alr "${pkgdir}/usr/bin/alr"
|
||||
|
||||
# completions
|
||||
install -Dm755 ./scripts/completion/bash ${pkgdir}/usr/share/bash-completion/completions/alr
|
||||
install -Dm755 ./scripts/completion/zsh ${pkgdir}/usr/share/zsh/site-functions/_alr
|
||||
release:
|
||||
gitea:
|
||||
owner: alr
|
||||
name: alr
|
||||
gitea_urls:
|
||||
api: 'https://gitea.elara.ws/api/v1/'
|
||||
download: 'https://gitea.elara.ws'
|
||||
skip_tls_verify: false
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ incpatch .Version }}-next"
|
||||
changelog:
|
||||
sort: asc
|
@ -1,5 +1,5 @@
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 Евгений Храмов
|
||||
# Copyright (C) 2025 The ALR Authors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,28 +0,0 @@
|
||||
# This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
# It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
#
|
||||
# ALR - Any Linux Repository
|
||||
# Copyright (C) 2025 Евгений Храмов
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
platform: linux/amd64
|
||||
pipeline:
|
||||
release:
|
||||
image: goreleaser/goreleaser
|
||||
commands:
|
||||
- goreleaser release
|
||||
secrets: [ gitea_token, aur_key ]
|
||||
when:
|
||||
event: tag
|
21
Makefile
21
Makefile
@ -1,6 +1,6 @@
|
||||
NAME := alr
|
||||
GIT_VERSION = $(shell git describe --tags )
|
||||
|
||||
IGNORE_ROOT_CHECK ?= 0
|
||||
DESTDIR ?=
|
||||
PREFIX ?= /usr/local
|
||||
BIN := ./$(NAME)
|
||||
@ -21,11 +21,12 @@ build: check-no-root $(BIN)
|
||||
|
||||
export CGO_ENABLED := 0
|
||||
$(BIN):
|
||||
go build -ldflags="-X 'gitea.plemya-x.ru/xpamych/ALR/internal/config.Version=$(GIT_VERSION)'" -o $@
|
||||
go build -ldflags="-X 'gitea.plemya-x.ru/Plemya-x/ALR/internal/config.Version=$(GIT_VERSION)'" -o $@
|
||||
|
||||
check-no-root:
|
||||
@if [[ "$$(whoami)" == 'root' ]]; then \
|
||||
@if [[ "$(IGNORE_ROOT_CHECK)" != "1" ]] && [[ "$$(whoami)" == 'root' ]]; then \
|
||||
echo "This target shouldn't run as root" 1>&2; \
|
||||
echo "Set IGNORE_ROOT_CHECK=1 to override" 1>&2; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@ -37,6 +38,7 @@ install: \
|
||||
|
||||
$(INSTALED_BIN): $(BIN)
|
||||
install -Dm755 $< $@
|
||||
setcap cap_setuid,cap_setgid+ep $(INSTALED_BIN)
|
||||
|
||||
$(INSTALLED_BASH_COMPLETION): $(BASH_COMPLETION)
|
||||
install -Dm755 $< $@
|
||||
@ -53,7 +55,7 @@ uninstall:
|
||||
clean clear:
|
||||
rm -f $(BIN)
|
||||
|
||||
OLD_FILES=$$(< old-files)
|
||||
OLD_FILES=$(shell cat old-files)
|
||||
IGNORE_OLD_FILES := $(foreach file,$(shell cat old-files),-ignore $(file))
|
||||
update-license:
|
||||
$(ADD_LICENSE_BIN) -v -f license-header-old-files.tmpl $(OLD_FILES)
|
||||
@ -66,7 +68,18 @@ i18n:
|
||||
$(XGOTEXT_BIN) --output ./internal/translations/default.pot
|
||||
msguniq --use-first -o ./internal/translations/default.pot ./internal/translations/default.pot
|
||||
msgmerge --backup=off -U ./internal/translations/po/ru/default.po ./internal/translations/default.pot
|
||||
bash scripts/i18n-badge.sh
|
||||
|
||||
test-coverage:
|
||||
go test ./... -v -coverpkg=./... -coverprofile=coverage.out
|
||||
bash scripts/coverage-badge.sh
|
||||
|
||||
update-deps-cve:
|
||||
bash scripts/update-deps-cve.sh
|
||||
|
||||
prepare-for-e2e-test: clean build
|
||||
rm -f ./e2e-tests/alr
|
||||
cp alr e2e-tests
|
||||
|
||||
e2e-test: prepare-for-e2e-test
|
||||
go test -tags=e2e ./...
|
24
README.md
24
README.md
@ -3,13 +3,13 @@
|
||||
</p>
|
||||
<b></b>
|
||||
|
||||
[](https://goreportcard.com/report/gitea.plemya-x.ru/Plemya-x/ALR) 
|
||||
[](https://goreportcard.com/report/gitea.plemya-x.ru/Plemya-x/ALR)  
|
||||
|
||||
# ALR (Any Linux Repository)
|
||||
|
||||
ALR - это независимая от дистрибутива система сборки для Linux, аналогичная [AUR](https://wiki.archlinux.org/title/Arch_User_Repository). В настоящее время она находится в стадии бета-тестирования. Исправлено большинство основных ошибок и добавлено большинство важных функций. alr готов к общему использованию, но все еще может время от времени ломаться или заменяться.
|
||||
ALR - это независимая от дистрибутива система сборки для Linux (форк [LURE](https://github.com/lure-sh/lure), аналогичная [AUR](https://wiki.archlinux.org/title/Arch_User_Repository). В настоящее время она находится в стадии бета-тестирования. Исправлено большинство основных ошибок и добавлено большинство важных функций. ALR готов к общему использованию, но все еще может время от времени ломаться или изменяться.
|
||||
|
||||
ALR написан на чистом Go и после сборки не имеет зависимостей. Единственное, для повышения привилегий ALR требуется команда, такая как `sudo`, `doas` и т.д., а также поддерживаемый менеджер пакетов. В настоящее время ALR поддерживает `apt`, `pacman`, `apk`, `dnf`, `yum`, and `zypper`. Если в вашей системе существует поддерживаемый менеджер пакетов, он будет обнаружен и использован автоматически.
|
||||
ALR написан на чистом Go и после сборки не имеет зависимостей. Для повышения привилегий ALR требуется команда, такая как `sudo`, `doas` и т.д., а также поддерживаемый менеджер пакетов. В настоящее время ALR поддерживает `apt`, `apt-get` `pacman`, `apk`, `dnf`, `yum`, and `zypper`. Если в вашей системе используется поддерживаемый менеджер пакетов, то он будет обнаружен и использован автоматически.
|
||||
|
||||
---
|
||||
|
||||
@ -23,14 +23,14 @@ ALR написан на чистом Go и после сборки не имее
|
||||
curl -fsSL plemya-x.ru/alr/install.sh | bash
|
||||
```
|
||||
|
||||
**ВАЖНО**: При этом скрипт будет загружен и запущен с <https://gitea.plemya-x.ru/Plemya-x/ALR/src/branch/master/scripts/install.sh>. Пожалуйста, просматривайте любые скрипты, которые вы скачиваете из Интернета (включая этот), прежде чем запускать их.
|
||||
**ВАЖНО**: При этом скрипт будет загружен и запущен с <https://plemya-x.ru/alr/install.sh>. Пожалуйста, просматривайте любые скрипты, которые вы скачиваете из Интернета (включая этот), прежде чем запускать их.
|
||||
|
||||
### Сборка из исходного кода
|
||||
|
||||
Чтобы собрать ALR из исходного кода, вам понадобится версия Go 1.18 или новее. Как только Go будет установлен, клонируйте это репозиторий и запустите:
|
||||
|
||||
```shell
|
||||
make build
|
||||
make build -B
|
||||
sudo make install
|
||||
```
|
||||
|
||||
@ -44,20 +44,23 @@ ALR был создан потому, что упаковка программн
|
||||
|
||||
## Документация
|
||||
|
||||
Документация по всем этим вопросам находится в [Wiki](https://gitea.plemya-x.ru/xpamych/ALR/wiki/Home).
|
||||
Документация находится в [Wiki](https://disc.plemya-x.ru/c/alr/wiki-alr).
|
||||
|
||||
---
|
||||
|
||||
## Репозитории
|
||||
|
||||
Репозитории alr - это git-хранилища, которые содержат каталог для каждого пакета с файлом `alr.sh` внутри. Файл `alr.sh` содержит все инструкции по сборке пакета и информацию о нем. Скрипты `alr.sh` аналогичны скриптам Aur PKGBUILD. Репозиторий [по-умолчанию](https://gitea.plemya-x.ru/xpamych/xpamych-alr-repo.git).
|
||||
Репозитории alr - это git-хранилища, которые содержат каталог для каждого пакета с файлом `alr.sh` внутри. Файл `alr.sh` содержит все инструкции по сборке пакета и информацию о нем. Скрипты `alr.sh` аналогичны скриптам Aur PKGBUILD.
|
||||
|
||||
Например, репозиторий [Plemya-x/alr-repo](https://gitea.plemya-x.ru/Plemya-x/alr-repo.git) можно подключить так:
|
||||
```
|
||||
alr addrepo --name alr-repo --url https://gitea.plemya-x.ru/Plemya-x/alr-repo.git
|
||||
```
|
||||
|
||||
---
|
||||
## Соцсети
|
||||
VK - https://vk.com/plemya_kh
|
||||
|
||||
Discord - https://discord.com/channels/817759634105827358/1261631565084233749
|
||||
|
||||
Telegram - https://t.me/plemyakh
|
||||
|
||||
## Спасибы
|
||||
@ -70,3 +73,6 @@ Telegram - https://t.me/plemyakh
|
||||
- <https://github.com/goreleaser/nfpm>
|
||||
- <https://github.com/charmbracelet/bubbletea>
|
||||
- <https://gitlab.com/cznic/sqlite>
|
||||
|
||||
Благодарим за активное участие в развитии проекта:
|
||||
- Maks1mS <maxim@slipenko.com>
|
@ -11,7 +11,7 @@
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||
<text x="33.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
|
||||
<text x="33.5" y="14">coverage</text>
|
||||
<text x="86" y="15" fill="#010101" fill-opacity=".3">19.2%</text>
|
||||
<text x="86" y="14">19.2%</text>
|
||||
<text x="86" y="15" fill="#010101" fill-opacity=".3">16.9%</text>
|
||||
<text x="86" y="14">16.9%</text>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 926 B |
18
assets/i18n-ru-badge.svg
Normal file
18
assets/i18n-ru-badge.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="129" height="20">
|
||||
<linearGradient id="smooth" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-opacity=".1"/></linearGradient>
|
||||
<mask id="round">
|
||||
<rect width="129" height="20" rx="3" fill="#fff"/>
|
||||
</mask>
|
||||
<g mask="url(#round)">
|
||||
<rect width="75" height="20" fill="#555"/>
|
||||
<rect x="75" width="64" height="20" fill="#4c1"/>
|
||||
<rect width="129" height="20" fill="url(#smooth)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||
<text x="37" y="15" fill="#010101" fill-opacity=".3">ru translate</text>
|
||||
<text x="37" y="14">ru translate</text>
|
||||
<text x="100" y="15" fill="#010101" fill-opacity=".3">100.00%</text>
|
||||
<text x="100" y="14">100.00%</text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 942 B |
189
build.go
189
build.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -23,16 +23,17 @@ import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/osutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/build"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
|
||||
)
|
||||
|
||||
func BuildCmd() *cli.Command {
|
||||
@ -46,6 +47,11 @@ func BuildCmd() *cli.Command {
|
||||
Value: "alr.sh",
|
||||
Usage: gotext.Get("Path to the build script"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "subpackage",
|
||||
Aliases: []string{"sb"},
|
||||
Usage: gotext.Get("Specify subpackage in script (for multi package script only)"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "package",
|
||||
Aliases: []string{"p"},
|
||||
@ -58,73 +64,174 @@ func BuildCmd() *cli.Command {
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
if err := utils.EnuseIsPrivilegedGroupMember(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting working directory"), err)
|
||||
}
|
||||
|
||||
wd, wdCleanup, err := Mount(wd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer wdCleanup()
|
||||
|
||||
ctx := c.Context
|
||||
|
||||
var script string
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithReposNoPull().
|
||||
WithDistroInfo().
|
||||
WithManager().
|
||||
Build()
|
||||
if err != nil {
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
// Проверяем, установлен ли флаг script (-s)
|
||||
var script string
|
||||
var packages []string
|
||||
|
||||
var res *build.BuildResult
|
||||
|
||||
var scriptArgs *build.BuildPackageFromScriptArgs
|
||||
var dbArgs *build.BuildPackageFromDbArgs
|
||||
|
||||
buildArgs := &build.BuildArgs{
|
||||
Opts: &types.BuildOpts{
|
||||
Clean: c.Bool("clean"),
|
||||
Interactive: c.Bool("interactive"),
|
||||
},
|
||||
PkgFormat_: build.GetPkgFormat(deps.Manager),
|
||||
Info: deps.Info,
|
||||
}
|
||||
|
||||
switch {
|
||||
case c.IsSet("script"):
|
||||
script = c.String("script")
|
||||
script, err = filepath.Abs(c.String("script"))
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Cannot get absolute script path"), err)
|
||||
}
|
||||
|
||||
subpackage := c.String("subpackage")
|
||||
|
||||
if subpackage != "" {
|
||||
packages = append(packages, subpackage)
|
||||
}
|
||||
|
||||
scriptArgs = &build.BuildPackageFromScriptArgs{
|
||||
Script: script,
|
||||
Packages: packages,
|
||||
BuildArgs: *buildArgs,
|
||||
}
|
||||
case c.IsSet("package"):
|
||||
// TODO: handle multiple packages
|
||||
packageInput := c.String("package")
|
||||
if filepath.Dir(packageInput) == "." {
|
||||
// Не указана директория репозитория, используем 'default' как префикс
|
||||
script = filepath.Join(config.GetPaths(ctx).RepoDir, "default", packageInput, "alr.sh")
|
||||
|
||||
arr := strings.Split(packageInput, "/")
|
||||
var packageSearch string
|
||||
if len(arr) == 2 {
|
||||
packageSearch = arr[1]
|
||||
} else {
|
||||
// Используем путь с указанным репозиторием
|
||||
script = filepath.Join(config.GetPaths(ctx).RepoDir, packageInput, "alr.sh")
|
||||
packageSearch = arr[0]
|
||||
}
|
||||
|
||||
pkgs, _, err := deps.Repos.FindPkgs(ctx, []string{packageSearch})
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("failed to find pkgs", err)
|
||||
}
|
||||
|
||||
pkg := cliutils.FlattenPkgs(ctx, pkgs, "build", c.Bool("interactive"))
|
||||
|
||||
if len(pkg) < 1 {
|
||||
return cliutils.FormatCliExit(gotext.Get("Package not found"), nil)
|
||||
}
|
||||
|
||||
if pkg[0].BasePkgName != "" {
|
||||
packages = append(packages, pkg[0].Name)
|
||||
}
|
||||
|
||||
dbArgs = &build.BuildPackageFromDbArgs{
|
||||
Package: &pkg[0],
|
||||
Packages: packages,
|
||||
BuildArgs: *buildArgs,
|
||||
}
|
||||
default:
|
||||
script = filepath.Join(config.GetPaths(ctx).RepoDir, "alr.sh")
|
||||
return cliutils.FormatCliExit(gotext.Get("Nothing to build"), nil)
|
||||
}
|
||||
|
||||
// Проверка автоматического пулла репозиториев
|
||||
if config.GetInstance(ctx).AutoPull(ctx) {
|
||||
err := repos.Pull(ctx, config.Config(ctx).Repos)
|
||||
if scriptArgs != nil {
|
||||
scriptFile := filepath.Base(scriptArgs.Script)
|
||||
newScriptDir, scriptDirCleanup, err := Mount(filepath.Dir(scriptArgs.Script))
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error pulling repositories"), "err", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
defer scriptDirCleanup()
|
||||
scriptArgs.Script = filepath.Join(newScriptDir, scriptFile)
|
||||
}
|
||||
|
||||
// Обнаружение менеджера пакетов
|
||||
mgr := manager.Detect()
|
||||
if mgr == nil {
|
||||
slog.Error(gotext.Get("Unable to detect a supported package manager on the system"))
|
||||
os.Exit(1)
|
||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Сборка пакета
|
||||
pkgPaths, _, err := build.BuildPackage(ctx, types.BuildOpts{
|
||||
Script: script,
|
||||
Manager: mgr,
|
||||
Clean: c.Bool("clean"),
|
||||
Interactive: c.Bool("interactive"),
|
||||
})
|
||||
installer, installerClose, err := build.GetSafeInstaller()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error building package"), "err", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
defer installerClose()
|
||||
|
||||
if err := utils.ExitIfCantSetNoNewPrivs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Получение текущей рабочей директории
|
||||
wd, err := os.Getwd()
|
||||
scripter, scripterClose, err := build.GetSafeScriptExecutor()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error getting working directory"), "err", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
defer scripterClose()
|
||||
|
||||
builder, err := build.NewMainBuilder(
|
||||
deps.Cfg,
|
||||
deps.Manager,
|
||||
deps.Repos,
|
||||
scripter,
|
||||
installer,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Перемещение собранных пакетов в рабочую директорию
|
||||
for _, pkgPath := range pkgPaths {
|
||||
if scriptArgs != nil {
|
||||
res, err = builder.BuildPackageFromScript(
|
||||
ctx,
|
||||
scriptArgs,
|
||||
)
|
||||
} else if dbArgs != nil {
|
||||
res, err = builder.BuildPackageFromDb(
|
||||
ctx,
|
||||
dbArgs,
|
||||
)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error building package"), err)
|
||||
}
|
||||
|
||||
for _, pkgPath := range res.PackagePaths {
|
||||
name := filepath.Base(pkgPath)
|
||||
err = osutils.Move(pkgPath, filepath.Join(wd, name))
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error moving the package"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error moving the package"), err)
|
||||
}
|
||||
}
|
||||
|
||||
slog.Info(gotext.Get("Done"))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
72
e2e-tests/addrepo_test.go
Normal file
72
e2e-tests/addrepo_test.go
Normal file
@ -0,0 +1,72 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestE2EAlrAddRepo(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"add-repo-remove-repo",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
err := r.Exec(e2e.NewCommand(
|
||||
"sudo",
|
||||
"alr",
|
||||
"addrepo",
|
||||
"--name",
|
||||
"alr-repo",
|
||||
"--url",
|
||||
"https://gitea.plemya-x.ru/Plemya-x/alr-repo.git",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"bash",
|
||||
"-c",
|
||||
"cat /etc/alr/alr.toml",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sudo",
|
||||
"alr",
|
||||
"removerepo",
|
||||
"--name",
|
||||
"alr-repo",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"bash",
|
||||
"-c",
|
||||
"cat /etc/alr/alr.toml",
|
||||
), e2e.WithExecOptionStdout(&buf))
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, buf.String(), "rootCmd")
|
||||
},
|
||||
)
|
||||
}
|
36
e2e-tests/bash_completion_test.go
Normal file
36
e2e-tests/bash_completion_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EBashCompletion(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"bash-completion",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
execShouldNoError(t, r, "alr", "install", "--generate-bash-completion")
|
||||
},
|
||||
)
|
||||
}
|
202
e2e-tests/common_test.go
Normal file
202
e2e-tests/common_test.go
Normal file
@ -0,0 +1,202 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
expect "github.com/tailscale/goexpect"
|
||||
)
|
||||
|
||||
// DebugWriter оборачивает io.Writer и логирует все записываемые данные.
|
||||
type DebugWriter struct {
|
||||
prefix string
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
func (d *DebugWriter) Write(p []byte) (n int, err error) {
|
||||
log.Printf("%s: Writing data: %q", d.prefix, p) // Логируем данные
|
||||
return d.writer.Write(p)
|
||||
}
|
||||
|
||||
// DebugReader оборачивает io.Reader и логирует все читаемые данные.
|
||||
type DebugReader struct {
|
||||
prefix string
|
||||
reader io.Reader
|
||||
}
|
||||
|
||||
func (d *DebugReader) Read(p []byte) (n int, err error) {
|
||||
n, err = d.reader.Read(p)
|
||||
if n > 0 {
|
||||
log.Printf("%s: Read data: %q", d.prefix, p[:n]) // Логируем данные
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func e2eSpawn(runnable e2e.Runnable, command e2e.Command, timeout time.Duration, opts ...expect.Option) (expect.Expecter, <-chan error, error, *io.PipeWriter) {
|
||||
resCh := make(chan error)
|
||||
|
||||
// Создаем pipe для stdin и stdout
|
||||
stdinReader, stdinWriter := io.Pipe()
|
||||
stdoutReader, stdoutWriter := io.Pipe()
|
||||
|
||||
debugStdinReader := &DebugReader{prefix: "STDIN", reader: stdinReader}
|
||||
debugStdoutWriter := &DebugWriter{prefix: "STDOUT", writer: stdoutWriter}
|
||||
|
||||
go func() {
|
||||
err := runnable.Exec(
|
||||
command,
|
||||
e2e.WithExecOptionStdout(debugStdoutWriter),
|
||||
e2e.WithExecOptionStdin(debugStdinReader),
|
||||
e2e.WithExecOptionStderr(debugStdoutWriter),
|
||||
)
|
||||
|
||||
resCh <- err
|
||||
}()
|
||||
|
||||
exp, chnErr, err := expect.SpawnGeneric(&expect.GenOptions{
|
||||
In: stdinWriter,
|
||||
Out: stdoutReader,
|
||||
Wait: func() error {
|
||||
return <-resCh
|
||||
},
|
||||
Close: func() error {
|
||||
stdinWriter.Close()
|
||||
stdoutReader.Close()
|
||||
return nil
|
||||
},
|
||||
Check: func() bool { return true },
|
||||
}, timeout, expect.Verbose(true), expect.VerboseWriter(os.Stdout))
|
||||
|
||||
return exp, chnErr, err, stdinWriter
|
||||
}
|
||||
|
||||
var ALL_SYSTEMS []string = []string{
|
||||
"ubuntu-24.04",
|
||||
"alt-sisyphus",
|
||||
"fedora-41",
|
||||
// "archlinux",
|
||||
// "alpine",
|
||||
// "opensuse-leap",
|
||||
// "redos-8",
|
||||
}
|
||||
|
||||
var AUTOREQ_AUTOPROV_SYSTEMS []string = []string{
|
||||
// "alt-sisyphus",
|
||||
"fedora-41",
|
||||
}
|
||||
|
||||
var RPM_SYSTEMS []string = []string{
|
||||
"fedora-41",
|
||||
}
|
||||
|
||||
var COMMON_SYSTEMS []string = []string{
|
||||
"ubuntu-24.04",
|
||||
}
|
||||
|
||||
func dockerMultipleRun(t *testing.T, name string, ids []string, f func(t *testing.T, runnable e2e.Runnable)) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
for _, id := range ids {
|
||||
t.Run(id, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dockerName := fmt.Sprintf("alr-test-%s-%s", name, id)
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(dockerName))
|
||||
hashSum := hash.Sum(nil)
|
||||
hashString := hex.EncodeToString(hashSum)
|
||||
truncatedHash := hashString[:8]
|
||||
e, err := e2e.New(e2e.WithVerbose(), e2e.WithName(fmt.Sprintf("alr-%s", truncatedHash)))
|
||||
assert.NoError(t, err)
|
||||
t.Cleanup(e.Close)
|
||||
imageId := fmt.Sprintf("ghcr.io/maks1ms/alr-e2e-test-image-%s", id)
|
||||
runnable := e.Runnable(dockerName).Init(
|
||||
e2e.StartOptions{
|
||||
Image: imageId,
|
||||
Volumes: []string{
|
||||
"./alr:/tmp/alr",
|
||||
},
|
||||
Privileged: true,
|
||||
},
|
||||
)
|
||||
assert.NoError(t, e2e.StartAndWaitReady(runnable))
|
||||
err = runnable.Exec(e2e.NewCommand("/bin/alr-test-setup", "alr-install"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = runnable.Exec(e2e.NewCommand("/bin/alr-test-setup", "passwordless-sudo-setup"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f(t, runnable)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func execShouldNoError(t *testing.T, r e2e.Runnable, cmd string, args ...string) {
|
||||
assert.NoError(t, r.Exec(e2e.NewCommand(cmd, args...)))
|
||||
}
|
||||
|
||||
func execShouldError(t *testing.T, r e2e.Runnable, cmd string, args ...string) {
|
||||
assert.Error(t, r.Exec(e2e.NewCommand(cmd, args...)))
|
||||
}
|
||||
|
||||
func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expects []expect.Batcher) {
|
||||
exp, _, err, _ := e2eSpawn(
|
||||
r,
|
||||
e2e.NewCommand("/bin/bash"), 25*time.Second,
|
||||
expect.Verbose(true),
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
_, err = exp.ExpectBatch(
|
||||
expects,
|
||||
timeout,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
const REPO_NAME_FOR_E2E_TESTS = "alr-repo"
|
||||
const REPO_URL_FOR_E2E_TESTS = "https://gitea.plemya-x.ru/Maks1mS/repo-for-tests.git"
|
||||
|
||||
func defaultPrepare(t *testing.T, r e2e.Runnable) {
|
||||
execShouldNoError(t, r,
|
||||
"sudo",
|
||||
"alr",
|
||||
"repo",
|
||||
"add",
|
||||
REPO_NAME_FOR_E2E_TESTS,
|
||||
REPO_URL_FOR_E2E_TESTS,
|
||||
)
|
||||
|
||||
execShouldNoError(t, r,
|
||||
"sudo",
|
||||
"alr",
|
||||
"ref",
|
||||
)
|
||||
}
|
43
e2e-tests/fix_test.go
Normal file
43
e2e-tests/fix_test.go
Normal file
@ -0,0 +1,43 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
expect "github.com/tailscale/goexpect"
|
||||
)
|
||||
|
||||
func TestE2EAlrFix(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"run-fix",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
runTestCommands(t, r, time.Second*30, []expect.Batcher{
|
||||
&expect.BSnd{S: "alr fix\n"},
|
||||
&expect.BExp{R: `--> Done`},
|
||||
&expect.BSnd{S: "echo $?\n"},
|
||||
&expect.BExp{R: `^0\n$`},
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
38
e2e-tests/group_and_summary_field_test.go
Normal file
38
e2e-tests/group_and_summary_field_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EGroupAndSummaryField(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"group-and-summary-field",
|
||||
RPM_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group}}\" | grep ^System/Base$")
|
||||
execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary}}\" | grep \"^Custom summary$\"")
|
||||
},
|
||||
)
|
||||
}
|
40
e2e-tests/issue_32_interactive_test.go
Normal file
40
e2e-tests/issue_32_interactive_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue32Interactive(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-32-interactive",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
execShouldNoError(t, r, "alr", "--interactive=false", "remove", "ca-certificates")
|
||||
execShouldNoError(t, r, "sudo", "alr", "--interactive=false", "remove", "openssl")
|
||||
execShouldNoError(t, r, "alr", "fix")
|
||||
execShouldNoError(t, r, "sudo", "apt-get", "update")
|
||||
execShouldNoError(t, r, "sudo", "alr", "--interactive=false", "install", "ca-certificates")
|
||||
},
|
||||
)
|
||||
}
|
40
e2e-tests/issue_41_autoreq_skiplist_test.go
Normal file
40
e2e-tests/issue_41_autoreq_skiplist_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue41AutoreqSkiplist(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-41-autoreq-skiplist",
|
||||
AUTOREQ_AUTOPROV_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "alr", "build", "-p", "alr-repo/test-autoreq-autoprov")
|
||||
execShouldNoError(t, r, "sh", "-c", "rpm -qp --requires *.rpm | grep \"^/bin/sh$\"")
|
||||
execShouldError(t, r, "sh", "-c", "rpm -qp --requires *.rpm | grep \"^/bin/bash$\"")
|
||||
execShouldError(t, r, "sh", "-c", "rpm -qp --requires *.rpm | grep \"^/bin/zsh$\"")
|
||||
},
|
||||
)
|
||||
}
|
39
e2e-tests/issue_50_install_multiple_test.go
Normal file
39
e2e-tests/issue_50_install_multiple_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue50InstallMultiple(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-50-install-multiple",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sudo", "alr", "in", "foo-pkg", "bar-pkg")
|
||||
execShouldNoError(t, r, "cat", "/opt/foo")
|
||||
execShouldNoError(t, r, "cat", "/opt/bar")
|
||||
},
|
||||
)
|
||||
}
|
37
e2e-tests/issue_53_lc_all_c_info_test.go
Normal file
37
e2e-tests/issue_53_lc_all_c_info_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue53LcAllCInfo(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-53-lc-all-c-info",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "bash", "-c", "LANG=C alr info foo-pkg")
|
||||
},
|
||||
)
|
||||
}
|
40
e2e-tests/issue_59_rm_completion_test.go
Normal file
40
e2e-tests/issue_59_rm_completion_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue59RmCompletion(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-59-rm-completion",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sudo", "alr", "in", "foo-pkg", "bar-pkg")
|
||||
execShouldNoError(t, r, "sh", "-c", "alr rm --generate-bash-completion | grep ^foo-pkg$")
|
||||
execShouldNoError(t, r, "sh", "-c", "alr rm --generate-bash-completion | grep ^bar-pkg$")
|
||||
execShouldError(t, r, "sh", "-c", "alr rm --generate-bash-completion | grep ^test-autoreq-autoprov$")
|
||||
},
|
||||
)
|
||||
}
|
37
e2e-tests/issue_72_install_with_deps_test.go
Normal file
37
e2e-tests/issue_72_install_with_deps_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue72InstallWithDeps(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-72-install-with-deps",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sudo", "alr", "in", "test-app-with-lib")
|
||||
},
|
||||
)
|
||||
}
|
43
e2e-tests/issue_74_upgradable_test.go
Normal file
43
e2e-tests/issue_74_upgradable_test.go
Normal file
@ -0,0 +1,43 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue74Upgradable(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-74-upgradable",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sudo", "alr", "repo", "set-ref", "alr-repo", "bd26236cd7")
|
||||
execShouldNoError(t, r, "alr", "ref")
|
||||
execShouldNoError(t, r, "sudo", "alr", "in", "bar-pkg")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 0 || exit 1")
|
||||
execShouldNoError(t, r, "sudo", "alr", "repo", "set-ref", "alr-repo", "d9a3541561")
|
||||
execShouldNoError(t, r, "sudo", "alr", "ref")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 1 || exit 1")
|
||||
},
|
||||
)
|
||||
}
|
38
e2e-tests/issue_75_ref_specify_test.go
Normal file
38
e2e-tests/issue_75_ref_specify_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue75InstallWithDeps(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-75-ref-specify",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sudo", "alr", "repo", "set-ref", "alr-repo", "bd26236cd7")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list | wc -l) -eq 2 || exit 1")
|
||||
},
|
||||
)
|
||||
}
|
38
e2e-tests/issue_81_multiple_packages_test.go
Normal file
38
e2e-tests/issue_81_multiple_packages_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue81MultiplePackages(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-81-multiple-packages",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sudo", "alr", "in", "first-package-with-dashes")
|
||||
execShouldNoError(t, r, "cat", "/opt/first-package")
|
||||
},
|
||||
)
|
||||
}
|
40
e2e-tests/issue_91_set_repo_ref_test.go
Normal file
40
e2e-tests/issue_91_set_repo_ref_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EIssue91MultiplePackages(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-91-set-repo-ref",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldError(t, r, "sudo", "alr", "repo", "set-ref")
|
||||
execShouldError(t, r, "sudo", "alr", "repo", "set-ref", "alr-repo")
|
||||
execShouldNoError(t, r, "sudo", "alr", "repo", "set-ref", "alr-repo", "bd26236cd7")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list | wc -l) -eq 2 || exit 1")
|
||||
},
|
||||
)
|
||||
}
|
44
e2e-tests/version_test.go
Normal file
44
e2e-tests/version_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
|
||||
expect "github.com/tailscale/goexpect"
|
||||
)
|
||||
|
||||
func TestE2EAlrVersion(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"check-version",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
runTestCommands(t, r, time.Second*10, []expect.Batcher{
|
||||
&expect.BSnd{S: "alr version\n"},
|
||||
&expect.BExp{R: `^v\d+\.\d+\.\d+(?:-\d+-g[a-f0-9]+)?\n$`},
|
||||
&expect.BSnd{S: "echo $?\n"},
|
||||
&expect.BExp{R: `^0\n$`},
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
68
fix.go
68
fix.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -22,13 +22,14 @@ package main
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
)
|
||||
|
||||
func FixCmd() *cli.Command {
|
||||
@ -36,32 +37,63 @@ func FixCmd() *cli.Command {
|
||||
Name: "fix",
|
||||
Usage: gotext.Get("Attempt to fix problems with ALR"),
|
||||
Action: func(c *cli.Context) error {
|
||||
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := c.Context
|
||||
|
||||
db.Close()
|
||||
paths := config.GetPaths(ctx)
|
||||
|
||||
slog.Info(gotext.Get("Removing cache directory"))
|
||||
|
||||
err := os.RemoveAll(paths.CacheDir)
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
Build()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to remove cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
cfg := deps.Cfg
|
||||
|
||||
paths := cfg.GetPaths()
|
||||
|
||||
slog.Info(gotext.Get("Clearing cache directory"))
|
||||
// Remove all nested directories of paths.CacheDir
|
||||
|
||||
dir, err := os.Open(paths.CacheDir)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Unable to open cache directory"), err)
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
entries, err := dir.Readdirnames(-1)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Unable to read cache directory contents"), err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
err = os.RemoveAll(filepath.Join(paths.CacheDir, entry))
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Unable to remove cache item (%s)", entry), err)
|
||||
}
|
||||
}
|
||||
|
||||
slog.Info(gotext.Get("Rebuilding cache"))
|
||||
|
||||
err = os.MkdirAll(paths.CacheDir, 0o755)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to create new cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Unable to create new cache directory"), err)
|
||||
}
|
||||
|
||||
err = repos.Pull(ctx, config.Config(ctx).Repos)
|
||||
deps, err = appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithReposForcePull().
|
||||
Build()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error pulling repos"), "err", err)
|
||||
os.Exit(1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
slog.Info(gotext.Get("Done"))
|
||||
|
||||
|
4
gen.go
4
gen.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
52
go.mod
52
go.mod
@ -1,22 +1,27 @@
|
||||
module gitea.plemya-x.ru/Plemya-x/ALR
|
||||
|
||||
go 1.22
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.5
|
||||
toolchain go1.24.2
|
||||
|
||||
require (
|
||||
gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.1
|
||||
gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.2-0.20250408104831-427aaa7713c3
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||
github.com/PuerkitoBio/purell v1.2.0
|
||||
github.com/alecthomas/assert/v2 v2.2.1
|
||||
github.com/alecthomas/chroma/v2 v2.9.1
|
||||
github.com/caarlos0/env v3.5.0+incompatible
|
||||
github.com/charmbracelet/bubbles v0.20.0
|
||||
github.com/charmbracelet/bubbletea v1.2.4
|
||||
github.com/charmbracelet/lipgloss v1.0.0
|
||||
github.com/charmbracelet/log v0.4.0
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/efficientgo/e2e v0.14.1-0.20240418111536-97db25a0c6c0
|
||||
github.com/go-git/go-billy/v5 v5.6.0
|
||||
github.com/go-git/go-git/v5 v5.13.0
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/goreleaser/nfpm/v2 v2.41.0
|
||||
github.com/hashicorp/go-hclog v0.14.1
|
||||
github.com/hashicorp/go-plugin v1.6.3
|
||||
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08
|
||||
github.com/jmoiron/sqlx v1.3.5
|
||||
github.com/leonelquinteros/gotext v1.7.0
|
||||
@ -26,13 +31,14 @@ require (
|
||||
github.com/muesli/reflow v0.3.0
|
||||
github.com/pelletier/go-toml/v2 v2.1.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41
|
||||
github.com/urfave/cli/v2 v2.25.7
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5
|
||||
go.elara.ws/vercmp v0.0.0-20230622214216-0b2b067575c4
|
||||
golang.org/x/crypto v0.27.0
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb
|
||||
golang.org/x/sys v0.29.0
|
||||
golang.org/x/text v0.21.0
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/text v0.23.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.25.0
|
||||
mvdan.cc/sh/v3 v3.10.0
|
||||
@ -45,7 +51,8 @@ require (
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.1.3 // indirect
|
||||
github.com/alecthomas/repr v0.2.0 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect
|
||||
@ -59,24 +66,31 @@ require (
|
||||
github.com/cloudflare/circl v1.3.8 // indirect
|
||||
github.com/connesc/cipherio v0.2.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/creack/pty v1.1.24 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/efficientgo/core v1.0.0-rc.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fatih/color v1.7.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f // indirect
|
||||
github.com/google/rpmpack v0.6.1-0.20240329070804-c2247cbb881a // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/goreleaser/chglog v0.6.1 // indirect
|
||||
github.com/goreleaser/fileglob v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/hexops/gotextdiff v1.0.3 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
@ -95,6 +109,7 @@ require (
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
|
||||
github.com/oklog/run v1.0.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.15 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
@ -103,7 +118,7 @@ require (
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
@ -112,11 +127,14 @@ require (
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect
|
||||
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/net v0.26.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/term v0.28.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/term v0.30.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/grpc v1.58.3 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.40.0 // indirect
|
||||
|
153
go.sum
153
go.sum
@ -17,8 +17,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.1 h1:c7F4OsyQbiVpSOrYGMrNsRL37BwoOfrgoKxAwULBKZo=
|
||||
gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.1/go.mod h1:iKQM6uttMJgE5CFrPw6SQqAV7TKtlJNICRAie/dTciw=
|
||||
gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.2-0.20250408104831-427aaa7713c3 h1:56BjRJJ2Sv50DfSvNUydUMJwwFuiBMWC1uYtH2GYjk8=
|
||||
gitea.plemya-x.ru/Plemya-x/fakeroot v0.0.2-0.20250408104831-427aaa7713c3/go.mod h1:iKQM6uttMJgE5CFrPw6SQqAV7TKtlJNICRAie/dTciw=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
||||
github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w=
|
||||
@ -39,8 +39,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
|
||||
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
|
||||
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k=
|
||||
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw=
|
||||
github.com/ProtonMail/gopenpgp/v2 v2.7.1 h1:Awsg7MPc2gD3I7IFac2qE3Gdls0lZW8SzrFZ3k1oz0s=
|
||||
@ -61,6 +61,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/bodgit/plumbing v1.2.0 h1:gg4haxoKphLjml+tgnecR4yLBV5zo4HAZGCtAh3xCzM=
|
||||
@ -69,12 +71,17 @@ github.com/bodgit/sevenzip v1.3.0 h1:1ljgELgtHqvgIp8W8kgeEGHIWP4ch3xGI8uOBZgLVKY
|
||||
github.com/bodgit/sevenzip v1.3.0/go.mod h1:omwNcgZTEooWM8gA/IJ2Nk/+ZQ94+GsytRzOJJ8FBlM=
|
||||
github.com/bodgit/windows v1.0.0 h1:rLQ/XjsleZvx4fR1tB/UxQrK+SJ2OFHzfPjLWWOhDIA=
|
||||
github.com/bodgit/windows v1.0.0/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
|
||||
github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8=
|
||||
github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs=
|
||||
github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y=
|
||||
github.com/caarlos0/testfs v0.4.4 h1:3PHvzHi5Lt+g332CiShwS8ogTgS3HjrmzZxCm6JCDr8=
|
||||
github.com/caarlos0/testfs v0.4.4/go.mod h1:bRN55zgG4XCUVVHZCeU+/Tz1Q6AxEJOEJTliBy+1DMk=
|
||||
github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM=
|
||||
github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||
github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
|
||||
github.com/charmbracelet/bubbletea v1.2.4 h1:KN8aCViA0eps9SCOThb2/XPIlea3ANJLUkv3KnQRNCE=
|
||||
@ -93,7 +100,6 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
|
||||
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/connesc/cipherio v0.2.1 h1:FGtpTPMbKNNWByNrr9aEBtaJtXjqOzkIXNYJp6OEycw=
|
||||
@ -101,10 +107,10 @@ github.com/connesc/cipherio v0.2.1/go.mod h1:ukY0MWJDFnJEbXMQtOcn2VmTpRfzcTz4OoV
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0=
|
||||
github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
|
||||
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -115,26 +121,32 @@ github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5Jflh
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/efficientgo/core v1.0.0-rc.0 h1:jJoA0N+C4/knWYVZ6GrdHOtDyrg8Y/TR4vFpTaqTsqs=
|
||||
github.com/efficientgo/core v1.0.0-rc.0/go.mod h1:kQa0V74HNYMfuJH6jiPiwNdpWXl4xd/K4tzlrcvYDQI=
|
||||
github.com/efficientgo/e2e v0.14.1-0.20240418111536-97db25a0c6c0 h1:C/FNIs+MtAJgQYLJ9FX/ACFYyDRuLYoXTmueErrOJyA=
|
||||
github.com/efficientgo/e2e v0.14.1-0.20240418111536-97db25a0c6c0/go.mod h1:plsKU0YHE9uX+7utvr7SiDtVBSHJyEfHRO4UnUgDmts=
|
||||
github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug=
|
||||
github.com/elazarl/goproxy v1.2.1/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
|
||||
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
|
||||
github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E=
|
||||
github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
@ -161,6 +173,9 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
@ -169,8 +184,11 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@ -197,10 +215,16 @@ github.com/goreleaser/nfpm/v2 v2.41.0 h1:JyMzS/EwqaWbFs+7Z9oZ4Hkk4or00gUTqwm9Dgr
|
||||
github.com/goreleaser/nfpm/v2 v2.41.0/go.mod h1:VPc5kF5OgfA+BosV/A2aB+Vg34honjWvp0Vt8ogsSi0=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg=
|
||||
github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
|
||||
@ -215,8 +239,12 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 h1:wMeVzrPO3mfHIWLZtDcSaGAe2I4PW9B/P5nMkRSwCAc=
|
||||
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
|
||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
@ -248,9 +276,11 @@ github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
@ -262,6 +292,8 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mholt/archiver/v4 v4.0.0-alpha.8 h1:tRGQuDVPh66WCOelqe6LIGh0gwmfwxUrSSDunscGsRM=
|
||||
@ -282,10 +314,14 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q0rDaRO0MPaOk=
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
||||
@ -296,7 +332,15 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.36.0 h1:78hJTing+BLYLjhXE+Z2BubeEymH5Lr0/Mt8FKkxxYo=
|
||||
github.com/prometheus/common v0.36.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
@ -317,8 +361,8 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG
|
||||
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
|
||||
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
|
||||
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
|
||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||
@ -338,6 +382,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41 h1:/V2rCMMWcsjYaYO2MeovLw+ClP63OtXgCF2Y1eb8+Ns=
|
||||
github.com/tailscale/goexpect v0.0.0-20210902213824-6e8c725cea41/go.mod h1:/roCdA6gg6lQyw/Oz6gIIGu3ggJKYhF+WC/AQReE5XQ=
|
||||
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||
github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
@ -373,10 +419,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -385,8 +429,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -405,9 +449,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -426,15 +469,15 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -442,9 +485,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -455,6 +497,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -470,18 +513,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -490,10 +529,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -521,9 +558,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@ -540,6 +576,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
@ -553,6 +591,8 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@ -560,6 +600,12 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
|
||||
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -570,6 +616,7 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
13
helper.go
13
helper.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -30,6 +30,7 @@ import (
|
||||
"mvdan.cc/sh/v3/expand"
|
||||
"mvdan.cc/sh/v3/interp"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
@ -71,19 +72,17 @@ func HelperCmd() *cli.Command {
|
||||
helper, ok := helpers.Helpers[c.Args().First()]
|
||||
if !ok {
|
||||
slog.Error(gotext.Get("No such helper command"), "name", c.Args().First())
|
||||
os.Exit(1)
|
||||
return cli.Exit(gotext.Get("No such helper command"), 1)
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error getting working directory"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting working directory"), err)
|
||||
}
|
||||
|
||||
info, err := distro.ParseOSRelease(ctx)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error getting working directory"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error parsing os-release file"), err)
|
||||
}
|
||||
|
||||
hc := interp.HandlerContext{
|
||||
|
107
info.go
107
info.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -21,19 +21,19 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/jeandeaual/go-locale"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
|
||||
)
|
||||
|
||||
func InfoCmd() *cli.Command {
|
||||
@ -47,40 +47,71 @@ func InfoCmd() *cli.Command {
|
||||
Usage: gotext.Get("Show all information, not just for the current distro"),
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
ctx := c.Context
|
||||
|
||||
cfg := config.New()
|
||||
db := db.New(cfg)
|
||||
err := db.Init(ctx)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error initialization database"), "err", err)
|
||||
os.Exit(1)
|
||||
BashComplete: cliutils.BashCompleteWithError(func(c *cli.Context) error {
|
||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := c.Context
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
result, err := deps.DB.GetPkgs(c.Context, "true")
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err)
|
||||
}
|
||||
defer result.Close()
|
||||
|
||||
for result.Next() {
|
||||
var pkg database.Package
|
||||
err = result.StructScan(&pkg)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error iterating over packages"), err)
|
||||
}
|
||||
|
||||
fmt.Println(pkg.Name)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
Action: func(c *cli.Context) error {
|
||||
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
||||
return err
|
||||
}
|
||||
rs := repos.New(cfg, db)
|
||||
|
||||
args := c.Args()
|
||||
if args.Len() < 1 {
|
||||
slog.Error(gotext.Get("Command info expected at least 1 argument, got %d", args.Len()))
|
||||
os.Exit(1)
|
||||
return cli.Exit(gotext.Get("Command info expected at least 1 argument, got %d", args.Len()), 1)
|
||||
}
|
||||
|
||||
if cfg.AutoPull(ctx) {
|
||||
err := rs.Pull(ctx, cfg.Repos(ctx))
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error pulling repos"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ctx := c.Context
|
||||
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithRepos().
|
||||
Build()
|
||||
if err != nil {
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
rs := deps.Repos
|
||||
|
||||
found, _, err := rs.FindPkgs(ctx, args.Slice())
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error finding packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error finding packages"), err)
|
||||
}
|
||||
|
||||
if len(found) == 0 {
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Package not found"), err)
|
||||
}
|
||||
|
||||
pkgs := cliutils.FlattenPkgs(ctx, found, "show", c.Bool("interactive"))
|
||||
@ -88,20 +119,26 @@ func InfoCmd() *cli.Command {
|
||||
var names []string
|
||||
all := c.Bool("all")
|
||||
|
||||
systemLang, err := locale.GetLanguage()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Can't detect system language"), err)
|
||||
}
|
||||
if systemLang == "" {
|
||||
systemLang = "en"
|
||||
}
|
||||
|
||||
if !all {
|
||||
info, err := distro.ParseOSRelease(ctx)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error parsing os-release file"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error parsing os-release file"), err)
|
||||
}
|
||||
names, err = overrides.Resolve(
|
||||
info,
|
||||
overrides.DefaultOpts.
|
||||
WithLanguages([]string{config.SystemLang()}),
|
||||
WithLanguages([]string{systemLang}),
|
||||
)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error resolving overrides"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error resolving overrides"), err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,14 +146,12 @@ func InfoCmd() *cli.Command {
|
||||
if !all {
|
||||
err = yaml.NewEncoder(os.Stdout).Encode(overrides.ResolvePackage(&pkg, names))
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error encoding script variables"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error encoding script variables"), err)
|
||||
}
|
||||
} else {
|
||||
err = yaml.NewEncoder(os.Stdout).Encode(pkg)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error encoding script variables"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error encoding script variables"), err)
|
||||
}
|
||||
}
|
||||
|
||||
|
217
install.go
217
install.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -21,19 +21,17 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/build"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
|
||||
)
|
||||
|
||||
func InstallCmd() *cli.Command {
|
||||
@ -45,65 +43,113 @@ func InstallCmd() *cli.Command {
|
||||
&cli.BoolFlag{
|
||||
Name: "clean",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Build package from scratch even if there's an already built package available",
|
||||
Usage: gotext.Get("Build package from scratch even if there's an already built package available"),
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
ctx := c.Context
|
||||
|
||||
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if args.Len() < 1 {
|
||||
slog.Error(gotext.Get("Command install expected at least 1 argument, got %d", args.Len()))
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Command install expected at least 1 argument, got %d", args.Len()), nil)
|
||||
}
|
||||
|
||||
mgr := manager.Detect()
|
||||
if mgr == nil {
|
||||
slog.Error(gotext.Get("Unable to detect a supported package manager on the system"))
|
||||
os.Exit(1)
|
||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.GetInstance(ctx).AutoPull(ctx) {
|
||||
err := repos.Pull(ctx, config.Config(ctx).Repos)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error pulling repositories"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
found, notFound, err := repos.FindPkgs(ctx, args.Slice())
|
||||
installer, installerClose, err := build.GetSafeInstaller()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error finding packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
defer installerClose()
|
||||
|
||||
if err := utils.ExitIfCantSetNoNewPrivs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scripter, scripterClose, err := build.GetSafeScriptExecutor()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer scripterClose()
|
||||
|
||||
ctx := c.Context
|
||||
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithRepos().
|
||||
WithDistroInfo().
|
||||
WithManager().
|
||||
Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
builder, err := build.NewMainBuilder(
|
||||
deps.Cfg,
|
||||
deps.Manager,
|
||||
deps.Repos,
|
||||
scripter,
|
||||
installer,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = builder.InstallPkgs(
|
||||
ctx,
|
||||
&build.BuildArgs{
|
||||
Opts: &types.BuildOpts{
|
||||
Clean: c.Bool("clean"),
|
||||
Interactive: c.Bool("interactive"),
|
||||
},
|
||||
Info: deps.Info,
|
||||
PkgFormat_: build.GetPkgFormat(deps.Manager),
|
||||
},
|
||||
args.Slice(),
|
||||
)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error when installing the package"), err)
|
||||
}
|
||||
|
||||
pkgs := cliutils.FlattenPkgs(ctx, found, "install", c.Bool("interactive"))
|
||||
build.InstallPkgs(ctx, pkgs, notFound, types.BuildOpts{
|
||||
Manager: mgr,
|
||||
Clean: c.Bool("clean"),
|
||||
Interactive: c.Bool("interactive"),
|
||||
})
|
||||
return nil
|
||||
},
|
||||
BashComplete: func(c *cli.Context) {
|
||||
result, err := db.GetPkgs(c.Context, "true")
|
||||
}),
|
||||
BashComplete: cliutils.BashCompleteWithError(func(c *cli.Context) error {
|
||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := c.Context
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
Build()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error getting packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
result, err := deps.DB.GetPkgs(c.Context, "true")
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err)
|
||||
}
|
||||
defer result.Close()
|
||||
|
||||
for result.Next() {
|
||||
var pkg db.Package
|
||||
var pkg database.Package
|
||||
err = result.StructScan(&pkg)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error iterating over packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error iterating over packages"), err)
|
||||
}
|
||||
|
||||
fmt.Println(pkg.Name)
|
||||
}
|
||||
},
|
||||
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,26 +158,79 @@ func RemoveCmd() *cli.Command {
|
||||
Name: "remove",
|
||||
Usage: gotext.Get("Remove an installed package"),
|
||||
Aliases: []string{"rm"},
|
||||
Action: func(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if args.Len() < 1 {
|
||||
slog.Error(gotext.Get("Command remove expected at least 1 argument, got %d", args.Len()))
|
||||
os.Exit(1)
|
||||
}
|
||||
BashComplete: cliutils.BashCompleteWithError(func(c *cli.Context) error {
|
||||
ctx := c.Context
|
||||
|
||||
mgr := manager.Detect()
|
||||
if mgr == nil {
|
||||
slog.Error(gotext.Get("Unable to detect a supported package manager on the system"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err := mgr.Remove(nil, c.Args().Slice()...)
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithManager().
|
||||
Build()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error removing packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
installedAlrPackages := map[string]string{}
|
||||
installed, err := deps.Manager.ListInstalled(&manager.Opts{})
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error listing installed packages"), err)
|
||||
}
|
||||
for pkgName, version := range installed {
|
||||
matches := build.RegexpALRPackageName.FindStringSubmatch(pkgName)
|
||||
if matches != nil {
|
||||
packageName := matches[build.RegexpALRPackageName.SubexpIndex("package")]
|
||||
repoName := matches[build.RegexpALRPackageName.SubexpIndex("repo")]
|
||||
installedAlrPackages[fmt.Sprintf("%s/%s", repoName, packageName)] = version
|
||||
}
|
||||
}
|
||||
|
||||
result, err := deps.DB.GetPkgs(c.Context, "true")
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err)
|
||||
}
|
||||
defer result.Close()
|
||||
|
||||
for result.Next() {
|
||||
var pkg database.Package
|
||||
err = result.StructScan(&pkg)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error iterating over packages"), err)
|
||||
}
|
||||
|
||||
_, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println(pkg.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}),
|
||||
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if args.Len() < 1 {
|
||||
return cliutils.FormatCliExit(gotext.Get("Command remove expected at least 1 argument, got %d", args.Len()), nil)
|
||||
}
|
||||
|
||||
deps, err := appbuilder.
|
||||
New(c.Context).
|
||||
WithManager().
|
||||
Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
if err := deps.Manager.Remove(&manager.Opts{
|
||||
NoConfirm: !c.Bool("interactive"),
|
||||
}, c.Args().Slice()...); err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error removing packages"), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
280
internal.go
Normal file
280
internal.go
Normal file
@ -0,0 +1,280 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/constants"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/build"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
)
|
||||
|
||||
func InternalBuildCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "_internal-safe-script-executor",
|
||||
HideHelp: true,
|
||||
Hidden: true,
|
||||
Action: func(c *cli.Context) error {
|
||||
logger.SetupForGoPlugin()
|
||||
|
||||
slog.Debug("start _internal-safe-script-executor", "uid", syscall.Getuid(), "gid", syscall.Getgid())
|
||||
|
||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg := config.New()
|
||||
err := cfg.Load()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error loading config"), err)
|
||||
}
|
||||
|
||||
logger := hclog.New(&hclog.LoggerOptions{
|
||||
Name: "plugin",
|
||||
Output: os.Stderr,
|
||||
Level: hclog.Debug,
|
||||
JSONFormat: false,
|
||||
DisableTime: true,
|
||||
})
|
||||
|
||||
plugin.Serve(&plugin.ServeConfig{
|
||||
HandshakeConfig: build.HandshakeConfig,
|
||||
Plugins: map[string]plugin.Plugin{
|
||||
"script-executor": &build.ScriptExecutorPlugin{
|
||||
Impl: build.NewLocalScriptExecutor(cfg),
|
||||
},
|
||||
},
|
||||
Logger: logger,
|
||||
})
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func InternalInstallCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "_internal-installer",
|
||||
HideHelp: true,
|
||||
Hidden: true,
|
||||
Action: func(c *cli.Context) error {
|
||||
logger.SetupForGoPlugin()
|
||||
|
||||
if err := utils.EnsureIsAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Before escalating the rights, we made sure that
|
||||
// this is an ALR user, so it looks safe.
|
||||
err := utils.EscalateToRootUid()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("cannot escalate to root", err)
|
||||
}
|
||||
|
||||
deps, err := appbuilder.
|
||||
New(c.Context).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithReposNoPull().
|
||||
Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
logger := hclog.New(&hclog.LoggerOptions{
|
||||
Name: "plugin",
|
||||
Output: os.Stderr,
|
||||
Level: hclog.Trace,
|
||||
JSONFormat: true,
|
||||
DisableTime: true,
|
||||
})
|
||||
|
||||
plugin.Serve(&plugin.ServeConfig{
|
||||
HandshakeConfig: build.HandshakeConfig,
|
||||
Plugins: map[string]plugin.Plugin{
|
||||
"installer": &build.InstallerPlugin{
|
||||
Impl: build.NewInstaller(
|
||||
manager.Detect(),
|
||||
),
|
||||
},
|
||||
},
|
||||
Logger: logger,
|
||||
})
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func Mount(target string) (string, func(), error) {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get executable path: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(exe, "_internal-temporary-mount", target)
|
||||
|
||||
stdoutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get stdout pipe: %w", err)
|
||||
}
|
||||
|
||||
stdinPipe, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get stdin pipe: %w", err)
|
||||
}
|
||||
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return "", nil, fmt.Errorf("failed to start mount: %w", err)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(stdoutPipe)
|
||||
var mountPath string
|
||||
if scanner.Scan() {
|
||||
mountPath = scanner.Text()
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
_ = cmd.Process.Kill()
|
||||
return "", nil, fmt.Errorf("failed to read mount output: %w", err)
|
||||
}
|
||||
|
||||
if mountPath == "" {
|
||||
_ = cmd.Process.Kill()
|
||||
return "", nil, errors.New("mount failed: no target path returned")
|
||||
}
|
||||
|
||||
cleanup := func() {
|
||||
slog.Debug("cleanup triggered")
|
||||
_, _ = fmt.Fprintln(stdinPipe, "")
|
||||
_ = cmd.Wait()
|
||||
}
|
||||
|
||||
return mountPath, cleanup, nil
|
||||
}
|
||||
|
||||
func InternalMountCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "_internal-temporary-mount",
|
||||
HideHelp: true,
|
||||
Hidden: true,
|
||||
Action: func(c *cli.Context) error {
|
||||
logger.SetupForGoPlugin()
|
||||
|
||||
sourceDir := c.Args().First()
|
||||
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("cannot get current user", err)
|
||||
}
|
||||
|
||||
_, alrGid, err := utils.GetUidGidAlrUser()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("cannot get alr user", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(sourceDir); err != nil {
|
||||
return cliutils.FormatCliExit(fmt.Sprintf("cannot read %s", sourceDir), err)
|
||||
}
|
||||
|
||||
if err := utils.EnuseIsPrivilegedGroupMember(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Before escalating the rights, we made sure that
|
||||
// 1. user in wheel group
|
||||
// 2. user can access sourceDir
|
||||
if err := utils.EscalateToRootUid(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := syscall.Setgid(alrGid); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(constants.AlrRunDir, 0o770); err != nil {
|
||||
return cliutils.FormatCliExit(fmt.Sprintf("failed to create %s", constants.AlrRunDir), err)
|
||||
}
|
||||
|
||||
if err := os.Chown(constants.AlrRunDir, 0, alrGid); err != nil {
|
||||
return cliutils.FormatCliExit(fmt.Sprintf("failed to chown %s", constants.AlrRunDir), err)
|
||||
}
|
||||
|
||||
targetDir := filepath.Join(constants.AlrRunDir, fmt.Sprintf("bindfs-%d", os.Getpid()))
|
||||
// 0750: owner (root) and group (alr)
|
||||
if err := os.MkdirAll(targetDir, 0o750); err != nil {
|
||||
return cliutils.FormatCliExit("error creating bindfs target directory", err)
|
||||
}
|
||||
|
||||
// chown AlrRunDir/mounts/bindfs-* to (root:alr),
|
||||
// so alr user can access dir
|
||||
if err := os.Chown(targetDir, 0, alrGid); err != nil {
|
||||
return cliutils.FormatCliExit("failed to chown bindfs directory", err)
|
||||
}
|
||||
|
||||
bindfsCmd := exec.Command(
|
||||
"bindfs",
|
||||
fmt.Sprintf("--map=%s/alr:@%s/@alr", u.Uid, u.Gid),
|
||||
sourceDir,
|
||||
targetDir,
|
||||
)
|
||||
|
||||
bindfsCmd.Stderr = os.Stderr
|
||||
|
||||
if err := bindfsCmd.Run(); err != nil {
|
||||
return cliutils.FormatCliExit("failed to strart bindfs", err)
|
||||
}
|
||||
|
||||
fmt.Println(targetDir)
|
||||
|
||||
_, _ = bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
|
||||
slog.Debug("start unmount", "dir", targetDir)
|
||||
|
||||
umountCmd := exec.Command("umount", targetDir)
|
||||
umountCmd.Stderr = os.Stderr
|
||||
if err := umountCmd.Run(); err != nil {
|
||||
return cliutils.FormatCliExit(fmt.Sprintf("failed to unmount %s", targetDir), err)
|
||||
}
|
||||
|
||||
if err := os.Remove(targetDir); err != nil {
|
||||
return cliutils.FormatCliExit(fmt.Sprintf("error removing directory %s", targetDir), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
176
internal/cliutils/app_builder/builder.go
Normal file
176
internal/cliutils/app_builder/builder.go
Normal file
@ -0,0 +1,176 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package appbuilder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
|
||||
)
|
||||
|
||||
type AppDeps struct {
|
||||
Cfg *config.ALRConfig
|
||||
DB *db.Database
|
||||
Repos *repos.Repos
|
||||
Info *distro.OSRelease
|
||||
Manager manager.Manager
|
||||
}
|
||||
|
||||
func (d *AppDeps) Defer() {
|
||||
if d.DB != nil {
|
||||
if err := d.DB.Close(); err != nil {
|
||||
slog.Warn("failed to close db", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type AppBuilder struct {
|
||||
deps AppDeps
|
||||
err error
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func New(ctx context.Context) *AppBuilder {
|
||||
return &AppBuilder{ctx: ctx}
|
||||
}
|
||||
|
||||
func (b *AppBuilder) UseConfig(cfg *config.ALRConfig) *AppBuilder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
b.deps.Cfg = cfg
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithConfig() *AppBuilder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
cfg := config.New()
|
||||
if err := cfg.Load(); err != nil {
|
||||
b.err = cliutils.FormatCliExit(gotext.Get("Error loading config"), err)
|
||||
return b
|
||||
}
|
||||
|
||||
b.deps.Cfg = cfg
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithDB() *AppBuilder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
cfg := b.deps.Cfg
|
||||
if cfg == nil {
|
||||
b.err = errors.New("config is required before initializing DB")
|
||||
return b
|
||||
}
|
||||
|
||||
db := db.New(cfg)
|
||||
if err := db.Init(b.ctx); err != nil {
|
||||
b.err = cliutils.FormatCliExit(gotext.Get("Error initialization database"), err)
|
||||
return b
|
||||
}
|
||||
|
||||
b.deps.DB = db
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithRepos() *AppBuilder {
|
||||
b.withRepos(true, false)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithReposForcePull() *AppBuilder {
|
||||
b.withRepos(true, true)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithReposNoPull() *AppBuilder {
|
||||
b.withRepos(false, false)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) withRepos(enablePull, forcePull bool) *AppBuilder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
cfg := b.deps.Cfg
|
||||
db := b.deps.DB
|
||||
if cfg == nil || db == nil {
|
||||
b.err = errors.New("config and db are required before initializing repos")
|
||||
return b
|
||||
}
|
||||
|
||||
rs := repos.New(cfg, db)
|
||||
|
||||
if enablePull && (forcePull || cfg.AutoPull()) {
|
||||
if err := rs.Pull(b.ctx, cfg.Repos()); err != nil {
|
||||
b.err = cliutils.FormatCliExit(gotext.Get("Error pulling repositories"), err)
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
b.deps.Repos = rs
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithDistroInfo() *AppBuilder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
b.deps.Info, b.err = distro.ParseOSRelease(b.ctx)
|
||||
if b.err != nil {
|
||||
b.err = cliutils.FormatCliExit(gotext.Get("Error parsing os release"), b.err)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) WithManager() *AppBuilder {
|
||||
if b.err != nil {
|
||||
return b
|
||||
}
|
||||
|
||||
b.deps.Manager = manager.Detect()
|
||||
if b.deps.Manager == nil {
|
||||
b.err = cliutils.FormatCliExit(gotext.Get("Unable to detect a supported package manager on the system"), nil)
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *AppBuilder) Build() (*AppDeps, error) {
|
||||
if b.err != nil {
|
||||
return nil, b.err
|
||||
}
|
||||
return &b.deps, nil
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
102
internal/cliutils/template.go
Normal file
102
internal/cliutils/template.go
Normal file
@ -0,0 +1,102 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cliutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
// Templates are based on https://github.com/urfave/cli/blob/3b17080d70a630feadadd23dd036cad121dd9a50/template.go
|
||||
|
||||
//nolint:unused
|
||||
var (
|
||||
helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}`
|
||||
descriptionTemplate = `{{wrap .Description 3}}`
|
||||
authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
||||
{{range $index, $author := .Authors}}{{if $index}}
|
||||
{{end}}{{$author}}{{end}}`
|
||||
visibleCommandTemplate = `{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
|
||||
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}`
|
||||
visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}`
|
||||
visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}}
|
||||
{{if .Name}}{{.Name}}
|
||||
|
||||
{{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}
|
||||
{{else}}{{$e}}
|
||||
{{end}}{{end}}{{end}}`
|
||||
visibleFlagTemplate = `{{range $i, $e := .VisibleFlags}}
|
||||
{{wrap $e.String 6}}{{end}}`
|
||||
copyrightTemplate = `{{wrap .Copyright 3}}`
|
||||
)
|
||||
|
||||
func GetAppCliTemplate() string {
|
||||
return fmt.Sprintf(`%s:
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
%s:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[%s]{{end}}{{if .Commands}} %s [%s]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[%s...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
||||
|
||||
%s:
|
||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
||||
|
||||
%s:
|
||||
{{template "descriptionTemplate" .}}{{end}}
|
||||
{{- if len .Authors}}
|
||||
|
||||
%s{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
%s:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
%s:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
%s:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}}
|
||||
|
||||
%s:
|
||||
{{template "copyrightTemplate" .}}{{end}}
|
||||
`, gotext.Get("NAME"), gotext.Get("USAGE"), gotext.Get("global options"), gotext.Get("command"), gotext.Get("command options"), gotext.Get("arguments"), gotext.Get("VERSION"), gotext.Get("DESCRIPTION"), gotext.Get("AUTHOR"), gotext.Get("COMMANDS"), gotext.Get("GLOBAL OPTIONS"), gotext.Get("GLOBAL OPTIONS"), gotext.Get("COPYRIGHT"))
|
||||
}
|
||||
|
||||
func GetCommandHelpTemplate() string {
|
||||
return fmt.Sprintf(`%s:
|
||||
{{template "helpNameTemplate" .}}
|
||||
|
||||
%s:
|
||||
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [%s]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[%s...]{{end}}{{end}}{{if .Category}}
|
||||
|
||||
%s:
|
||||
{{.Category}}{{end}}{{if .Description}}
|
||||
|
||||
%s:
|
||||
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
|
||||
|
||||
%s:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
|
||||
|
||||
%s:{{template "visibleFlagTemplate" .}}{{end}}
|
||||
`, gotext.Get("NAME"),
|
||||
gotext.Get("USAGE"),
|
||||
gotext.Get("command options"),
|
||||
gotext.Get("arguments"),
|
||||
gotext.Get("CATEGORY"),
|
||||
gotext.Get("DESCRIPTION"),
|
||||
gotext.Get("OPTIONS"),
|
||||
gotext.Get("OPTIONS"),
|
||||
)
|
||||
}
|
72
internal/cliutils/utils.go
Normal file
72
internal/cliutils/utils.go
Normal file
@ -0,0 +1,72 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cliutils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
type BashCompleteWithErrorFunc func(c *cli.Context) error
|
||||
|
||||
func BashCompleteWithError(f BashCompleteWithErrorFunc) cli.BashCompleteFunc {
|
||||
return func(c *cli.Context) { HandleExitCoder(f(c)) }
|
||||
}
|
||||
|
||||
func HandleExitCoder(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if exitErr, ok := err.(cli.ExitCoder); ok {
|
||||
if err.Error() != "" {
|
||||
if _, ok := exitErr.(cli.ErrorFormatter); ok {
|
||||
slog.Error(fmt.Sprintf("%+v\n", err))
|
||||
} else {
|
||||
slog.Error(err.Error())
|
||||
}
|
||||
}
|
||||
cli.OsExiter(exitErr.ExitCode())
|
||||
return
|
||||
}
|
||||
|
||||
slog.Error(err.Error())
|
||||
cli.OsExiter(1)
|
||||
}
|
||||
|
||||
func FormatCliExit(msg string, err error) cli.ExitCoder {
|
||||
return FormatCliExitWithCode(msg, err, 1)
|
||||
}
|
||||
|
||||
func FormatCliExitWithCode(msg string, err error, exitCode int) cli.ExitCoder {
|
||||
if err == nil {
|
||||
return cli.Exit(errors.New(msg), exitCode)
|
||||
}
|
||||
return cli.Exit(fmt.Errorf("%s: %w", msg, err), exitCode)
|
||||
}
|
||||
|
||||
func WarnLegacyCommand(newSyntax string) {
|
||||
slog.Warn(
|
||||
gotext.Get(
|
||||
"This command is deprecated and would be removed in the future, use \"%s\" instead!", newSyntax,
|
||||
),
|
||||
)
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -20,153 +20,142 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"reflect"
|
||||
|
||||
"github.com/caarlos0/env"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/constants"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
)
|
||||
|
||||
type ALRConfig struct {
|
||||
cfg *types.Config
|
||||
paths *Paths
|
||||
|
||||
cfgOnce sync.Once
|
||||
pathsOnce sync.Once
|
||||
}
|
||||
|
||||
var defaultConfig = &types.Config{
|
||||
RootCmd: "sudo",
|
||||
UseRootCmd: true,
|
||||
PagerStyle: "native",
|
||||
IgnorePkgUpdates: []string{},
|
||||
AutoPull: true,
|
||||
Repos: []types.Repo{
|
||||
{
|
||||
Name: "default",
|
||||
URL: "https://gitea.plemya-x.ru/xpamych/xpamych-alr-repo.git",
|
||||
},
|
||||
},
|
||||
Repos: []types.Repo{},
|
||||
}
|
||||
|
||||
func New() *ALRConfig {
|
||||
return &ALRConfig{}
|
||||
}
|
||||
|
||||
func (c *ALRConfig) Load(ctx context.Context) {
|
||||
cfgFl, err := os.Open(c.GetPaths(ctx).ConfigPath)
|
||||
func readConfig(path string) (*types.Config, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
slog.Warn(gotext.Get("Error opening config file, using defaults"), "err", err)
|
||||
c.cfg = defaultConfig
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
config := types.Config{}
|
||||
|
||||
if err := toml.NewDecoder(file).Decode(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
func mergeStructs(dst, src interface{}) {
|
||||
srcVal := reflect.ValueOf(src)
|
||||
if srcVal.IsNil() {
|
||||
return
|
||||
}
|
||||
defer cfgFl.Close()
|
||||
srcVal = srcVal.Elem()
|
||||
dstVal := reflect.ValueOf(dst).Elem()
|
||||
|
||||
// Copy the default configuration into config
|
||||
defCopy := *defaultConfig
|
||||
config := &defCopy
|
||||
config.Repos = nil
|
||||
for i := range srcVal.NumField() {
|
||||
srcField := srcVal.Field(i)
|
||||
srcFieldName := srcVal.Type().Field(i).Name
|
||||
|
||||
err = toml.NewDecoder(cfgFl).Decode(config)
|
||||
if err != nil {
|
||||
slog.Warn(gotext.Get("Error decoding config file, using defaults"), "err", err)
|
||||
c.cfg = defaultConfig
|
||||
return
|
||||
dstField := dstVal.FieldByName(srcFieldName)
|
||||
if dstField.IsValid() && dstField.CanSet() {
|
||||
dstField.Set(srcField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ALRConfig) Load() error {
|
||||
systemConfig, err := readConfig(
|
||||
constants.SystemConfigPath,
|
||||
)
|
||||
if err != nil {
|
||||
slog.Debug("Cannot read system config", "err", err)
|
||||
}
|
||||
|
||||
config := &types.Config{}
|
||||
|
||||
mergeStructs(config, defaultConfig)
|
||||
mergeStructs(config, systemConfig)
|
||||
err = env.Parse(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.cfg = config
|
||||
|
||||
c.paths = &Paths{}
|
||||
c.paths.UserConfigPath = constants.SystemConfigPath
|
||||
c.paths.CacheDir = constants.SystemCachePath
|
||||
c.paths.RepoDir = filepath.Join(c.paths.CacheDir, "repo")
|
||||
c.paths.PkgsDir = filepath.Join(c.paths.CacheDir, "pkgs")
|
||||
c.paths.DBPath = filepath.Join(c.paths.CacheDir, "db")
|
||||
// c.initPaths()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ALRConfig) initPaths() {
|
||||
paths := &Paths{}
|
||||
|
||||
cfgDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to detect user config directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.ConfigDir = filepath.Join(cfgDir, "alr")
|
||||
|
||||
err = os.MkdirAll(paths.ConfigDir, 0o755)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to create ALR config directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.ConfigPath = filepath.Join(paths.ConfigDir, "alr.toml")
|
||||
|
||||
if _, err := os.Stat(paths.ConfigPath); err != nil {
|
||||
cfgFl, err := os.Create(paths.ConfigPath)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to create ALR config file"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = toml.NewEncoder(cfgFl).Encode(&defaultConfig)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error encoding default configuration"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfgFl.Close()
|
||||
}
|
||||
|
||||
cacheDir, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to detect cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.CacheDir = filepath.Join(cacheDir, "alr")
|
||||
paths.RepoDir = filepath.Join(paths.CacheDir, "repo")
|
||||
paths.PkgsDir = filepath.Join(paths.CacheDir, "pkgs")
|
||||
|
||||
err = os.MkdirAll(paths.RepoDir, 0o755)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to create repo cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(paths.PkgsDir, 0o755)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Unable to create package cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.DBPath = filepath.Join(paths.CacheDir, "db")
|
||||
|
||||
c.paths = paths
|
||||
func (c *ALRConfig) RootCmd() string {
|
||||
return c.cfg.RootCmd
|
||||
}
|
||||
|
||||
func (c *ALRConfig) GetPaths(ctx context.Context) *Paths {
|
||||
c.pathsOnce.Do(func() {
|
||||
c.initPaths()
|
||||
})
|
||||
return c.paths
|
||||
func (c *ALRConfig) PagerStyle() string {
|
||||
return c.cfg.PagerStyle
|
||||
}
|
||||
|
||||
func (c *ALRConfig) Repos(ctx context.Context) []types.Repo {
|
||||
c.cfgOnce.Do(func() {
|
||||
c.Load(ctx)
|
||||
})
|
||||
func (c *ALRConfig) AutoPull() bool {
|
||||
return c.cfg.AutoPull
|
||||
}
|
||||
|
||||
func (c *ALRConfig) Repos() []types.Repo {
|
||||
return c.cfg.Repos
|
||||
}
|
||||
|
||||
func (c *ALRConfig) IgnorePkgUpdates(ctx context.Context) []string {
|
||||
c.cfgOnce.Do(func() {
|
||||
c.Load(ctx)
|
||||
})
|
||||
func (c *ALRConfig) SetRepos(repos []types.Repo) {
|
||||
c.cfg.Repos = repos
|
||||
}
|
||||
|
||||
func (c *ALRConfig) IgnorePkgUpdates() []string {
|
||||
return c.cfg.IgnorePkgUpdates
|
||||
}
|
||||
|
||||
func (c *ALRConfig) AutoPull(ctx context.Context) bool {
|
||||
c.cfgOnce.Do(func() {
|
||||
c.Load(ctx)
|
||||
})
|
||||
return c.cfg.AutoPull
|
||||
func (c *ALRConfig) LogLevel() string {
|
||||
return c.cfg.LogLevel
|
||||
}
|
||||
|
||||
func (c *ALRConfig) UseRootCmd() bool {
|
||||
return c.cfg.UseRootCmd
|
||||
}
|
||||
|
||||
func (c *ALRConfig) GetPaths() *Paths {
|
||||
return c.paths
|
||||
}
|
||||
|
||||
func (c *ALRConfig) SaveUserConfig() error {
|
||||
f, err := os.Create(c.paths.UserConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return toml.NewEncoder(f).Encode(c.cfg)
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
var (
|
||||
langMtx sync.Mutex
|
||||
lang language.Tag
|
||||
langSet bool
|
||||
)
|
||||
|
||||
// Language returns the system language.
|
||||
// The first time it's called, it'll detect the langauge based on
|
||||
// the $LANG environment variable.
|
||||
// Subsequent calls will just return the same value.
|
||||
func Language(ctx context.Context) language.Tag {
|
||||
langMtx.Lock()
|
||||
if !langSet {
|
||||
syslang := SystemLang()
|
||||
tag, err := language.Parse(syslang)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error parsing system language"), "err", err)
|
||||
langMtx.Unlock()
|
||||
os.Exit(1)
|
||||
}
|
||||
base, _ := tag.Base()
|
||||
lang = language.Make(base.String())
|
||||
langSet = true
|
||||
}
|
||||
langMtx.Unlock()
|
||||
return lang
|
||||
}
|
||||
|
||||
// SystemLang returns the system language based on
|
||||
// the $LANG environment variable.
|
||||
func SystemLang() string {
|
||||
lang := os.Getenv("LANG")
|
||||
lang, _, _ = strings.Cut(lang, ".")
|
||||
if lang == "" || lang == "C" {
|
||||
lang = "en"
|
||||
}
|
||||
return lang
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -19,27 +19,11 @@
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Paths contains various paths used by ALR
|
||||
type Paths struct {
|
||||
ConfigDir string
|
||||
ConfigPath string
|
||||
CacheDir string
|
||||
RepoDir string
|
||||
PkgsDir string
|
||||
DBPath string
|
||||
}
|
||||
|
||||
// GetPaths returns a Paths struct.
|
||||
// The first time it's called, it'll generate the struct
|
||||
// using information from the system.
|
||||
// Subsequent calls will return the same value.
|
||||
//
|
||||
// Deprecated: use struct API
|
||||
func GetPaths(ctx context.Context) *Paths {
|
||||
alrConfig := GetInstance(ctx)
|
||||
return alrConfig.GetPaths(ctx)
|
||||
UserConfigPath string
|
||||
CacheDir string
|
||||
RepoDir string
|
||||
PkgsDir string
|
||||
DBPath string
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
24
internal/constants/constants.go
Normal file
24
internal/constants/constants.go
Normal file
@ -0,0 +1,24 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package constants
|
||||
|
||||
const (
|
||||
SystemConfigPath = "/etc/alr/alr.toml"
|
||||
SystemCachePath = "/var/cache/alr"
|
||||
AlrRunDir = "/var/run/alr"
|
||||
PrivilegedGroup = "wheel"
|
||||
)
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -31,15 +31,18 @@ import (
|
||||
|
||||
// CurrentVersion is the current version of the database.
|
||||
// The database is reset if its version doesn't match this.
|
||||
const CurrentVersion = 2
|
||||
const CurrentVersion = 4
|
||||
|
||||
// Package is a ALR package's database representation
|
||||
type Package struct {
|
||||
BasePkgName string `sh:"base" db:"basepkg_name"`
|
||||
Name string `sh:"name,required" db:"name"`
|
||||
Version string `sh:"version,required" db:"version"`
|
||||
Release int `sh:"release,required" db:"release"`
|
||||
Epoch uint `sh:"epoch" db:"epoch"`
|
||||
Summary JSON[map[string]string] `db:"summary"`
|
||||
Description JSON[map[string]string] `db:"description"`
|
||||
Group JSON[map[string]string] `db:"group_name"`
|
||||
Homepage JSON[map[string]string] `db:"homepage"`
|
||||
Maintainer JSON[map[string]string] `db:"maintainer"`
|
||||
Architectures JSON[[]string] `sh:"architectures" db:"architectures"`
|
||||
@ -58,7 +61,7 @@ type version struct {
|
||||
}
|
||||
|
||||
type Config interface {
|
||||
GetPaths(ctx context.Context) *config.Paths
|
||||
GetPaths() *config.Paths
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
@ -81,7 +84,7 @@ func (d *Database) Init(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (d *Database) Connect(ctx context.Context) error {
|
||||
dsn := d.config.GetPaths(ctx).DBPath
|
||||
dsn := d.config.GetPaths().DBPath
|
||||
db, err := sqlx.Open("sqlite", dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -99,12 +102,15 @@ func (d *Database) initDB(ctx context.Context) error {
|
||||
conn := d.conn
|
||||
_, err := conn.ExecContext(ctx, `
|
||||
CREATE TABLE IF NOT EXISTS pkgs (
|
||||
basepkg_name TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
repository TEXT NOT NULL,
|
||||
version TEXT NOT NULL,
|
||||
release INT NOT NULL,
|
||||
epoch INT,
|
||||
summary TEXT CHECK(summary = 'null' OR (JSON_VALID(summary) AND JSON_TYPE(summary) = 'object')),
|
||||
description TEXT CHECK(description = 'null' OR (JSON_VALID(description) AND JSON_TYPE(description) = 'object')),
|
||||
group_name TEXT CHECK(group_name = 'null' OR (JSON_VALID(group_name) AND JSON_TYPE(group_name) = 'object')),
|
||||
homepage TEXT CHECK(homepage = 'null' OR (JSON_VALID(homepage) AND JSON_TYPE(homepage) = 'object')),
|
||||
maintainer TEXT CHECK(maintainer = 'null' OR (JSON_VALID(maintainer) AND JSON_TYPE(maintainer) = 'object')),
|
||||
architectures TEXT CHECK(architectures = 'null' OR (JSON_VALID(architectures) AND JSON_TYPE(architectures) = 'array')),
|
||||
@ -196,12 +202,15 @@ func (d *Database) IsEmpty(ctx context.Context) bool {
|
||||
func (d *Database) InsertPackage(ctx context.Context, pkg Package) error {
|
||||
_, err := d.conn.NamedExecContext(ctx, `
|
||||
INSERT OR REPLACE INTO pkgs (
|
||||
basepkg_name,
|
||||
name,
|
||||
repository,
|
||||
version,
|
||||
release,
|
||||
epoch,
|
||||
summary,
|
||||
description,
|
||||
group_name,
|
||||
homepage,
|
||||
maintainer,
|
||||
architectures,
|
||||
@ -213,12 +222,15 @@ func (d *Database) InsertPackage(ctx context.Context, pkg Package) error {
|
||||
builddepends,
|
||||
optdepends
|
||||
) VALUES (
|
||||
:basepkg_name,
|
||||
:name,
|
||||
:repository,
|
||||
:version,
|
||||
:release,
|
||||
:epoch,
|
||||
:summary,
|
||||
:description,
|
||||
:group_name,
|
||||
:homepage,
|
||||
:maintainer,
|
||||
:architectures,
|
||||
|
@ -1,106 +0,0 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
)
|
||||
|
||||
// DB returns the ALR database.
|
||||
// The first time it's called, it opens the SQLite database file.
|
||||
// Subsequent calls return the same connection.
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func DB(ctx context.Context) *sqlx.DB {
|
||||
return GetInstance(ctx).GetConn()
|
||||
}
|
||||
|
||||
// Close closes the database
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func Close() error {
|
||||
if database != nil {
|
||||
return database.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the database has no packages in it, otherwise it returns false.
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func IsEmpty(ctx context.Context) bool {
|
||||
return GetInstance(ctx).IsEmpty(ctx)
|
||||
}
|
||||
|
||||
// InsertPackage adds a package to the database
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func InsertPackage(ctx context.Context, pkg Package) error {
|
||||
return GetInstance(ctx).InsertPackage(ctx, pkg)
|
||||
}
|
||||
|
||||
// GetPkgs returns a result containing packages that match the where conditions
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func GetPkgs(ctx context.Context, where string, args ...any) (*sqlx.Rows, error) {
|
||||
return GetInstance(ctx).GetPkgs(ctx, where, args...)
|
||||
}
|
||||
|
||||
// GetPkg returns a single package that matches the where conditions
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func GetPkg(ctx context.Context, where string, args ...any) (*Package, error) {
|
||||
return GetInstance(ctx).GetPkg(ctx, where, args...)
|
||||
}
|
||||
|
||||
// DeletePkgs deletes all packages matching the where conditions
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func DeletePkgs(ctx context.Context, where string, args ...any) error {
|
||||
return GetInstance(ctx).DeletePkgs(ctx, where, args...)
|
||||
}
|
||||
|
||||
// =======================
|
||||
// FOR LEGACY ONLY
|
||||
// =======================
|
||||
|
||||
var (
|
||||
dbOnce sync.Once
|
||||
database *Database
|
||||
)
|
||||
|
||||
// Deprecated: For legacy only
|
||||
func GetInstance(ctx context.Context) *Database {
|
||||
dbOnce.Do(func() {
|
||||
cfg := config.GetInstance(ctx)
|
||||
database = New(cfg)
|
||||
err := database.Init(ctx)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error opening database"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
})
|
||||
return database
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -33,7 +33,7 @@ import (
|
||||
|
||||
type TestALRConfig struct{}
|
||||
|
||||
func (c *TestALRConfig) GetPaths(ctx context.Context) *config.Paths {
|
||||
func (c *TestALRConfig) GetPaths() *config.Paths {
|
||||
return &config.Paths{
|
||||
DBPath: ":memory:",
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -38,7 +38,7 @@ import (
|
||||
|
||||
type TestALRConfig struct{}
|
||||
|
||||
func (c *TestALRConfig) GetPaths(ctx context.Context) *config.Paths {
|
||||
func (c *TestALRConfig) GetPaths() *config.Paths {
|
||||
return &config.Paths{
|
||||
CacheDir: "/tmp",
|
||||
}
|
||||
@ -91,7 +91,7 @@ func TestDownloadWithoutCache(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "git download",
|
||||
path: "git+%s/git-downloader/git/Plemya-x/xpamych-alr-repo",
|
||||
path: "git+%s/git-downloader/git/Plemya-x/alr-repo",
|
||||
expected: func(t *testing.T, err error, tmpdir string) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -123,6 +123,7 @@ func (FileDownloader) Download(ctx context.Context, opts Options) (Type, string,
|
||||
} else {
|
||||
out = fl
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
h, err := opts.NewHash()
|
||||
if err != nil {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -28,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
type Config interface {
|
||||
GetPaths(ctx context.Context) *config.Paths
|
||||
GetPaths() *config.Paths
|
||||
}
|
||||
|
||||
type DownloadCache struct {
|
||||
@ -43,7 +43,7 @@ func New(cfg Config) *DownloadCache {
|
||||
|
||||
func (dc *DownloadCache) BasePath(ctx context.Context) string {
|
||||
return filepath.Join(
|
||||
dc.cfg.GetPaths(ctx).CacheDir, "dl",
|
||||
dc.cfg.GetPaths().CacheDir, "dl",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -32,19 +32,11 @@ import (
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/dlcache"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dir, err := os.MkdirTemp("/tmp", "alr-dlcache-test.*")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
config.GetPaths(context.Background()).RepoDir = dir
|
||||
}
|
||||
|
||||
type TestALRConfig struct {
|
||||
CacheDir string
|
||||
}
|
||||
|
||||
func (c *TestALRConfig) GetPaths(ctx context.Context) *config.Paths {
|
||||
func (c *TestALRConfig) GetPaths() *config.Paths {
|
||||
return &config.Paths{
|
||||
CacheDir: c.CacheDir,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
152
internal/logger/hclog.go
Normal file
152
internal/logger/hclog.go
Normal file
@ -0,0 +1,152 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
chLog "github.com/charmbracelet/log"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
)
|
||||
|
||||
type HCLoggerAdapter struct {
|
||||
logger *Logger
|
||||
}
|
||||
|
||||
func hclogLevelTochLog(level hclog.Level) chLog.Level {
|
||||
switch level {
|
||||
case hclog.Debug:
|
||||
return chLog.DebugLevel
|
||||
case hclog.Info:
|
||||
return chLog.InfoLevel
|
||||
case hclog.Warn:
|
||||
return chLog.WarnLevel
|
||||
case hclog.Error:
|
||||
return chLog.ErrorLevel
|
||||
}
|
||||
return chLog.FatalLevel
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
|
||||
filteredArgs := make([]interface{}, 0, len(args))
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
if i+1 >= len(args) {
|
||||
filteredArgs = append(filteredArgs, args[i])
|
||||
continue
|
||||
}
|
||||
|
||||
key, ok := args[i].(string)
|
||||
if !ok || key != "timestamp" {
|
||||
filteredArgs = append(filteredArgs, args[i], args[i+1])
|
||||
}
|
||||
}
|
||||
|
||||
// Start ugly hacks
|
||||
// Ignore exit messages
|
||||
// - https://github.com/hashicorp/go-plugin/issues/331
|
||||
// - https://github.com/hashicorp/go-plugin/issues/203
|
||||
// - https://github.com/hashicorp/go-plugin/issues/192
|
||||
var chLogLevel chLog.Level
|
||||
if msg == "plugin process exited" ||
|
||||
strings.HasPrefix(msg, "[ERR] plugin: stream copy 'stderr' error") ||
|
||||
strings.HasPrefix(msg, "[DEBUG] plugin") {
|
||||
chLogLevel = chLog.DebugLevel
|
||||
} else {
|
||||
chLogLevel = hclogLevelTochLog(level)
|
||||
}
|
||||
|
||||
a.logger.l.Log(chLogLevel, msg, filteredArgs...)
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Trace(msg string, args ...interface{}) {
|
||||
a.Log(hclog.Trace, msg, args...)
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Debug(msg string, args ...interface{}) {
|
||||
a.Log(hclog.Debug, msg, args...)
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Info(msg string, args ...interface{}) {
|
||||
a.Log(hclog.Info, msg, args...)
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Warn(msg string, args ...interface{}) {
|
||||
a.Log(hclog.Warn, msg, args...)
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Error(msg string, args ...interface{}) {
|
||||
a.Log(hclog.Error, msg, args...)
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) IsTrace() bool {
|
||||
return a.logger.l.GetLevel() <= chLog.DebugLevel
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) IsDebug() bool {
|
||||
return a.logger.l.GetLevel() <= chLog.DebugLevel
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) IsInfo() bool {
|
||||
return a.logger.l.GetLevel() <= chLog.InfoLevel
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) IsWarn() bool {
|
||||
return a.logger.l.GetLevel() <= chLog.WarnLevel
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) IsError() bool {
|
||||
return a.logger.l.GetLevel() <= chLog.ErrorLevel
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) ImpliedArgs() []interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) With(args ...interface{}) hclog.Logger {
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Name() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) Named(name string) hclog.Logger {
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) ResetNamed(name string) hclog.Logger {
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) SetLevel(level hclog.Level) {
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *HCLoggerAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetHCLoggerAdapter() *HCLoggerAdapter {
|
||||
return &HCLoggerAdapter{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -22,75 +22,90 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/charmbracelet/log"
|
||||
|
||||
chLog "github.com/charmbracelet/log"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
lOut slog.Handler
|
||||
lErr slog.Handler
|
||||
l *chLog.Logger
|
||||
}
|
||||
|
||||
func setupOutLogger() *log.Logger {
|
||||
styles := log.DefaultStyles()
|
||||
logger := log.New(os.Stdout)
|
||||
styles.Levels[log.InfoLevel] = lipgloss.NewStyle().
|
||||
func setupLogger() *chLog.Logger {
|
||||
styles := chLog.DefaultStyles()
|
||||
logger := chLog.New(os.Stderr)
|
||||
styles.Levels[chLog.InfoLevel] = lipgloss.NewStyle().
|
||||
SetString("-->").
|
||||
Foreground(lipgloss.Color("35"))
|
||||
logger.SetStyles(styles)
|
||||
return logger
|
||||
}
|
||||
|
||||
func setupErrorLogger() *log.Logger {
|
||||
styles := log.DefaultStyles()
|
||||
styles.Levels[log.ErrorLevel] = lipgloss.NewStyle().
|
||||
styles.Levels[chLog.ErrorLevel] = lipgloss.NewStyle().
|
||||
SetString(gotext.Get("ERROR")).
|
||||
Padding(0, 1, 0, 1).
|
||||
Background(lipgloss.Color("204")).
|
||||
Foreground(lipgloss.Color("0"))
|
||||
logger := log.New(os.Stderr)
|
||||
logger.SetStyles(styles)
|
||||
return logger
|
||||
}
|
||||
|
||||
func New() *Logger {
|
||||
standardLogger := setupOutLogger()
|
||||
errLogger := setupErrorLogger()
|
||||
return &Logger{
|
||||
lOut: standardLogger,
|
||||
lErr: errLogger,
|
||||
l: setupLogger(),
|
||||
}
|
||||
}
|
||||
|
||||
func slogLevelToLog(level slog.Level) chLog.Level {
|
||||
switch level {
|
||||
case slog.LevelDebug:
|
||||
return chLog.DebugLevel
|
||||
case slog.LevelInfo:
|
||||
return chLog.InfoLevel
|
||||
case slog.LevelWarn:
|
||||
return chLog.WarnLevel
|
||||
case slog.LevelError:
|
||||
return chLog.ErrorLevel
|
||||
}
|
||||
return chLog.FatalLevel
|
||||
}
|
||||
|
||||
func (l *Logger) SetLevel(level slog.Level) {
|
||||
l.l.SetLevel(slogLevelToLog(level))
|
||||
}
|
||||
|
||||
func (l *Logger) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
if level <= slog.LevelInfo {
|
||||
return l.lOut.Enabled(ctx, level)
|
||||
}
|
||||
return l.lErr.Enabled(ctx, level)
|
||||
return l.l.Enabled(ctx, level)
|
||||
}
|
||||
|
||||
func (l *Logger) Handle(ctx context.Context, rec slog.Record) error {
|
||||
if rec.Level <= slog.LevelInfo {
|
||||
return l.lOut.Handle(ctx, rec)
|
||||
}
|
||||
return l.lErr.Handle(ctx, rec)
|
||||
return l.l.Handle(ctx, rec)
|
||||
}
|
||||
|
||||
func (l *Logger) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
sl := *l
|
||||
sl.lOut = l.lOut.WithAttrs(attrs)
|
||||
sl.lErr = l.lErr.WithAttrs(attrs)
|
||||
sl.l = l.l.WithAttrs(attrs).(*chLog.Logger)
|
||||
return &sl
|
||||
}
|
||||
|
||||
func (l *Logger) WithGroup(name string) slog.Handler {
|
||||
sl := *l
|
||||
sl.lOut = l.lOut.WithGroup(name)
|
||||
sl.lErr = l.lErr.WithGroup(name)
|
||||
sl.l = l.l.WithGroup(name).(*chLog.Logger)
|
||||
return &sl
|
||||
}
|
||||
|
||||
func SetupDefault() {
|
||||
logger := slog.New(New())
|
||||
slog.SetDefault(logger)
|
||||
var logger *Logger
|
||||
|
||||
func SetupDefault() *Logger {
|
||||
logger = New()
|
||||
slogLogger := slog.New(logger)
|
||||
slog.SetDefault(slogLogger)
|
||||
return logger
|
||||
}
|
||||
|
||||
func SetupForGoPlugin() {
|
||||
logger.l.SetFormatter(chLog.JSONFormatter)
|
||||
chLog.TimestampKey = "@timestamp"
|
||||
chLog.MessageKey = "@message"
|
||||
chLog.LevelKey = "@level"
|
||||
}
|
||||
|
||||
func GetLogger() *Logger {
|
||||
return logger
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -104,7 +104,7 @@ func Resolve(info *distro.OSRelease, opts *Opts) ([]string, error) {
|
||||
out = append(out, opts.Name)
|
||||
|
||||
for index, item := range out {
|
||||
out[index] = strings.TrimPrefix(strings.ReplaceAll(item, "-", "_"), "_")
|
||||
out[index] = strings.TrimPrefix(item, "_")
|
||||
}
|
||||
|
||||
return out, nil
|
||||
@ -157,6 +157,8 @@ type ResolvedPackage struct {
|
||||
Version string `sh:"version"`
|
||||
Release int `sh:"release"`
|
||||
Epoch uint `sh:"epoch"`
|
||||
Group string `db:"group_name"`
|
||||
Summary string `db:"summary"`
|
||||
Description string `db:"description"`
|
||||
Homepage string `db:"homepage"`
|
||||
Maintainer string `db:"maintainer"`
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -41,7 +41,7 @@ func init() {
|
||||
|
||||
b2 := lipgloss.RoundedBorder()
|
||||
b2.Left = "\u2524"
|
||||
infoStyle = titleStyle.Copy().BorderStyle(b2)
|
||||
infoStyle = titleStyle.BorderStyle(b2)
|
||||
}
|
||||
|
||||
type Pager struct {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -123,15 +123,29 @@ func (d *Decoder) DecodeVars(val any) error {
|
||||
}
|
||||
|
||||
rVal := reflect.ValueOf(val).Elem()
|
||||
return d.decodeStruct(rVal)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeStruct(rVal reflect.Value) error {
|
||||
for i := 0; i < rVal.NumField(); i++ {
|
||||
field := rVal.Field(i)
|
||||
fieldType := rVal.Type().Field(i)
|
||||
|
||||
// Пропускаем неэкспортируемые поля
|
||||
if !fieldType.IsExported() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Обрабатываем встроенные поля рекурсивно
|
||||
if fieldType.Anonymous {
|
||||
if field.Kind() == reflect.Struct {
|
||||
if err := d.decodeStruct(field); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
name := fieldType.Name
|
||||
tag := fieldType.Tag.Get("sh")
|
||||
required := false
|
||||
@ -160,11 +174,13 @@ func (d *Decoder) DecodeVars(val any) error {
|
||||
|
||||
field.Set(newVal.Elem())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ScriptFunc func(ctx context.Context, opts ...interp.RunnerOption) error
|
||||
type (
|
||||
ScriptFunc func(ctx context.Context, opts ...interp.RunnerOption) error
|
||||
ScriptFuncWithSubshell func(ctx context.Context, opts ...interp.RunnerOption) (*interp.Runner, error)
|
||||
)
|
||||
|
||||
// GetFunc returns a function corresponding to a bash function
|
||||
// with the given name
|
||||
@ -197,6 +213,24 @@ func (d *Decoder) GetFuncP(name string, prepare PrepareFunc) (ScriptFunc, bool)
|
||||
}, true
|
||||
}
|
||||
|
||||
func (d *Decoder) GetFuncWithSubshell(name string) (ScriptFuncWithSubshell, bool) {
|
||||
fn := d.getFunc(name)
|
||||
if fn == nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return func(ctx context.Context, opts ...interp.RunnerOption) (*interp.Runner, error) {
|
||||
sub := d.Runner.Subshell()
|
||||
for _, opt := range opts {
|
||||
err := opt(sub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return sub, sub.Run(ctx, fn)
|
||||
}, true
|
||||
}
|
||||
|
||||
func (d *Decoder) getFunc(name string) *syntax.Stmt {
|
||||
names, err := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name))
|
||||
if err != nil {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -29,9 +29,9 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/fakeroot"
|
||||
"mvdan.cc/sh/v3/expand"
|
||||
"mvdan.cc/sh/v3/interp"
|
||||
"gitea.plemya-x.ru/Plemya-x/fakeroot"
|
||||
)
|
||||
|
||||
// FakerootExecHandler was extracted from github.com/mvdan/sh/interp/handler.go
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -22,10 +22,11 @@ package handlers
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
)
|
||||
|
||||
func NopReadDir(context.Context, string) ([]os.FileInfo, error) {
|
||||
func NopReadDir(context.Context, string) ([]fs.DirEntry, error) {
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -31,12 +31,12 @@ import (
|
||||
"mvdan.cc/sh/v3/interp"
|
||||
)
|
||||
|
||||
func RestrictedReadDir(allowedPrefixes ...string) interp.ReadDirHandlerFunc {
|
||||
return func(ctx context.Context, s string) ([]fs.FileInfo, error) {
|
||||
func RestrictedReadDir(allowedPrefixes ...string) interp.ReadDirHandlerFunc2 {
|
||||
return func(ctx context.Context, s string) ([]fs.DirEntry, error) {
|
||||
path := filepath.Clean(s)
|
||||
for _, allowedPrefix := range allowedPrefixes {
|
||||
if strings.HasPrefix(path, allowedPrefix) {
|
||||
return interp.DefaultReadDirHandler()(ctx, s)
|
||||
return interp.DefaultReadDirHandler2()(ctx, s)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -9,71 +9,83 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: build.go:41
|
||||
#: build.go:42
|
||||
msgid "Build a local package"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:47
|
||||
#: build.go:48
|
||||
msgid "Path to the build script"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:52
|
||||
#: build.go:53
|
||||
msgid "Specify subpackage in script (for multi package script only)"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:58
|
||||
msgid "Name of the package to build and its repo (example: default/go-bin)"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:57
|
||||
#: build.go:63
|
||||
msgid ""
|
||||
"Build package from scratch even if there's an already built package available"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:87
|
||||
msgid "Error pulling repositories"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:95
|
||||
msgid "Unable to detect a supported package manager on the system"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:107
|
||||
msgid "Error building package"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:114
|
||||
#: build.go:73
|
||||
msgid "Error getting working directory"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:123
|
||||
#: build.go:118
|
||||
msgid "Cannot get absolute script path"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:152
|
||||
msgid "Package not found"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:165
|
||||
msgid "Nothing to build"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:222
|
||||
msgid "Error building package"
|
||||
msgstr ""
|
||||
|
||||
#: build.go:229
|
||||
msgid "Error moving the package"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:37
|
||||
#: build.go:233
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:38
|
||||
msgid "Attempt to fix problems with ALR"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:44
|
||||
msgid "Removing cache directory"
|
||||
#: fix.go:59
|
||||
msgid "Clearing cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:48
|
||||
msgid "Unable to remove cache directory"
|
||||
#: fix.go:64
|
||||
msgid "Unable to open cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:52
|
||||
#: fix.go:70
|
||||
msgid "Unable to read cache directory contents"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:76
|
||||
msgid "Unable to remove cache item (%s)"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:80
|
||||
msgid "Rebuilding cache"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:56
|
||||
#: fix.go:84
|
||||
msgid "Unable to create new cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:62
|
||||
msgid "Error pulling repos"
|
||||
msgstr ""
|
||||
|
||||
#: fix.go:66
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#: gen.go:34
|
||||
msgid "Generate a ALR script from a template"
|
||||
msgstr ""
|
||||
@ -82,22 +94,26 @@ msgstr ""
|
||||
msgid "Generate a ALR script for a pip module"
|
||||
msgstr ""
|
||||
|
||||
#: helper.go:41
|
||||
#: helper.go:42
|
||||
msgid "List all the available helper commands"
|
||||
msgstr ""
|
||||
|
||||
#: helper.go:53
|
||||
#: helper.go:54
|
||||
msgid "Run a ALR helper command"
|
||||
msgstr ""
|
||||
|
||||
#: helper.go:60
|
||||
#: helper.go:61
|
||||
msgid "The directory that the install commands will install to"
|
||||
msgstr ""
|
||||
|
||||
#: helper.go:73
|
||||
#: helper.go:74 helper.go:75
|
||||
msgid "No such helper command"
|
||||
msgstr ""
|
||||
|
||||
#: helper.go:85
|
||||
msgid "Error parsing os-release file"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:42
|
||||
msgid "Print information about a package"
|
||||
msgstr ""
|
||||
@ -106,58 +122,82 @@ msgstr ""
|
||||
msgid "Show all information, not just for the current distro"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:57
|
||||
msgid "Error initialization database"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:64
|
||||
msgid "Command info expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:78
|
||||
msgid "Error finding packages"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:94
|
||||
msgid "Error parsing os-release file"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:103
|
||||
msgid "Error resolving overrides"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:112 info.go:118
|
||||
msgid "Error encoding script variables"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:42
|
||||
msgid "Install a new package"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:56
|
||||
msgid "Command install expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:91
|
||||
#: info.go:68
|
||||
msgid "Error getting packages"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:100
|
||||
#: info.go:76
|
||||
msgid "Error iterating over packages"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:113
|
||||
#: info.go:90
|
||||
msgid "Command info expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:110
|
||||
msgid "Error finding packages"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:124
|
||||
msgid "Can't detect system language"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:141
|
||||
msgid "Error resolving overrides"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:149 info.go:154
|
||||
msgid "Error encoding script variables"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:40
|
||||
msgid "Install a new package"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:52
|
||||
msgid "Command install expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:114
|
||||
msgid "Error when installing the package"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:159
|
||||
msgid "Remove an installed package"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:118
|
||||
#: install.go:178
|
||||
msgid "Error listing installed packages"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:215
|
||||
msgid "Command remove expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: install.go:130
|
||||
#: install.go:230
|
||||
msgid "Error removing packages"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:75
|
||||
msgid "Error loading config"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:96
|
||||
msgid "Error initialization database"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:135
|
||||
msgid "Error pulling repositories"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:152
|
||||
msgid "Error parsing os release"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:165
|
||||
msgid "Unable to detect a supported package manager on the system"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/prompt.go:60
|
||||
msgid "Would you like to view the build script for %s"
|
||||
msgstr ""
|
||||
@ -182,59 +222,77 @@ msgstr ""
|
||||
msgid "Choose which optional package(s) to install"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:64
|
||||
msgid "Error opening config file, using defaults"
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:93
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:77
|
||||
msgid "Error decoding config file, using defaults"
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:94
|
||||
msgid "USAGE"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:89
|
||||
msgid "Unable to detect user config directory"
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "global options"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:97
|
||||
msgid "Unable to create ALR config directory"
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "command"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:106
|
||||
msgid "Unable to create ALR config file"
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:95
|
||||
msgid "command options"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:112
|
||||
msgid "Error encoding default configuration"
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:96
|
||||
msgid "arguments"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:121
|
||||
msgid "Unable to detect cache directory"
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "VERSION"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:131
|
||||
msgid "Unable to create repo cache directory"
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:98
|
||||
msgid "DESCRIPTION"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:137
|
||||
msgid "Unable to create package cache directory"
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "AUTHOR"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/lang.go:49
|
||||
msgid "Error parsing system language"
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "COMMANDS"
|
||||
msgstr ""
|
||||
|
||||
#: internal/db/db.go:131
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "GLOBAL OPTIONS"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "COPYRIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/template.go:97
|
||||
msgid "CATEGORY"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/template.go:99 internal/cliutils/template.go:100
|
||||
msgid "OPTIONS"
|
||||
msgstr ""
|
||||
|
||||
#: internal/cliutils/utils.go:69
|
||||
msgid ""
|
||||
"This command is deprecated and would be removed in the future, use \"%s\" "
|
||||
"instead!"
|
||||
msgstr ""
|
||||
|
||||
#: internal/db/db.go:137
|
||||
msgid "Database version mismatch; resetting"
|
||||
msgstr ""
|
||||
|
||||
#: internal/db/db.go:138
|
||||
#: internal/db/db.go:144
|
||||
msgid ""
|
||||
"Database version does not exist. Run alr fix if something isn't working."
|
||||
msgstr ""
|
||||
|
||||
#: internal/db/db_legacy.go:101
|
||||
msgid "Error opening database"
|
||||
msgstr ""
|
||||
|
||||
#: internal/dl/dl.go:170
|
||||
msgid "Source can be updated, updating if required"
|
||||
msgstr ""
|
||||
@ -259,16 +317,44 @@ msgstr ""
|
||||
msgid "%s %s downloading at %s/s\n"
|
||||
msgstr ""
|
||||
|
||||
#: internal/logger/log.go:47
|
||||
#: internal/logger/log.go:41
|
||||
msgid "ERROR"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:40
|
||||
#: internal/utils/cmd.go:97
|
||||
msgid "Error on dropping capabilities"
|
||||
msgstr ""
|
||||
|
||||
#: internal/utils/cmd.go:164
|
||||
msgid "You need to be a %s member to perform this action"
|
||||
msgstr ""
|
||||
|
||||
#: internal/utils/cmd.go:200
|
||||
msgid "You need to be root to perform this action"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:43
|
||||
msgid "List ALR repo packages"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:91
|
||||
msgid "Error listing installed packages"
|
||||
#: list.go:57
|
||||
msgid "Format output using a Go template"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:89
|
||||
msgid "Error getting packages for upgrade"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:92
|
||||
msgid "No packages for upgrade"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:102 list.go:187
|
||||
msgid "Error parsing format template"
|
||||
msgstr ""
|
||||
|
||||
#: list.go:108 list.go:191
|
||||
msgid "Error executing template"
|
||||
msgstr ""
|
||||
|
||||
#: main.go:45
|
||||
@ -283,184 +369,190 @@ msgstr ""
|
||||
msgid "Enable interactive questions and prompts"
|
||||
msgstr ""
|
||||
|
||||
#: main.go:90
|
||||
msgid ""
|
||||
"Running ALR as root is forbidden as it may cause catastrophic damage to your "
|
||||
"system"
|
||||
#: main.go:146
|
||||
msgid "Show help"
|
||||
msgstr ""
|
||||
|
||||
#: main.go:124
|
||||
#: main.go:150
|
||||
msgid "Error while running app"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:108
|
||||
msgid "Failed to prompt user to view build script"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:112
|
||||
#: pkg/build/build.go:395
|
||||
msgid "Building package"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:156
|
||||
#: pkg/build/build.go:424
|
||||
msgid "The checksums array must be the same length as sources"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:455
|
||||
msgid "Downloading sources"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:168
|
||||
msgid "Building package metadata"
|
||||
#: pkg/build/build.go:549
|
||||
msgid "Installing dependencies"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:190
|
||||
msgid "Compressing package"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:316
|
||||
#: pkg/build/checker.go:43
|
||||
msgid ""
|
||||
"Your system's CPU architecture doesn't match this package. Do you want to "
|
||||
"build anyway?"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:327
|
||||
#: pkg/build/checker.go:67
|
||||
msgid "This package is already installed"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:355
|
||||
msgid "Installing build dependencies"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:397
|
||||
msgid "Installing dependencies"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:443
|
||||
msgid "Executing version()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:463
|
||||
msgid "Updating version"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:468
|
||||
msgid "Executing prepare()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:478
|
||||
msgid "Executing build()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:488
|
||||
msgid "Executing package()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:510
|
||||
msgid "Executing files()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:588
|
||||
msgid "AutoProv is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:599
|
||||
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:706
|
||||
msgid "Would you like to remove the build dependencies?"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/build.go:812
|
||||
msgid "The checksums array must be the same length as sources"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/findDeps.go:35
|
||||
#: pkg/build/find_deps/alt_linux.go:35
|
||||
msgid "Command not found on the system"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/findDeps.go:82
|
||||
#: pkg/build/find_deps/alt_linux.go:86
|
||||
msgid "Provided dependency found"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/findDeps.go:89
|
||||
#: pkg/build/find_deps/alt_linux.go:93
|
||||
msgid "Required dependency found"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/install.go:42
|
||||
msgid "Error installing native packages"
|
||||
#: pkg/build/find_deps/empty.go:32
|
||||
msgid "AutoProv is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/install.go:79
|
||||
msgid "Error installing package"
|
||||
#: pkg/build/find_deps/empty.go:37
|
||||
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/repos/pull.go:75
|
||||
#: pkg/build/script_executor.go:241
|
||||
msgid "Building package metadata"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/script_executor.go:372
|
||||
msgid "Executing prepare()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/script_executor.go:381
|
||||
msgid "Executing build()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/build/script_executor.go:410 pkg/build/script_executor.go:430
|
||||
msgid "Executing %s()"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/repos/pull.go:77
|
||||
msgid "Pulling repository"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/repos/pull.go:99
|
||||
#: pkg/repos/pull.go:113
|
||||
msgid "Repository up to date"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/repos/pull.go:156
|
||||
#: pkg/repos/pull.go:204
|
||||
msgid "Git repository does not appear to be a valid ALR repo"
|
||||
msgstr ""
|
||||
|
||||
#: pkg/repos/pull.go:172
|
||||
#: pkg/repos/pull.go:220
|
||||
msgid ""
|
||||
"ALR repo's minimum ALR version is greater than the current version. Try "
|
||||
"updating ALR if something doesn't work."
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:41
|
||||
msgid "Add a new repository"
|
||||
#: refresh.go:30
|
||||
msgid "Pull all repositories that have changed"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:48
|
||||
msgid "Name of the new repo"
|
||||
#: repo.go:39
|
||||
msgid "Manage repos"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:54
|
||||
msgid "URL of the new repo"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:79 repo.go:136
|
||||
msgid "Error opening config file"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:85 repo.go:142
|
||||
msgid "Error encoding config"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:103
|
||||
#: repo.go:51 repo.go:269
|
||||
msgid "Remove an existing repository"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:110
|
||||
msgid "Name of the repo to be deleted"
|
||||
#: repo.go:53
|
||||
msgid "<name>"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:128
|
||||
msgid "Repo does not exist"
|
||||
#: repo.go:83
|
||||
msgid "Repo \"%s\" does not exist"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:148
|
||||
#: repo.go:90
|
||||
msgid "Error removing repo directory"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:154
|
||||
#: repo.go:94 repo.go:161 repo.go:219
|
||||
msgid "Error saving config"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:113
|
||||
msgid "Error removing packages from database"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:166
|
||||
msgid "Pull all repositories that have changed"
|
||||
#: repo.go:124 repo.go:239
|
||||
msgid "Add a new repository"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:125
|
||||
msgid "<name> <url>"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:150
|
||||
msgid "Repo \"%s\" already exists"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:187
|
||||
msgid "Set the reference of the repository"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:188
|
||||
msgid "<name> <ref>"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:246
|
||||
msgid "Name of the new repo"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:252
|
||||
msgid "URL of the new repo"
|
||||
msgstr ""
|
||||
|
||||
#: repo.go:276
|
||||
msgid "Name of the repo to be deleted"
|
||||
msgstr ""
|
||||
|
||||
#: search.go:40
|
||||
msgid "Search packages"
|
||||
msgstr ""
|
||||
|
||||
#: search.go:51
|
||||
msgid "Search by name"
|
||||
msgstr ""
|
||||
|
||||
#: search.go:56
|
||||
msgid "Search by description"
|
||||
msgstr ""
|
||||
|
||||
#: search.go:61
|
||||
msgid "Search by repository"
|
||||
msgstr ""
|
||||
|
||||
#: search.go:66
|
||||
msgid "Search by provides"
|
||||
msgstr ""
|
||||
|
||||
#: search.go:130
|
||||
msgid "Error while executing search"
|
||||
msgstr ""
|
||||
|
||||
#: upgrade.go:47
|
||||
msgid "Upgrade all installed packages"
|
||||
msgstr ""
|
||||
|
||||
#: upgrade.go:83
|
||||
#: upgrade.go:105 upgrade.go:122
|
||||
msgid "Error checking for updates"
|
||||
msgstr ""
|
||||
|
||||
#: upgrade.go:94
|
||||
#: upgrade.go:125
|
||||
msgid "There is nothing to do."
|
||||
msgstr ""
|
||||
|
@ -1,86 +1,98 @@
|
||||
#
|
||||
# Maxim Slipenko <maks1ms@alt-gnome.ru>, 2025.
|
||||
# x1z53 <x1z53@yandex.ru>, 2025.
|
||||
# Maxim Slipenko <maks1ms@alt-gnome.ru>, 2025.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: unnamed project\n"
|
||||
"PO-Revision-Date: 2025-01-24 21:20+0300\n"
|
||||
"Last-Translator: x1z53 <x1z53@yandex.ru>\n"
|
||||
"PO-Revision-Date: 2025-05-16 20:47+0300\n"
|
||||
"Last-Translator: Maxim Slipenko <maks1ms@alt-gnome.ru>\n"
|
||||
"Language-Team: Russian\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Gtranslator 47.1\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Gtranslator 48.0\n"
|
||||
|
||||
#: build.go:41
|
||||
#: build.go:42
|
||||
msgid "Build a local package"
|
||||
msgstr "Сборка локального пакета"
|
||||
|
||||
#: build.go:47
|
||||
#: build.go:48
|
||||
msgid "Path to the build script"
|
||||
msgstr "Путь к скрипту сборки"
|
||||
|
||||
#: build.go:52
|
||||
#: build.go:53
|
||||
msgid "Specify subpackage in script (for multi package script only)"
|
||||
msgstr "Укажите подпакет в скрипте (только для многопакетного скрипта)"
|
||||
|
||||
#: build.go:58
|
||||
msgid "Name of the package to build and its repo (example: default/go-bin)"
|
||||
msgstr "Имя пакета для сборки и его репозиторий (пример: default/go-bin)"
|
||||
|
||||
#: build.go:57
|
||||
#: build.go:63
|
||||
msgid ""
|
||||
"Build package from scratch even if there's an already built package available"
|
||||
msgstr "Создайте пакет с нуля, даже если уже имеется готовый пакет"
|
||||
|
||||
#: build.go:87
|
||||
msgid "Error pulling repositories"
|
||||
msgstr "Ошибка при извлечении репозиториев"
|
||||
|
||||
#: build.go:95
|
||||
msgid "Unable to detect a supported package manager on the system"
|
||||
msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе"
|
||||
|
||||
#: build.go:107
|
||||
msgid "Error building package"
|
||||
msgstr "Ошибка при сборке пакета"
|
||||
|
||||
#: build.go:114
|
||||
#: build.go:73
|
||||
msgid "Error getting working directory"
|
||||
msgstr "Ошибка при получении рабочего каталога"
|
||||
|
||||
#: build.go:123
|
||||
#: build.go:118
|
||||
msgid "Cannot get absolute script path"
|
||||
msgstr "Невозможно получить абсолютный путь к скрипту"
|
||||
|
||||
#: build.go:152
|
||||
msgid "Package not found"
|
||||
msgstr "Пакет не найден"
|
||||
|
||||
#: build.go:165
|
||||
msgid "Nothing to build"
|
||||
msgstr "Нечего собирать"
|
||||
|
||||
#: build.go:222
|
||||
msgid "Error building package"
|
||||
msgstr "Ошибка при сборке пакета"
|
||||
|
||||
#: build.go:229
|
||||
msgid "Error moving the package"
|
||||
msgstr "Ошибка при перемещении пакета"
|
||||
|
||||
#: fix.go:37
|
||||
#: build.go:233
|
||||
msgid "Done"
|
||||
msgstr "Сделано"
|
||||
|
||||
#: fix.go:38
|
||||
msgid "Attempt to fix problems with ALR"
|
||||
msgstr "Попытка устранить проблемы с ALR"
|
||||
|
||||
#: fix.go:44
|
||||
msgid "Removing cache directory"
|
||||
msgstr "Удаление каталога кэша"
|
||||
#: fix.go:59
|
||||
msgid "Clearing cache directory"
|
||||
msgstr "Очистка каталога кэша"
|
||||
|
||||
#: fix.go:48
|
||||
msgid "Unable to remove cache directory"
|
||||
msgstr "Не удалось удалить каталог кэша"
|
||||
#: fix.go:64
|
||||
msgid "Unable to open cache directory"
|
||||
msgstr "Невозможно открыть каталог кэша"
|
||||
|
||||
#: fix.go:52
|
||||
#: fix.go:70
|
||||
msgid "Unable to read cache directory contents"
|
||||
msgstr "Невозможно прочитать содержимое каталога кэша"
|
||||
|
||||
#: fix.go:76
|
||||
msgid "Unable to remove cache item (%s)"
|
||||
msgstr "Невозможно удалить элемент кэша (%s)"
|
||||
|
||||
#: fix.go:80
|
||||
msgid "Rebuilding cache"
|
||||
msgstr "Восстановление кэша"
|
||||
|
||||
#: fix.go:56
|
||||
#: fix.go:84
|
||||
msgid "Unable to create new cache directory"
|
||||
msgstr "Не удалось создать новый каталог кэша"
|
||||
|
||||
#: fix.go:62
|
||||
msgid "Error pulling repos"
|
||||
msgstr "Ошибка при извлечении репозиториев"
|
||||
|
||||
#: fix.go:66
|
||||
msgid "Done"
|
||||
msgstr "Сделано"
|
||||
|
||||
#: gen.go:34
|
||||
msgid "Generate a ALR script from a template"
|
||||
msgstr "Генерация скрипта ALR из шаблона"
|
||||
@ -89,22 +101,26 @@ msgstr "Генерация скрипта ALR из шаблона"
|
||||
msgid "Generate a ALR script for a pip module"
|
||||
msgstr "Генерация скрипта ALR для модуля pip"
|
||||
|
||||
#: helper.go:41
|
||||
#: helper.go:42
|
||||
msgid "List all the available helper commands"
|
||||
msgstr "Список всех доступных вспомогательных команды"
|
||||
|
||||
#: helper.go:53
|
||||
#: helper.go:54
|
||||
msgid "Run a ALR helper command"
|
||||
msgstr "Запустить вспомогательную команду ALR"
|
||||
|
||||
#: helper.go:60
|
||||
#: helper.go:61
|
||||
msgid "The directory that the install commands will install to"
|
||||
msgstr "Каталог, в который будут устанавливать команды установки"
|
||||
|
||||
#: helper.go:73
|
||||
#: helper.go:74 helper.go:75
|
||||
msgid "No such helper command"
|
||||
msgstr "Такой вспомогательной команды нет"
|
||||
|
||||
#: helper.go:85
|
||||
msgid "Error parsing os-release file"
|
||||
msgstr "Ошибка при разборе файла выпуска операционной системы"
|
||||
|
||||
#: info.go:42
|
||||
msgid "Print information about a package"
|
||||
msgstr "Отобразить информацию о пакете"
|
||||
@ -113,58 +129,82 @@ msgstr "Отобразить информацию о пакете"
|
||||
msgid "Show all information, not just for the current distro"
|
||||
msgstr "Показывать всю информацию, не только для текущего дистрибутива"
|
||||
|
||||
#: info.go:57
|
||||
msgid "Error initialization database"
|
||||
msgstr "Ошибка инициализации базы данных"
|
||||
|
||||
#: info.go:64
|
||||
msgid "Command info expected at least 1 argument, got %d"
|
||||
msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d"
|
||||
|
||||
#: info.go:78
|
||||
msgid "Error finding packages"
|
||||
msgstr "Ошибка при поиске пакетов"
|
||||
|
||||
#: info.go:94
|
||||
msgid "Error parsing os-release file"
|
||||
msgstr "Ошибка при разборе файла выпуска операционной системы"
|
||||
|
||||
#: info.go:103
|
||||
msgid "Error resolving overrides"
|
||||
msgstr "Ошибка устранения переорпеделений"
|
||||
|
||||
#: info.go:112 info.go:118
|
||||
msgid "Error encoding script variables"
|
||||
msgstr "Ошибка кодирования переменных скрита"
|
||||
|
||||
#: install.go:42
|
||||
msgid "Install a new package"
|
||||
msgstr "Установить новый пакет"
|
||||
|
||||
#: install.go:56
|
||||
msgid "Command install expected at least 1 argument, got %d"
|
||||
msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d"
|
||||
|
||||
#: install.go:91
|
||||
#: info.go:68
|
||||
msgid "Error getting packages"
|
||||
msgstr "Ошибка при получении пакетов"
|
||||
|
||||
#: install.go:100
|
||||
#: info.go:76
|
||||
msgid "Error iterating over packages"
|
||||
msgstr "Ошибка при переборе пакетов"
|
||||
|
||||
#: install.go:113
|
||||
#: info.go:90
|
||||
msgid "Command info expected at least 1 argument, got %d"
|
||||
msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d"
|
||||
|
||||
#: info.go:110
|
||||
msgid "Error finding packages"
|
||||
msgstr "Ошибка при поиске пакетов"
|
||||
|
||||
#: info.go:124
|
||||
msgid "Can't detect system language"
|
||||
msgstr "Ошибка при определении языка системы"
|
||||
|
||||
#: info.go:141
|
||||
msgid "Error resolving overrides"
|
||||
msgstr "Ошибка устранения переорпеделений"
|
||||
|
||||
#: info.go:149 info.go:154
|
||||
msgid "Error encoding script variables"
|
||||
msgstr "Ошибка кодирования переменных скрита"
|
||||
|
||||
#: install.go:40
|
||||
msgid "Install a new package"
|
||||
msgstr "Установить новый пакет"
|
||||
|
||||
#: install.go:52
|
||||
msgid "Command install expected at least 1 argument, got %d"
|
||||
msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d"
|
||||
|
||||
#: install.go:114
|
||||
msgid "Error when installing the package"
|
||||
msgstr "Ошибка при установке пакета"
|
||||
|
||||
#: install.go:159
|
||||
msgid "Remove an installed package"
|
||||
msgstr "Удалить установленный пакет"
|
||||
|
||||
#: install.go:118
|
||||
#: install.go:178
|
||||
msgid "Error listing installed packages"
|
||||
msgstr "Ошибка при составлении списка установленных пакетов"
|
||||
|
||||
#: install.go:215
|
||||
msgid "Command remove expected at least 1 argument, got %d"
|
||||
msgstr "Для команды remove ожидался хотя бы 1 аргумент, получено %d"
|
||||
|
||||
#: install.go:130
|
||||
#: install.go:230
|
||||
msgid "Error removing packages"
|
||||
msgstr "Ошибка при удалении пакетов"
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:75
|
||||
msgid "Error loading config"
|
||||
msgstr "Ошибка при загрузке"
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:96
|
||||
msgid "Error initialization database"
|
||||
msgstr "Ошибка инициализации базы данных"
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:135
|
||||
msgid "Error pulling repositories"
|
||||
msgstr "Ошибка при извлечении репозиториев"
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:152
|
||||
msgid "Error parsing os release"
|
||||
msgstr "Ошибка при разборе файла выпуска операционной системы"
|
||||
|
||||
#: internal/cliutils/app_builder/builder.go:165
|
||||
msgid "Unable to detect a supported package manager on the system"
|
||||
msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе"
|
||||
|
||||
#: internal/cliutils/prompt.go:60
|
||||
msgid "Would you like to view the build script for %s"
|
||||
msgstr "Показать скрипт для пакета %s"
|
||||
@ -189,64 +229,80 @@ msgstr "Выберите, какой пакет использовать для
|
||||
msgid "Choose which optional package(s) to install"
|
||||
msgstr "Выберите, какой дополнительный пакет(ы) следует установить"
|
||||
|
||||
#: internal/config/config.go:64
|
||||
msgid "Error opening config file, using defaults"
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:93
|
||||
msgid "NAME"
|
||||
msgstr "НАЗВАНИЕ"
|
||||
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:94
|
||||
msgid "USAGE"
|
||||
msgstr "ИСПОЛЬЗОВАНИЕ"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "global options"
|
||||
msgstr "глобальные опции"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "command"
|
||||
msgstr "команда"
|
||||
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:95
|
||||
msgid "command options"
|
||||
msgstr "опции команды"
|
||||
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:96
|
||||
msgid "arguments"
|
||||
msgstr "аргументы"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "VERSION"
|
||||
msgstr "ВЕРСИЯ"
|
||||
|
||||
#: internal/cliutils/template.go:74 internal/cliutils/template.go:98
|
||||
msgid "DESCRIPTION"
|
||||
msgstr "ОПИСАНИЕ"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "AUTHOR"
|
||||
msgstr "АВТОР"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "COMMANDS"
|
||||
msgstr "КОМАНДЫ"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "GLOBAL OPTIONS"
|
||||
msgstr "ГЛОБАЛЬНЫЕ ОПЦИИ"
|
||||
|
||||
#: internal/cliutils/template.go:74
|
||||
msgid "COPYRIGHT"
|
||||
msgstr "АВТОРСКОЕ ПРАВО"
|
||||
|
||||
#: internal/cliutils/template.go:97
|
||||
msgid "CATEGORY"
|
||||
msgstr "КАТЕГОРИЯ"
|
||||
|
||||
#: internal/cliutils/template.go:99 internal/cliutils/template.go:100
|
||||
msgid "OPTIONS"
|
||||
msgstr "ПАРАМЕТРЫ"
|
||||
|
||||
#: internal/cliutils/utils.go:69
|
||||
msgid ""
|
||||
"This command is deprecated and would be removed in the future, use \"%s\" "
|
||||
"instead!"
|
||||
msgstr ""
|
||||
"Ошибка при открытии конфигурационного файла, используются значения по "
|
||||
"умолчанию"
|
||||
"Эта команда устарела и будет удалена в будущем, используйте вместо нее "
|
||||
"\"%s\"!"
|
||||
|
||||
#: internal/config/config.go:77
|
||||
msgid "Error decoding config file, using defaults"
|
||||
msgstr ""
|
||||
"Ошибка при декодировании конфигурационного файла, используются значения по "
|
||||
"умолчанию"
|
||||
|
||||
#: internal/config/config.go:89
|
||||
msgid "Unable to detect user config directory"
|
||||
msgstr "Не удалось обнаружить каталог конфигурации пользователя"
|
||||
|
||||
#: internal/config/config.go:97
|
||||
msgid "Unable to create ALR config directory"
|
||||
msgstr "Не удалось создать каталог конфигурации ALR"
|
||||
|
||||
#: internal/config/config.go:106
|
||||
msgid "Unable to create ALR config file"
|
||||
msgstr "Не удалось создать конфигурационный файл ALR"
|
||||
|
||||
#: internal/config/config.go:112
|
||||
msgid "Error encoding default configuration"
|
||||
msgstr "Ошибка кодирования конфигурации по умолчанию"
|
||||
|
||||
#: internal/config/config.go:121
|
||||
msgid "Unable to detect cache directory"
|
||||
msgstr "Не удалось обнаружить каталог кэша"
|
||||
|
||||
#: internal/config/config.go:131
|
||||
msgid "Unable to create repo cache directory"
|
||||
msgstr "Не удалось создать каталог кэша репозитория"
|
||||
|
||||
#: internal/config/config.go:137
|
||||
msgid "Unable to create package cache directory"
|
||||
msgstr "Не удалось создать каталог кэша пакетов"
|
||||
|
||||
#: internal/config/lang.go:49
|
||||
msgid "Error parsing system language"
|
||||
msgstr "Ошибка при парсинге языка системы"
|
||||
|
||||
#: internal/db/db.go:131
|
||||
#: internal/db/db.go:137
|
||||
msgid "Database version mismatch; resetting"
|
||||
msgstr "Несоответствие версий базы данных; сброс настроек"
|
||||
|
||||
#: internal/db/db.go:138
|
||||
#: internal/db/db.go:144
|
||||
msgid ""
|
||||
"Database version does not exist. Run alr fix if something isn't working."
|
||||
msgstr ""
|
||||
"Версия базы данных не существует. Запустите alr fix, если что-то не работает."
|
||||
|
||||
#: internal/db/db_legacy.go:101
|
||||
msgid "Error opening database"
|
||||
msgstr "Ошибка при открытии базы данных"
|
||||
|
||||
#: internal/dl/dl.go:170
|
||||
msgid "Source can be updated, updating if required"
|
||||
msgstr "Исходный код можно обновлять, обновляя при необходимости"
|
||||
@ -265,23 +321,51 @@ msgstr "Скачивание источника"
|
||||
|
||||
#: internal/dl/progress_tui.go:100
|
||||
msgid "%s: done!\n"
|
||||
msgstr ""
|
||||
msgstr "%s: выполнено!\n"
|
||||
|
||||
#: internal/dl/progress_tui.go:104
|
||||
msgid "%s %s downloading at %s/s\n"
|
||||
msgstr ""
|
||||
msgstr "%s %s загружается — %s/с\n"
|
||||
|
||||
#: internal/logger/log.go:47
|
||||
#: internal/logger/log.go:41
|
||||
msgid "ERROR"
|
||||
msgstr "ОШИБКА"
|
||||
|
||||
#: list.go:40
|
||||
#: internal/utils/cmd.go:97
|
||||
msgid "Error on dropping capabilities"
|
||||
msgstr "Ошибка при понижении привилегий"
|
||||
|
||||
#: internal/utils/cmd.go:164
|
||||
msgid "You need to be a %s member to perform this action"
|
||||
msgstr "Вы должны быть членом %s чтобы выполнить это"
|
||||
|
||||
#: internal/utils/cmd.go:200
|
||||
msgid "You need to be root to perform this action"
|
||||
msgstr "Вы должны быть root чтобы выполнить это"
|
||||
|
||||
#: list.go:43
|
||||
msgid "List ALR repo packages"
|
||||
msgstr "Список пакетов репозитория ALR"
|
||||
|
||||
#: list.go:91
|
||||
msgid "Error listing installed packages"
|
||||
msgstr "Ошибка при составлении списка установленных пакетов"
|
||||
#: list.go:57
|
||||
msgid "Format output using a Go template"
|
||||
msgstr "Формат выходных данных с использованием шаблона Go"
|
||||
|
||||
#: list.go:89
|
||||
msgid "Error getting packages for upgrade"
|
||||
msgstr "Ошибка при получении пакетов для обновления"
|
||||
|
||||
#: list.go:92
|
||||
msgid "No packages for upgrade"
|
||||
msgstr "Нет пакетов к обновлению"
|
||||
|
||||
#: list.go:102 list.go:187
|
||||
msgid "Error parsing format template"
|
||||
msgstr "Ошибка при разборе шаблона"
|
||||
|
||||
#: list.go:108 list.go:191
|
||||
msgid "Error executing template"
|
||||
msgstr "Ошибка при выполнении шаблона"
|
||||
|
||||
#: main.go:45
|
||||
msgid "Print the current ALR version and exit"
|
||||
@ -295,39 +379,31 @@ msgstr "Аргументы, которые будут переданы мене
|
||||
msgid "Enable interactive questions and prompts"
|
||||
msgstr "Включение интерактивных вопросов и запросов"
|
||||
|
||||
#: main.go:90
|
||||
msgid ""
|
||||
"Running ALR as root is forbidden as it may cause catastrophic damage to your "
|
||||
"system"
|
||||
msgstr ""
|
||||
"Запуск ALR от имени root запрещён, так как это может привести к "
|
||||
"катастрофическому повреждению вашей системы"
|
||||
#: main.go:146
|
||||
msgid "Show help"
|
||||
msgstr "Показать справку"
|
||||
|
||||
#: main.go:124
|
||||
#: main.go:150
|
||||
msgid "Error while running app"
|
||||
msgstr "Ошибка при запуске приложения"
|
||||
|
||||
#: pkg/build/build.go:108
|
||||
msgid "Failed to prompt user to view build script"
|
||||
msgstr "Не удалось предложить пользователю просмотреть скрипт сборки"
|
||||
|
||||
#: pkg/build/build.go:112
|
||||
#: pkg/build/build.go:395
|
||||
msgid "Building package"
|
||||
msgstr "Сборка пакета"
|
||||
|
||||
#: pkg/build/build.go:156
|
||||
#: pkg/build/build.go:424
|
||||
msgid "The checksums array must be the same length as sources"
|
||||
msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
|
||||
|
||||
#: pkg/build/build.go:455
|
||||
msgid "Downloading sources"
|
||||
msgstr "Скачивание источников"
|
||||
|
||||
#: pkg/build/build.go:168
|
||||
msgid "Building package metadata"
|
||||
msgstr "Сборка метаданных пакета"
|
||||
#: pkg/build/build.go:549
|
||||
msgid "Installing dependencies"
|
||||
msgstr "Установка зависимостей"
|
||||
|
||||
#: pkg/build/build.go:190
|
||||
msgid "Compressing package"
|
||||
msgstr "Сжатие пакета"
|
||||
|
||||
#: pkg/build/build.go:316
|
||||
#: pkg/build/checker.go:43
|
||||
msgid ""
|
||||
"Your system's CPU architecture doesn't match this package. Do you want to "
|
||||
"build anyway?"
|
||||
@ -335,93 +411,61 @@ msgstr ""
|
||||
"Архитектура процессора вашей системы не соответствует этому пакету. Вы все "
|
||||
"равно хотите выполнить сборку?"
|
||||
|
||||
#: pkg/build/build.go:327
|
||||
#: pkg/build/checker.go:67
|
||||
msgid "This package is already installed"
|
||||
msgstr "Этот пакет уже установлен"
|
||||
|
||||
#: pkg/build/build.go:355
|
||||
msgid "Installing build dependencies"
|
||||
msgstr "Установка зависимостей сборки"
|
||||
#: pkg/build/find_deps/alt_linux.go:35
|
||||
msgid "Command not found on the system"
|
||||
msgstr "Команда не найдена в системе"
|
||||
|
||||
#: pkg/build/build.go:397
|
||||
msgid "Installing dependencies"
|
||||
msgstr "Установка зависимостей"
|
||||
#: pkg/build/find_deps/alt_linux.go:86
|
||||
msgid "Provided dependency found"
|
||||
msgstr "Найденная предоставленная зависимость"
|
||||
|
||||
#: pkg/build/build.go:443
|
||||
msgid "Executing version()"
|
||||
msgstr "Исполнение версия()"
|
||||
#: pkg/build/find_deps/alt_linux.go:93
|
||||
msgid "Required dependency found"
|
||||
msgstr "Найдена требуемая зависимость"
|
||||
|
||||
#: pkg/build/build.go:463
|
||||
msgid "Updating version"
|
||||
msgstr "Обновление версии"
|
||||
|
||||
#: pkg/build/build.go:468
|
||||
msgid "Executing prepare()"
|
||||
msgstr "Исполнение prepare()"
|
||||
|
||||
#: pkg/build/build.go:478
|
||||
msgid "Executing build()"
|
||||
msgstr "Исполнение build()"
|
||||
|
||||
#: pkg/build/build.go:488
|
||||
msgid "Executing package()"
|
||||
msgstr "Исполнение package()"
|
||||
|
||||
#: pkg/build/build.go:510
|
||||
msgid "Executing files()"
|
||||
msgstr "Исполнение files()"
|
||||
|
||||
#: pkg/build/build.go:588
|
||||
#: pkg/build/find_deps/empty.go:32
|
||||
msgid "AutoProv is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
"AutoProv не реализовано для этого формата пакета, поэтому будет пропущено"
|
||||
|
||||
#: pkg/build/build.go:599
|
||||
#: pkg/build/find_deps/empty.go:37
|
||||
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||
msgstr ""
|
||||
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
|
||||
|
||||
#: pkg/build/build.go:706
|
||||
msgid "Would you like to remove the build dependencies?"
|
||||
msgstr "Хотели бы вы удалить зависимости сборки?"
|
||||
#: pkg/build/script_executor.go:241
|
||||
msgid "Building package metadata"
|
||||
msgstr "Сборка метаданных пакета"
|
||||
|
||||
#: pkg/build/build.go:812
|
||||
msgid "The checksums array must be the same length as sources"
|
||||
msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
|
||||
#: pkg/build/script_executor.go:372
|
||||
msgid "Executing prepare()"
|
||||
msgstr "Выполнение prepare()"
|
||||
|
||||
#: pkg/build/findDeps.go:35
|
||||
msgid "Command not found on the system"
|
||||
msgstr "Команда не найдена в системе"
|
||||
#: pkg/build/script_executor.go:381
|
||||
msgid "Executing build()"
|
||||
msgstr "Выполнение build()"
|
||||
|
||||
#: pkg/build/findDeps.go:82
|
||||
msgid "Provided dependency found"
|
||||
msgstr "Найденная предоставленная зависимость"
|
||||
#: pkg/build/script_executor.go:410 pkg/build/script_executor.go:430
|
||||
msgid "Executing %s()"
|
||||
msgstr "Выполнение %s()"
|
||||
|
||||
#: pkg/build/findDeps.go:89
|
||||
msgid "Required dependency found"
|
||||
msgstr "Найдена требуемая зависимость"
|
||||
|
||||
#: pkg/build/install.go:42
|
||||
msgid "Error installing native packages"
|
||||
msgstr "Ошибка при установке нативных пакетов"
|
||||
|
||||
#: pkg/build/install.go:79
|
||||
msgid "Error installing package"
|
||||
msgstr "Ошибка при установке пакета"
|
||||
|
||||
#: pkg/repos/pull.go:75
|
||||
#: pkg/repos/pull.go:77
|
||||
msgid "Pulling repository"
|
||||
msgstr "Скачивание репозитория"
|
||||
|
||||
#: pkg/repos/pull.go:99
|
||||
#: pkg/repos/pull.go:113
|
||||
msgid "Repository up to date"
|
||||
msgstr "Репозиторий уже обновлён"
|
||||
|
||||
#: pkg/repos/pull.go:156
|
||||
#: pkg/repos/pull.go:204
|
||||
msgid "Git repository does not appear to be a valid ALR repo"
|
||||
msgstr "Репозиторий Git не поддерживается репозиторием ALR"
|
||||
|
||||
#: pkg/repos/pull.go:172
|
||||
#: pkg/repos/pull.go:220
|
||||
msgid ""
|
||||
"ALR repo's minimum ALR version is greater than the current version. Try "
|
||||
"updating ALR if something doesn't work."
|
||||
@ -429,58 +473,179 @@ msgstr ""
|
||||
"Минимальная версия ALR для ALR-репозитория выше текущей версии. Попробуйте "
|
||||
"обновить ALR, если что-то не работает."
|
||||
|
||||
#: repo.go:41
|
||||
msgid "Add a new repository"
|
||||
msgstr "Добавить новый репозиторий"
|
||||
#: refresh.go:30
|
||||
msgid "Pull all repositories that have changed"
|
||||
msgstr "Скачать все изменённые репозитории"
|
||||
|
||||
#: repo.go:48
|
||||
msgid "Name of the new repo"
|
||||
msgstr "Название нового репозитория"
|
||||
#: repo.go:39
|
||||
msgid "Manage repos"
|
||||
msgstr "Управление репозиториями"
|
||||
|
||||
#: repo.go:54
|
||||
msgid "URL of the new repo"
|
||||
msgstr "URL-адрес нового репозитория"
|
||||
|
||||
#: repo.go:79 repo.go:136
|
||||
msgid "Error opening config file"
|
||||
msgstr "Ошибка при открытии конфигурационного файла"
|
||||
|
||||
#: repo.go:85 repo.go:142
|
||||
msgid "Error encoding config"
|
||||
msgstr "Ошибка при кодировании конфигурации"
|
||||
|
||||
#: repo.go:103
|
||||
#: repo.go:51 repo.go:269
|
||||
msgid "Remove an existing repository"
|
||||
msgstr "Удалить существующий репозиторий"
|
||||
|
||||
#: repo.go:110
|
||||
msgid "Name of the repo to be deleted"
|
||||
msgstr "Название репозитория удалён"
|
||||
#: repo.go:53
|
||||
msgid "<name>"
|
||||
msgstr "<имя>"
|
||||
|
||||
#: repo.go:128
|
||||
msgid "Repo does not exist"
|
||||
msgstr "Репозитория не существует"
|
||||
#: repo.go:83
|
||||
msgid "Repo \"%s\" does not exist"
|
||||
msgstr "Репозитория \"%s\" не существует"
|
||||
|
||||
#: repo.go:148
|
||||
#: repo.go:90
|
||||
msgid "Error removing repo directory"
|
||||
msgstr "Ошибка при удалении каталога репозитория"
|
||||
|
||||
#: repo.go:154
|
||||
#: repo.go:94 repo.go:161 repo.go:219
|
||||
msgid "Error saving config"
|
||||
msgstr "Ошибка при сохранении конфигурации"
|
||||
|
||||
#: repo.go:113
|
||||
msgid "Error removing packages from database"
|
||||
msgstr "Ошибка при удалении пакетов из базы данных"
|
||||
|
||||
#: repo.go:166
|
||||
msgid "Pull all repositories that have changed"
|
||||
msgstr "Скачать все изменённые репозитории"
|
||||
#: repo.go:124 repo.go:239
|
||||
msgid "Add a new repository"
|
||||
msgstr "Добавить новый репозиторий"
|
||||
|
||||
#: repo.go:125
|
||||
msgid "<name> <url>"
|
||||
msgstr "<имя> <url>"
|
||||
|
||||
#: repo.go:150
|
||||
msgid "Repo \"%s\" already exists"
|
||||
msgstr "Репозиторий \"%s\" уже существует"
|
||||
|
||||
#: repo.go:187
|
||||
msgid "Set the reference of the repository"
|
||||
msgstr "Установить ссылку на версию репозитория"
|
||||
|
||||
#: repo.go:188
|
||||
msgid "<name> <ref>"
|
||||
msgstr "<имя> <ссылка_на_версию>"
|
||||
|
||||
#: repo.go:246
|
||||
msgid "Name of the new repo"
|
||||
msgstr "Название нового репозитория"
|
||||
|
||||
#: repo.go:252
|
||||
msgid "URL of the new repo"
|
||||
msgstr "URL-адрес нового репозитория"
|
||||
|
||||
#: repo.go:276
|
||||
msgid "Name of the repo to be deleted"
|
||||
msgstr "Название репозитория удалён"
|
||||
|
||||
#: search.go:40
|
||||
msgid "Search packages"
|
||||
msgstr "Поиск пакетов"
|
||||
|
||||
#: search.go:51
|
||||
msgid "Search by name"
|
||||
msgstr "Искать по имени"
|
||||
|
||||
#: search.go:56
|
||||
msgid "Search by description"
|
||||
msgstr "Искать по описанию"
|
||||
|
||||
#: search.go:61
|
||||
msgid "Search by repository"
|
||||
msgstr "Искать по репозиторию"
|
||||
|
||||
#: search.go:66
|
||||
msgid "Search by provides"
|
||||
msgstr "Иcкать по provides"
|
||||
|
||||
#: search.go:130
|
||||
msgid "Error while executing search"
|
||||
msgstr "Ошибка при выполнении поиска"
|
||||
|
||||
#: upgrade.go:47
|
||||
msgid "Upgrade all installed packages"
|
||||
msgstr "Обновить все установленные пакеты"
|
||||
|
||||
#: upgrade.go:83
|
||||
#: upgrade.go:105 upgrade.go:122
|
||||
msgid "Error checking for updates"
|
||||
msgstr "Ошибка при проверке обновлений"
|
||||
|
||||
#: upgrade.go:94
|
||||
#: upgrade.go:125
|
||||
msgid "There is nothing to do."
|
||||
msgstr "Здесь нечего делать."
|
||||
|
||||
#~ msgid "Error pulling repos"
|
||||
#~ msgstr "Ошибка при извлечении репозиториев"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Error getting current executable"
|
||||
#~ msgstr "Ошибка при получении рабочего каталога"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Error mounting"
|
||||
#~ msgstr "Ошибка при кодировании конфигурации"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Unable to create config directory"
|
||||
#~ msgstr "Не удалось создать каталог конфигурации ALR"
|
||||
|
||||
#~ msgid "Unable to create repo cache directory"
|
||||
#~ msgstr "Не удалось создать каталог кэша репозитория"
|
||||
|
||||
#~ msgid "Unable to create package cache directory"
|
||||
#~ msgstr "Не удалось создать каталог кэша пакетов"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Running ALR as root is forbidden as it may cause catastrophic damage to "
|
||||
#~ "your system"
|
||||
#~ msgstr ""
|
||||
#~ "Запуск ALR от имени root запрещён, так как это может привести к "
|
||||
#~ "катастрофическому повреждению вашей системы"
|
||||
|
||||
#~ msgid "Failed to prompt user to view build script"
|
||||
#~ msgstr "Не удалось предложить пользователю просмотреть скрипт сборки"
|
||||
|
||||
#~ msgid "Compressing package"
|
||||
#~ msgstr "Сжатие пакета"
|
||||
|
||||
#~ msgid "Installing build dependencies"
|
||||
#~ msgstr "Установка зависимостей сборки"
|
||||
|
||||
#~ msgid "Would you like to remove the build dependencies?"
|
||||
#~ msgstr "Хотели бы вы удалить зависимости сборки?"
|
||||
|
||||
#~ msgid "Error installing native packages"
|
||||
#~ msgstr "Ошибка при установке нативных пакетов"
|
||||
|
||||
#~ msgid "Error opening config file, using defaults"
|
||||
#~ msgstr ""
|
||||
#~ "Ошибка при открытии конфигурационного файла, используются значения по "
|
||||
#~ "умолчанию"
|
||||
|
||||
#~ msgid "Error decoding config file, using defaults"
|
||||
#~ msgstr ""
|
||||
#~ "Ошибка при декодировании конфигурационного файла, используются значения "
|
||||
#~ "по умолчанию"
|
||||
|
||||
#~ msgid "Unable to detect user config directory"
|
||||
#~ msgstr "Не удалось обнаружить каталог конфигурации пользователя"
|
||||
|
||||
#~ msgid "Unable to create ALR config file"
|
||||
#~ msgstr "Не удалось создать конфигурационный файл ALR"
|
||||
|
||||
#~ msgid "Error encoding default configuration"
|
||||
#~ msgstr "Ошибка кодирования конфигурации по умолчанию"
|
||||
|
||||
#~ msgid "Unable to detect cache directory"
|
||||
#~ msgstr "Не удалось обнаружить каталог кэша"
|
||||
|
||||
#~ msgid "Error opening config file"
|
||||
#~ msgstr "Ошибка при открытии конфигурационного файла"
|
||||
|
||||
#~ msgid "Executing version()"
|
||||
#~ msgstr "Исполнение версия()"
|
||||
|
||||
#~ msgid "Updating version"
|
||||
#~ msgstr "Обновление версии"
|
||||
|
||||
#~ msgid "Executing package()"
|
||||
#~ msgstr "Исполнение package()"
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -19,39 +19,52 @@
|
||||
|
||||
package types
|
||||
|
||||
import "gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
|
||||
type BuildOpts struct {
|
||||
Script string
|
||||
Manager manager.Manager
|
||||
Clean bool
|
||||
Interactive bool
|
||||
}
|
||||
|
||||
type BuildVarsPre struct {
|
||||
Version string `sh:"version,required"`
|
||||
Release int `sh:"release,required"`
|
||||
Epoch uint `sh:"epoch"`
|
||||
Summary string `sh:"summary"`
|
||||
Description string `sh:"desc"`
|
||||
Group string `sh:"group"`
|
||||
Homepage string `sh:"homepage"`
|
||||
Maintainer string `sh:"maintainer"`
|
||||
Architectures []string `sh:"architectures"`
|
||||
Licenses []string `sh:"license"`
|
||||
Provides []string `sh:"provides"`
|
||||
Conflicts []string `sh:"conflicts"`
|
||||
Depends []string `sh:"deps"`
|
||||
BuildDepends []string `sh:"build_deps"`
|
||||
OptDepends []string `sh:"opt_deps"`
|
||||
Replaces []string `sh:"replaces"`
|
||||
Sources []string `sh:"sources"`
|
||||
Checksums []string `sh:"checksums"`
|
||||
Backup []string `sh:"backup"`
|
||||
Scripts Scripts `sh:"scripts"`
|
||||
AutoReq []string `sh:"auto_req"`
|
||||
AutoProv []string `sh:"auto_prov"`
|
||||
AutoReqSkipList []string `sh:"auto_req_skiplist"`
|
||||
AutoProvSkipList []string `sh:"auto_prov_skiplist"`
|
||||
}
|
||||
|
||||
func (bv *BuildVarsPre) ToBuildVars() BuildVars {
|
||||
return BuildVars{
|
||||
Name: "",
|
||||
Base: "",
|
||||
BuildVarsPre: *bv,
|
||||
}
|
||||
}
|
||||
|
||||
// BuildVars represents the script variables required
|
||||
// to build a package
|
||||
type BuildVars struct {
|
||||
Name string `sh:"name,required"`
|
||||
Version string `sh:"version,required"`
|
||||
Release int `sh:"release,required"`
|
||||
Epoch uint `sh:"epoch"`
|
||||
Description string `sh:"desc"`
|
||||
Homepage string `sh:"homepage"`
|
||||
Maintainer string `sh:"maintainer"`
|
||||
Architectures []string `sh:"architectures"`
|
||||
Licenses []string `sh:"license"`
|
||||
Provides []string `sh:"provides"`
|
||||
Conflicts []string `sh:"conflicts"`
|
||||
Depends []string `sh:"deps"`
|
||||
BuildDepends []string `sh:"build_deps"`
|
||||
OptDepends []string `sh:"opt_deps"`
|
||||
Replaces []string `sh:"replaces"`
|
||||
Sources []string `sh:"sources"`
|
||||
Checksums []string `sh:"checksums"`
|
||||
Backup []string `sh:"backup"`
|
||||
Scripts Scripts `sh:"scripts"`
|
||||
AutoReq []string `sh:"auto_req"`
|
||||
AutoProv []string `sh:"auto_prov"`
|
||||
Name string `sh:"name,required"`
|
||||
Base string
|
||||
BuildVarsPre
|
||||
}
|
||||
|
||||
type Scripts struct {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -21,20 +21,18 @@ package types
|
||||
|
||||
// Config represents the ALR configuration file
|
||||
type Config struct {
|
||||
RootCmd string `toml:"rootCmd"`
|
||||
PagerStyle string `toml:"pagerStyle"`
|
||||
RootCmd string `toml:"rootCmd" env:"ALR_ROOT_CMD"`
|
||||
UseRootCmd bool `toml:"useRootCmd"`
|
||||
PagerStyle string `toml:"pagerStyle" env:"ALR_PAGER_STYLE"`
|
||||
IgnorePkgUpdates []string `toml:"ignorePkgUpdates"`
|
||||
Repos []Repo `toml:"repo"`
|
||||
Unsafe Unsafe `toml:"unsafe"`
|
||||
AutoPull bool `toml:"autoPull"`
|
||||
AutoPull bool `toml:"autoPull" env:"ALR_AUTOPULL"`
|
||||
LogLevel string `toml:"logLevel" env:"ALR_LOG_LEVEL"`
|
||||
}
|
||||
|
||||
// Repo represents a ALR repo within a configuration file
|
||||
type Repo struct {
|
||||
Name string `toml:"name"`
|
||||
URL string `toml:"url"`
|
||||
}
|
||||
|
||||
type Unsafe struct {
|
||||
AllowRunAsRoot bool `toml:"allowRunAsRoot"`
|
||||
Ref string `toml:"ref"`
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
|
215
internal/utils/cmd.go
Normal file
215
internal/utils/cmd.go
Normal file
@ -0,0 +1,215 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/constants"
|
||||
)
|
||||
|
||||
func GetUidGidAlrUserString() (string, string, error) {
|
||||
u, err := user.Lookup("alr")
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return u.Uid, u.Gid, nil
|
||||
}
|
||||
|
||||
func GetUidGidAlrUser() (int, int, error) {
|
||||
strUid, strGid, err := GetUidGidAlrUserString()
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
uid, err := strconv.Atoi(strUid)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
gid, err := strconv.Atoi(strGid)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return uid, gid, nil
|
||||
}
|
||||
|
||||
func DropCapsToAlrUser() error {
|
||||
uid, gid, err := GetUidGidAlrUser()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Setgid(gid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Setuid(uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return EnsureIsAlrUser()
|
||||
}
|
||||
|
||||
func ExitIfCantDropGidToAlr() cli.ExitCoder {
|
||||
_, gid, err := GetUidGidAlrUser()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("cannot get gid alr", err)
|
||||
}
|
||||
err = syscall.Setgid(gid)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("cannot get setgid alr", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExitIfCantDropCapsToAlrUser attempts to drop capabilities to the already
|
||||
// running user. Returns a cli.ExitCoder with an error if the operation fails.
|
||||
// See also [ExitIfCantDropCapsToAlrUserNoPrivs] for a version that also applies
|
||||
// no-new-privs.
|
||||
func ExitIfCantDropCapsToAlrUser() cli.ExitCoder {
|
||||
err := DropCapsToAlrUser()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error on dropping capabilities"), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExitIfCantSetNoNewPrivs() cli.ExitCoder {
|
||||
if err := NoNewPrivs(); err != nil {
|
||||
return cliutils.FormatCliExit("error on NoNewPrivs", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExitIfCantDropCapsToAlrUserNoPrivs combines [ExitIfCantDropCapsToAlrUser] with [ExitIfCantSetNoNewPrivs]
|
||||
func ExitIfCantDropCapsToAlrUserNoPrivs() cli.ExitCoder {
|
||||
if err := ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ExitIfCantSetNoNewPrivs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsNotRoot() bool {
|
||||
return os.Getuid() != 0
|
||||
}
|
||||
|
||||
func EnsureIsAlrUser() error {
|
||||
uid, gid, err := GetUidGidAlrUser()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newUid := syscall.Getuid()
|
||||
if newUid != uid {
|
||||
return errors.New("new uid don't matches requested")
|
||||
}
|
||||
newGid := syscall.Getgid()
|
||||
if newGid != gid {
|
||||
return errors.New("new gid don't matches requested")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func EnuseIsPrivilegedGroupMember() error {
|
||||
currentUser, err := user.Current()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
group, err := user.LookupGroup(constants.PrivilegedGroup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
groups, err := currentUser.GroupIds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, gid := range groups {
|
||||
if gid == group.Gid {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return cliutils.FormatCliExit(gotext.Get("You need to be a %s member to perform this action", constants.PrivilegedGroup), nil)
|
||||
}
|
||||
|
||||
func EscalateToRootGid() error {
|
||||
return syscall.Setgid(0)
|
||||
}
|
||||
|
||||
func EscalateToRootUid() error {
|
||||
return syscall.Setuid(0)
|
||||
}
|
||||
|
||||
func EscalateToRoot() error {
|
||||
err := EscalateToRootUid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = EscalateToRootGid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RootNeededAction(f cli.ActionFunc) cli.ActionFunc {
|
||||
return func(ctx *cli.Context) error {
|
||||
deps, err := appbuilder.
|
||||
New(ctx.Context).
|
||||
WithConfig().
|
||||
Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
if IsNotRoot() {
|
||||
if !deps.Cfg.UseRootCmd() {
|
||||
return cli.Exit(gotext.Get("You need to be root to perform this action"), 1)
|
||||
}
|
||||
executable, err := os.Executable()
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit("failed to get executable path", err)
|
||||
}
|
||||
args := append([]string{executable}, os.Args[1:]...)
|
||||
cmd := exec.Command(deps.Cfg.RootCmd(), args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
return f(ctx)
|
||||
}
|
||||
}
|
23
internal/utils/utils.go
Normal file
23
internal/utils/utils.go
Normal file
@ -0,0 +1,23 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
func NoNewPrivs() error {
|
||||
return unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
|
||||
ALR - Any Linux Repository
|
||||
Copyright (C) {{ .Year }} Евгений Храмов
|
||||
Copyright (C) {{ .Year }} The ALR Authors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,5 +1,5 @@
|
||||
ALR - Any Linux Repository
|
||||
Copyright (C) {{ .Year }} Евгений Храмов
|
||||
Copyright (C) {{ .Year }} The ALR Authors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
144
list.go
144
list.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -23,15 +23,18 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"slices"
|
||||
"text/template"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||
database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/build"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/repos"
|
||||
)
|
||||
|
||||
func ListCmd() *cli.Command {
|
||||
@ -44,25 +47,72 @@ func ListCmd() *cli.Command {
|
||||
Name: "installed",
|
||||
Aliases: []string{"I"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "upgradable",
|
||||
Aliases: []string{"U"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "format",
|
||||
Aliases: []string{"f"},
|
||||
Usage: gotext.Get("Format output using a Go template"),
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
ctx := c.Context
|
||||
cfg := config.New()
|
||||
db := database.New(cfg)
|
||||
err := db.Init(ctx)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error initialization database"), "err", err)
|
||||
os.Exit(1)
|
||||
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
||||
return err
|
||||
}
|
||||
rs := repos.New(cfg, db)
|
||||
|
||||
if cfg.AutoPull(ctx) {
|
||||
err = rs.Pull(ctx, cfg.Repos(ctx))
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error pulling repositories"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ctx := c.Context
|
||||
|
||||
deps, err := appbuilder.
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithManager().
|
||||
// autoPull only
|
||||
WithRepos().
|
||||
WithDistroInfo().
|
||||
Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer deps.Defer()
|
||||
|
||||
cfg := deps.Cfg
|
||||
db := deps.DB
|
||||
mgr := deps.Manager
|
||||
info := deps.Info
|
||||
|
||||
if c.Bool("upgradable") {
|
||||
updates, err := checkForUpdates(ctx, mgr, db, info)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting packages for upgrade"), err)
|
||||
}
|
||||
if len(updates) == 0 {
|
||||
slog.Info(gotext.Get("No packages for upgrade"))
|
||||
return nil
|
||||
}
|
||||
|
||||
format := c.String("format")
|
||||
if format == "" {
|
||||
format = "{{.Package.Repository}}/{{.Package.Name}} {{.FromVersion}} -> {{.ToVersion}}\n"
|
||||
}
|
||||
tmpl, err := template.New("format").Parse(format)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error parsing format template"), err)
|
||||
}
|
||||
|
||||
for _, updateInfo := range updates {
|
||||
err = tmpl.Execute(os.Stdout, updateInfo)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: refactor code below
|
||||
|
||||
where := "true"
|
||||
args := []any(nil)
|
||||
@ -73,23 +123,30 @@ func ListCmd() *cli.Command {
|
||||
|
||||
result, err := db.GetPkgs(ctx, where, args...)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error getting packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err)
|
||||
}
|
||||
defer result.Close()
|
||||
|
||||
var installed map[string]string
|
||||
installedAlrPackages := map[string]string{}
|
||||
if c.Bool("installed") {
|
||||
mgr := manager.Detect()
|
||||
if mgr == nil {
|
||||
slog.Error(gotext.Get("Unable to detect a supported package manager on the system"))
|
||||
os.Exit(1)
|
||||
return cli.Exit(gotext.Get("Unable to detect a supported package manager on the system"), 1)
|
||||
}
|
||||
|
||||
installed, err = mgr.ListInstalled(&manager.Opts{AsRoot: false})
|
||||
installed, err := mgr.ListInstalled(&manager.Opts{})
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error listing installed packages"), "err", err)
|
||||
os.Exit(1)
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
for pkgName, version := range installed {
|
||||
matches := build.RegexpALRPackageName.FindStringSubmatch(pkgName)
|
||||
if matches != nil {
|
||||
packageName := matches[build.RegexpALRPackageName.SubexpIndex("package")]
|
||||
repoName := matches[build.RegexpALRPackageName.SubexpIndex("repo")]
|
||||
installedAlrPackages[fmt.Sprintf("%s/%s", repoName, packageName)] = version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,29 +154,42 @@ func ListCmd() *cli.Command {
|
||||
var pkg database.Package
|
||||
err := result.StructScan(&pkg)
|
||||
if err != nil {
|
||||
return err
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
if slices.Contains(cfg.IgnorePkgUpdates(ctx), pkg.Name) {
|
||||
if slices.Contains(cfg.IgnorePkgUpdates(), pkg.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
version := pkg.Version
|
||||
type packageInfo struct {
|
||||
Package *database.Package
|
||||
Version string
|
||||
}
|
||||
|
||||
pkgInfo := &packageInfo{}
|
||||
pkgInfo.Package = &pkg
|
||||
pkgInfo.Version = pkg.Version
|
||||
if c.Bool("installed") {
|
||||
instVersion, ok := installed[pkg.Name]
|
||||
instVersion, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)]
|
||||
if !ok {
|
||||
continue
|
||||
} else {
|
||||
version = instVersion
|
||||
pkgInfo.Version = instVersion
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%s/%s %s\n", pkg.Repository, pkg.Name, version)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error iterating over packages"), "err", err)
|
||||
os.Exit(1)
|
||||
format := c.String("format")
|
||||
if format == "" {
|
||||
format = "{{.Package.Repository}}/{{.Package.Name}} {{.Version}}\n"
|
||||
}
|
||||
tmpl, err := template.New("format").Parse(format)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error parsing format template"), err)
|
||||
}
|
||||
err = tmpl.Execute(os.Stdout, pkgInfo)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
74
main.go
74
main.go
@ -1,8 +1,8 @@
|
||||
// This file was originally part of the project "LURE - Linux User REpository", created by Elara Musayelyan.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by Евгений Храмов.
|
||||
// It has been modified as part of "ALR - Any Linux Repository" by the ALR Authors.
|
||||
//
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -31,8 +31,8 @@ import (
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/translations"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
|
||||
@ -74,52 +74,78 @@ func GetApp() *cli.App {
|
||||
InfoCmd(),
|
||||
ListCmd(),
|
||||
BuildCmd(),
|
||||
AddRepoCmd(),
|
||||
RemoveRepoCmd(),
|
||||
LegacyAddRepoCmd(),
|
||||
LegacyRemoveRepoCmd(),
|
||||
RefreshCmd(),
|
||||
FixCmd(),
|
||||
GenCmd(),
|
||||
HelperCmd(),
|
||||
VersionCmd(),
|
||||
SearchCmd(),
|
||||
RepoCmd(),
|
||||
// Internal commands
|
||||
InternalBuildCmd(),
|
||||
InternalInstallCmd(),
|
||||
InternalMountCmd(),
|
||||
},
|
||||
Before: func(c *cli.Context) error {
|
||||
ctx := c.Context
|
||||
|
||||
cmd := c.Args().First()
|
||||
if cmd != "helper" && !config.Config(ctx).Unsafe.AllowRunAsRoot && os.Geteuid() == 0 {
|
||||
slog.Error(gotext.Get("Running ALR as root is forbidden as it may cause catastrophic damage to your system"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if trimmed := strings.TrimSpace(c.String("pm-args")); trimmed != "" {
|
||||
args := strings.Split(trimmed, " ")
|
||||
manager.Args = append(manager.Args, args...)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
After: func(ctx *cli.Context) error {
|
||||
return db.Close()
|
||||
},
|
||||
EnableBashCompletion: true,
|
||||
ExitErrHandler: func(cCtx *cli.Context, err error) {
|
||||
cliutils.HandleExitCoder(err)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
translations.Setup()
|
||||
logger.SetupDefault()
|
||||
func setLogLevel(newLevel string) {
|
||||
level := slog.LevelInfo
|
||||
switch newLevel {
|
||||
case "DEBUG":
|
||||
level = slog.LevelDebug
|
||||
case "INFO":
|
||||
level = slog.LevelInfo
|
||||
case "WARN":
|
||||
level = slog.LevelWarn
|
||||
case "ERROR":
|
||||
level = slog.LevelError
|
||||
}
|
||||
logger, ok := slog.Default().Handler().(*logger.Logger)
|
||||
if !ok {
|
||||
panic("unexpected")
|
||||
}
|
||||
logger.SetLevel(level)
|
||||
}
|
||||
|
||||
app := GetApp()
|
||||
func main() {
|
||||
logger.SetupDefault()
|
||||
setLogLevel(os.Getenv("ALR_LOG_LEVEL"))
|
||||
translations.Setup()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Set the root command to the one set in the ALR config
|
||||
manager.DefaultRootCmd = config.Config(ctx).RootCmd
|
||||
app := GetApp()
|
||||
cfg := config.New()
|
||||
err := cfg.Load()
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error loading config"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
setLogLevel(cfg.LogLevel())
|
||||
|
||||
ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer cancel()
|
||||
|
||||
err := app.RunContext(ctx, os.Args)
|
||||
// Make the application more internationalized
|
||||
cli.AppHelpTemplate = cliutils.GetAppCliTemplate()
|
||||
cli.CommandHelpTemplate = cliutils.GetCommandHelpTemplate()
|
||||
cli.HelpFlag.(*cli.BoolFlag).Usage = gotext.Get("Show help")
|
||||
|
||||
err = app.RunContext(ctx, os.Args)
|
||||
if err != nil {
|
||||
slog.Error(gotext.Get("Error while running app"), "err", err)
|
||||
}
|
||||
|
1395
pkg/build/build.go
1395
pkg/build/build.go
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -18,10 +18,18 @@ package build
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"mvdan.cc/sh/v3/syntax"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
)
|
||||
|
||||
@ -134,93 +142,145 @@ func (m *TestManager) IsInstalled(pkg string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// TODO: fix test
|
||||
func TestInstallBuildDeps(t *testing.T) {
|
||||
type testEnv struct {
|
||||
pf PackageFinder
|
||||
vars *types.BuildVars
|
||||
opts types.BuildOpts
|
||||
type TestConfig struct{}
|
||||
|
||||
// Contains pkgs captured by FindPkgsFunc
|
||||
// capturedPkgs []string
|
||||
func (c *TestConfig) PagerStyle() string {
|
||||
return "native"
|
||||
}
|
||||
|
||||
func (c *TestConfig) GetPaths() *config.Paths {
|
||||
return &config.Paths{
|
||||
CacheDir: "/tmp",
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteFirstPassIsSecure(t *testing.T) {
|
||||
cfg := &TestConfig{}
|
||||
pf := &TestPackageFinder{}
|
||||
info := &distro.OSRelease{}
|
||||
m := &TestManager{}
|
||||
|
||||
opts := types.BuildOpts{
|
||||
Manager: m,
|
||||
Interactive: false,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
b := NewBuilder(
|
||||
ctx,
|
||||
opts,
|
||||
pf,
|
||||
info,
|
||||
cfg,
|
||||
)
|
||||
|
||||
tmpFile, err := os.CreateTemp("", "testfile-")
|
||||
assert.NoError(t, err)
|
||||
tmpFilePath := tmpFile.Name()
|
||||
defer os.Remove(tmpFilePath)
|
||||
|
||||
_, err = os.Stat(tmpFilePath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
testScript := fmt.Sprintf(`name='test'
|
||||
version=1.0.0
|
||||
release=1
|
||||
rm -f %s`, tmpFilePath)
|
||||
|
||||
fl, err := syntax.NewParser().Parse(strings.NewReader(testScript), "alr.sh")
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, _, err = b.executeFirstPass(fl)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = os.Stat(tmpFilePath)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestExecuteFirstPassIsCorrect(t *testing.T) {
|
||||
type testCase struct {
|
||||
Name string
|
||||
Prepare func() *testEnv
|
||||
Expected func(t *testing.T, e *testEnv, res []string, err error)
|
||||
Script string
|
||||
Opts types.BuildOpts
|
||||
Expected func(t *testing.T, vars []*types.BuildVars)
|
||||
}
|
||||
|
||||
for _, tc := range []testCase{
|
||||
/*
|
||||
{
|
||||
Name: "install only needed deps",
|
||||
Prepare: func() *testEnv {
|
||||
pf := TestPackageFinder{}
|
||||
vars := types.BuildVars{}
|
||||
m := TestManager{}
|
||||
opts := types.BuildOpts{
|
||||
Manager: &m,
|
||||
Interactive: false,
|
||||
}
|
||||
for _, tc := range []testCase{{
|
||||
Name: "single package",
|
||||
Script: `name='test'
|
||||
version='1.0.0'
|
||||
release=1
|
||||
epoch=2
|
||||
desc="Test package"
|
||||
homepage='https://example.com'
|
||||
maintainer='Ivan Ivanov'
|
||||
`,
|
||||
Opts: types.BuildOpts{
|
||||
Manager: &TestManager{},
|
||||
Interactive: false,
|
||||
},
|
||||
Expected: func(t *testing.T, vars []*types.BuildVars) {
|
||||
assert.Equal(t, 1, len(vars))
|
||||
assert.Equal(t, vars[0].Name, "test")
|
||||
assert.Equal(t, vars[0].Version, "1.0.0")
|
||||
assert.Equal(t, vars[0].Release, int(1))
|
||||
assert.Equal(t, vars[0].Epoch, uint(2))
|
||||
assert.Equal(t, vars[0].Description, "Test package")
|
||||
},
|
||||
}, {
|
||||
Name: "multiple packages",
|
||||
Script: `name=(
|
||||
foo
|
||||
bar
|
||||
)
|
||||
|
||||
env := &testEnv{
|
||||
pf: &pf,
|
||||
vars: &vars,
|
||||
opts: opts,
|
||||
capturedPkgs: []string{},
|
||||
}
|
||||
version='0.0.1'
|
||||
release=1
|
||||
epoch=2
|
||||
desc="Test package"
|
||||
|
||||
pf.FindPkgsFunc = func(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error) {
|
||||
env.capturedPkgs = append(env.capturedPkgs, pkgs...)
|
||||
result := make(map[string][]db.Package)
|
||||
result["bar"] = []db.Package{{
|
||||
Name: "bar-pkg",
|
||||
}}
|
||||
result["buz"] = []db.Package{{
|
||||
Name: "buz-pkg",
|
||||
}}
|
||||
meta_foo() {
|
||||
desc="Foo package"
|
||||
}
|
||||
|
||||
return result, []string{}, nil
|
||||
}
|
||||
meta_bar() {
|
||||
|
||||
vars.BuildDepends = []string{
|
||||
"foo",
|
||||
"bar",
|
||||
"buz",
|
||||
}
|
||||
m.IsInstalledFunc = func(pkg string) (bool, error) {
|
||||
if pkg == "foo" {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
Opts: types.BuildOpts{
|
||||
Packages: []string{"foo"},
|
||||
Manager: &TestManager{},
|
||||
Interactive: false,
|
||||
},
|
||||
Expected: func(t *testing.T, vars []*types.BuildVars) {
|
||||
assert.Equal(t, 1, len(vars))
|
||||
assert.Equal(t, vars[0].Name, "foo")
|
||||
assert.Equal(t, vars[0].Description, "Foo package")
|
||||
},
|
||||
}} {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
cfg := &TestConfig{}
|
||||
pf := &TestPackageFinder{}
|
||||
info := &distro.OSRelease{}
|
||||
|
||||
return env
|
||||
},
|
||||
Expected: func(t *testing.T, e *testEnv, res []string, err error) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, res, 2)
|
||||
assert.ElementsMatch(t, res, []string{"bar-pkg", "buz-pkg"})
|
||||
|
||||
assert.ElementsMatch(t, e.capturedPkgs, []string{"bar", "buz"})
|
||||
},
|
||||
},
|
||||
*/
|
||||
} {
|
||||
t.Run(tc.Name, func(tt *testing.T) {
|
||||
ctx := context.Background()
|
||||
env := tc.Prepare()
|
||||
|
||||
result, err := installBuildDeps(
|
||||
b := NewBuilder(
|
||||
ctx,
|
||||
env.pf,
|
||||
env.vars,
|
||||
env.opts,
|
||||
tc.Opts,
|
||||
pf,
|
||||
info,
|
||||
cfg,
|
||||
)
|
||||
|
||||
tc.Expected(tt, env, result, err)
|
||||
fl, err := syntax.NewParser().Parse(strings.NewReader(tc.Script), "alr.sh")
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, allVars, err := b.scriptExecutor.ExecuteSecondPass(fl)
|
||||
assert.NoError(t, err)
|
||||
|
||||
tc.Expected(t, allVars)
|
||||
})
|
||||
}
|
||||
}
|
69
pkg/build/cache.go
Normal file
69
pkg/build/cache.go
Normal file
@ -0,0 +1,69 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
cfg Config
|
||||
}
|
||||
|
||||
func (c *Cache) CheckForBuiltPackage(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
vars *types.BuildVars,
|
||||
) (string, bool, error) {
|
||||
filename, err := pkgFileName(input, vars)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
pkgPath := filepath.Join(getBaseDir(c.cfg, vars.Name), filename)
|
||||
|
||||
_, err = os.Stat(pkgPath)
|
||||
if err != nil {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
return pkgPath, true, nil
|
||||
}
|
||||
|
||||
func pkgFileName(
|
||||
input interface {
|
||||
OsInfoProvider
|
||||
PkgFormatProvider
|
||||
RepositoryProvider
|
||||
},
|
||||
vars *types.BuildVars,
|
||||
) (string, error) {
|
||||
pkgInfo := getBasePkgInfo(vars, input)
|
||||
|
||||
packager, err := nfpm.Get(input.PkgFormat())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return packager.ConventionalFileName(pkgInfo), nil
|
||||
}
|
74
pkg/build/checker.go
Normal file
74
pkg/build/checker.go
Normal file
@ -0,0 +1,74 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
)
|
||||
|
||||
type Checker struct {
|
||||
mgr manager.Manager
|
||||
}
|
||||
|
||||
func (c *Checker) PerformChecks(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
vars *types.BuildVars,
|
||||
) (bool, error) {
|
||||
if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) { // Проверяем совместимость архитектуры
|
||||
cont, err := cliutils.YesNoPrompt(
|
||||
ctx,
|
||||
gotext.Get("Your system's CPU architecture doesn't match this package. Do you want to build anyway?"),
|
||||
input.opts.Interactive,
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !cont {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
installed, err := c.mgr.ListInstalled(nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
filename, err := pkgFileName(input, vars)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if instVer, ok := installed[filename]; ok { // Если пакет уже установлен, выводим предупреждение
|
||||
slog.Warn(gotext.Get("This package is already installed"),
|
||||
"name", vars.Name,
|
||||
"version", instVer,
|
||||
)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
71
pkg/build/dirs.go
Normal file
71
pkg/build/dirs.go
Normal file
@ -0,0 +1,71 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package build
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
)
|
||||
|
||||
type BaseDirProvider interface {
|
||||
BaseDir() string
|
||||
}
|
||||
|
||||
type SrcDirProvider interface {
|
||||
SrcDir() string
|
||||
}
|
||||
|
||||
type PkgDirProvider interface {
|
||||
PkgDir() string
|
||||
}
|
||||
|
||||
type ScriptDirProvider interface {
|
||||
ScriptDir() string
|
||||
}
|
||||
|
||||
func getDirs(
|
||||
cfg Config,
|
||||
scriptPath string,
|
||||
basePkg string,
|
||||
) (types.Directories, error) {
|
||||
pkgsDir := cfg.GetPaths().PkgsDir
|
||||
|
||||
scriptPath, err := filepath.Abs(scriptPath)
|
||||
if err != nil {
|
||||
return types.Directories{}, err
|
||||
}
|
||||
baseDir := filepath.Join(pkgsDir, basePkg)
|
||||
return types.Directories{
|
||||
BaseDir: getBaseDir(cfg, basePkg),
|
||||
SrcDir: getSrcDir(cfg, basePkg),
|
||||
PkgDir: filepath.Join(baseDir, "pkg"),
|
||||
ScriptDir: getScriptDir(scriptPath),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getBaseDir(cfg Config, basePkg string) string {
|
||||
return filepath.Join(cfg.GetPaths().PkgsDir, basePkg)
|
||||
}
|
||||
|
||||
func getSrcDir(cfg Config, basePkg string) string {
|
||||
return filepath.Join(getBaseDir(cfg, basePkg), "src")
|
||||
}
|
||||
|
||||
func getScriptDir(scriptPath string) string {
|
||||
return filepath.Dir(scriptPath)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package build
|
||||
package finddeps
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -30,7 +30,7 @@ import (
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
)
|
||||
|
||||
func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, updateFunc func(string)) error {
|
||||
func rpmFindDependenciesALTLinux(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, envs []string, updateFunc func(string)) error {
|
||||
if _, err := exec.LookPath(command); err != nil {
|
||||
slog.Info(gotext.Get("Command not found on the system"), "command", command)
|
||||
return nil
|
||||
@ -49,8 +49,8 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.Command(command)
|
||||
cmd.Stdin = bytes.NewBufferString(strings.Join(paths, "\n"))
|
||||
cmd := exec.CommandContext(ctx, command)
|
||||
cmd.Stdin = bytes.NewBufferString(strings.Join(paths, "\n") + "\n")
|
||||
cmd.Env = append(cmd.Env,
|
||||
"RPM_BUILD_ROOT="+dirs.PkgDir,
|
||||
"RPM_FINDPROV_METHOD=",
|
||||
@ -58,6 +58,7 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
|
||||
"RPM_DATADIR=",
|
||||
"RPM_SUBPACKAGE_NAME=",
|
||||
)
|
||||
cmd.Env = append(cmd.Env, envs...)
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
@ -66,6 +67,7 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
|
||||
slog.Error(stderr.String())
|
||||
return err
|
||||
}
|
||||
slog.Debug(stderr.String())
|
||||
|
||||
dependencies := strings.Split(strings.TrimSpace(out.String()), "\n")
|
||||
for _, dep := range dependencies {
|
||||
@ -77,15 +79,17 @@ func rpmFindDependencies(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Dir
|
||||
return nil
|
||||
}
|
||||
|
||||
func rpmFindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories) error {
|
||||
return rpmFindDependencies(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-provides", func(dep string) {
|
||||
type ALTLinuxFindProvReq struct{}
|
||||
|
||||
func (o *ALTLinuxFindProvReq) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
return rpmFindDependenciesALTLinux(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-provides", []string{"RPM_FINDPROV_SKIPLIST=" + strings.Join(skiplist, "\n")}, func(dep string) {
|
||||
slog.Info(gotext.Get("Provided dependency found"), "dep", dep)
|
||||
pkgInfo.Overridables.Provides = append(pkgInfo.Overridables.Provides, dep)
|
||||
})
|
||||
}
|
||||
|
||||
func rpmFindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories) error {
|
||||
return rpmFindDependencies(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-requires", func(dep string) {
|
||||
func (o *ALTLinuxFindProvReq) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
return rpmFindDependenciesALTLinux(ctx, pkgInfo, dirs, "/usr/lib/rpm/find-requires", []string{"RPM_FINDREQ_SKIPLIST=" + strings.Join(skiplist, "\n")}, func(dep string) {
|
||||
slog.Info(gotext.Get("Required dependency found"), "dep", dep)
|
||||
pkgInfo.Overridables.Depends = append(pkgInfo.Overridables.Depends, dep)
|
||||
})
|
@ -1,5 +1,5 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 Евгений Храмов
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -14,39 +14,26 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package config
|
||||
package finddeps
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"log/slog"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
)
|
||||
|
||||
// Config returns a ALR configuration struct.
|
||||
// The first time it's called, it'll load the config from a file.
|
||||
// Subsequent calls will just return the same value.
|
||||
//
|
||||
// Deprecated: use struct method
|
||||
func Config(ctx context.Context) *types.Config {
|
||||
return GetInstance(ctx).cfg
|
||||
type EmptyFindProvReq struct{}
|
||||
|
||||
func (o *EmptyFindProvReq) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
slog.Info(gotext.Get("AutoProv is not implemented for this package format, so it's skipped"))
|
||||
return nil
|
||||
}
|
||||
|
||||
// =======================
|
||||
// FOR LEGACY ONLY
|
||||
// =======================
|
||||
|
||||
var (
|
||||
alrConfig *ALRConfig
|
||||
alrConfigOnce sync.Once
|
||||
)
|
||||
|
||||
// Deprecated: For legacy only
|
||||
func GetInstance(ctx context.Context) *ALRConfig {
|
||||
alrConfigOnce.Do(func() {
|
||||
alrConfig = New()
|
||||
alrConfig.Load(ctx)
|
||||
})
|
||||
|
||||
return alrConfig
|
||||
func (o *EmptyFindProvReq) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
slog.Info(gotext.Get("AutoReq is not implemented for this package format, so it's skipped"))
|
||||
return nil
|
||||
}
|
118
pkg/build/find_deps/fedora.go
Normal file
118
pkg/build/find_deps/fedora.go
Normal file
@ -0,0 +1,118 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package finddeps
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
)
|
||||
|
||||
type FedoraFindProvReq struct{}
|
||||
|
||||
func rpmFindDependenciesFedora(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, args []string, updateFunc func(string)) error {
|
||||
if _, err := exec.LookPath(command); err != nil {
|
||||
slog.Info(gotext.Get("Command not found on the system"), "command", command)
|
||||
return nil
|
||||
}
|
||||
|
||||
var paths []string
|
||||
for _, content := range pkgInfo.Contents {
|
||||
if content.Type != "dir" {
|
||||
paths = append(paths,
|
||||
path.Join(dirs.PkgDir, content.Destination),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if len(paths) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, command, args...)
|
||||
cmd.Stdin = bytes.NewBufferString(strings.Join(paths, "\n") + "\n")
|
||||
cmd.Env = append(cmd.Env,
|
||||
"RPM_BUILD_ROOT="+dirs.PkgDir,
|
||||
)
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
slog.Error(stderr.String())
|
||||
return err
|
||||
}
|
||||
slog.Debug(stderr.String())
|
||||
|
||||
dependencies := strings.Split(strings.TrimSpace(out.String()), "\n")
|
||||
for _, dep := range dependencies {
|
||||
if dep != "" {
|
||||
updateFunc(dep)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *FedoraFindProvReq) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
return rpmFindDependenciesFedora(
|
||||
ctx,
|
||||
pkgInfo,
|
||||
dirs,
|
||||
"/usr/lib/rpm/rpmdeps",
|
||||
[]string{
|
||||
"--define=_use_internal_dependency_generator 1",
|
||||
"--provides",
|
||||
fmt.Sprintf(
|
||||
"--define=__provides_exclude_from %s\"",
|
||||
strings.Join(skiplist, "|"),
|
||||
),
|
||||
},
|
||||
func(dep string) {
|
||||
slog.Info(gotext.Get("Provided dependency found"), "dep", dep)
|
||||
pkgInfo.Overridables.Provides = append(pkgInfo.Overridables.Provides, dep)
|
||||
})
|
||||
}
|
||||
|
||||
func (o *FedoraFindProvReq) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
return rpmFindDependenciesFedora(
|
||||
ctx,
|
||||
pkgInfo,
|
||||
dirs,
|
||||
"/usr/lib/rpm/rpmdeps",
|
||||
[]string{
|
||||
"--define=_use_internal_dependency_generator 1",
|
||||
"--requires",
|
||||
fmt.Sprintf(
|
||||
"--define=__requires_exclude_from %s",
|
||||
strings.Join(skiplist, "|"),
|
||||
),
|
||||
},
|
||||
func(dep string) {
|
||||
slog.Info(gotext.Get("Required dependency found"), "dep", dep)
|
||||
pkgInfo.Overridables.Depends = append(pkgInfo.Overridables.Depends, dep)
|
||||
})
|
||||
}
|
58
pkg/build/find_deps/find_deps.go
Normal file
58
pkg/build/find_deps/find_deps.go
Normal file
@ -0,0 +1,58 @@
|
||||
// ALR - Any Linux Repository
|
||||
// Copyright (C) 2025 The ALR Authors
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package finddeps
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
)
|
||||
|
||||
type ProvReqFinder interface {
|
||||
FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error
|
||||
FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error
|
||||
}
|
||||
|
||||
type ProvReqService struct {
|
||||
finder ProvReqFinder
|
||||
}
|
||||
|
||||
func New(info *distro.OSRelease, pkgFormat string) *ProvReqService {
|
||||
s := &ProvReqService{
|
||||
finder: &EmptyFindProvReq{},
|
||||
}
|
||||
if pkgFormat == "rpm" {
|
||||
switch info.ID {
|
||||
case "altlinux":
|
||||
s.finder = &ALTLinuxFindProvReq{}
|
||||
case "fedora":
|
||||
s.finder = &FedoraFindProvReq{}
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *ProvReqService) FindProvides(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
return s.finder.FindProvides(ctx, pkgInfo, dirs, skiplist)
|
||||
}
|
||||
|
||||
func (s *ProvReqService) FindRequires(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, skiplist []string) error {
|
||||
return s.finder.FindRequires(ctx, pkgInfo, dirs, skiplist)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user