Compare commits
65 Commits
Author | SHA1 | Date | |
---|---|---|---|
bd79dcf401 | |||
d1fe02fa57 | |||
1ca7801fba | |||
661d79ce24 | |||
bece64c132 | |||
6d29b98cf7 | |||
d286041864 | |||
392a522723 | |||
e259184a89 | |||
65ab4de561 | |||
1cdab8dfed | |||
237e2c338d | |||
703ab8e8c4 | |||
06fcab4ce7 | |||
7741c7368b | |||
69f4af0a4d | |||
bcf627f176 | |||
6ec95e4bd9 | |||
578da7ff52 | |||
c51caf5c52 | |||
09dba577c6 | |||
ca82bf3024 | |||
c0023db6cd | |||
152e5077ec | |||
15ba8700e8 | |||
a8aefc0524 | |||
9540030579 | |||
4f9d4260b8 | |||
38b5e6f581 | |||
408bd12302 | |||
fb83d544de | |||
2cb963d4b2 | |||
e74d74cdf6 | |||
5b3d53d253 | |||
36e704f735 | |||
07356d5e55 | |||
52bd6aca93 | |||
2f1770b43b | |||
9d5b5b51ff | |||
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 |
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:
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
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'
|
||||
cache: false
|
||||
|
||||
# - 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:
|
||||
IGNORE_ROOT_CHECK: 1
|
||||
run: |
|
||||
make e2e-test
|
51
.gitea/workflows/pre-commit.yaml
Normal file
51
.gitea/workflows/pre-commit.yaml
Normal file
@ -0,0 +1,51 @@
|
||||
# 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
|
||||
container:
|
||||
image: docker.gitea.com/runner-images: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
|
120
.gitea/workflows/release.yaml
Normal file
120
.gitea/workflows/release.yaml
Normal file
@ -0,0 +1,120 @@
|
||||
# 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: Prepare for install
|
||||
run: |
|
||||
apt-get update && apt-get install -y libcap2-bin bindfs
|
||||
|
||||
- name: Build alr
|
||||
env:
|
||||
IGNORE_ROOT_CHECK: 1
|
||||
run: |
|
||||
make build
|
||||
|
||||
- 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
|
||||
|
||||
- name: Checkout alr-default repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: Plemya-x/alr-default
|
||||
token: ${{ secrets.GITEAPUBLIC }}
|
||||
path: alr-default
|
||||
|
||||
- name: Update version in alr-bin
|
||||
run: |
|
||||
# Замените значения в файле с конфигурацией
|
||||
sed -i "s/version='[0-9]\+\.[0-9]\+\.[0-9]\+'/version='${{ env.VERSION }}'/g" alr-default/alr-bin/alr.sh
|
||||
sed -i "s/release='[0-9]\+'/release='1'/g" alr-default/alr-bin/alr.sh
|
||||
|
||||
- name: Install alr
|
||||
run: |
|
||||
make install
|
||||
|
||||
# temporary fix
|
||||
groupadd wheel
|
||||
usermod -aG wheel root
|
||||
|
||||
- name: Build packages
|
||||
run: |
|
||||
SCRIPT_PATH=alr-default/alr-bin/alr.sh
|
||||
ALR_DISTRO=altlinux ALR_PKG_FORMAT=rpm alr build -s "$SCRIPT_PATH"
|
||||
ALR_PKG_FORMAT=rpm alr build -s "$SCRIPT_PATH"
|
||||
ALR_PKG_FORMAT=deb alr build -s "$SCRIPT_PATH"
|
||||
ALR_PKG_FORMAT=archlinux alr build -s "$SCRIPT_PATH"
|
||||
|
||||
- name: Upload assets
|
||||
uses: akkuman/gitea-release-action@v1
|
||||
with:
|
||||
body: ${{ steps.changes.outputs.changes }}
|
||||
files: |-
|
||||
alr-bin+alr-default_${{ env.VERSION }}-1.red80_amd64.deb \
|
||||
alr-bin+alr-default-${{ env.VERSION }}-1-x86_64.pkg.tar.zst \
|
||||
alr-bin+alr-default-${{ env.VERSION }}-1.red80.x86_64.rpm \
|
||||
alr-bin+alr-default-${{ env.VERSION }}-alt1.x86_64.rpm
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
cd alr-default
|
||||
git config user.name "gitea"
|
||||
git config user.email "admin@plemya-x.ru"
|
||||
git add .
|
||||
git commit -m "Обновление версии до ${{ env.VERSION }}"
|
||||
git push
|
69
.gitea/workflows/update-alr-git.yaml
Normal file
69
.gitea/workflows/update-alr-git.yaml
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/>.
|
||||
|
||||
name: Update alr-git
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
changelog:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
|
||||
- name: Setup alr-spec
|
||||
run: |
|
||||
uv tool install alr-spec==0.0.5
|
||||
|
||||
- name: Install alr
|
||||
run: |
|
||||
apt-get update && apt-get install -y libcap2-bin
|
||||
curl -fsS https://gitea.plemya-x.ru/Plemya-x/ALR/raw/branch/master/scripts/install.sh | bash
|
||||
|
||||
- name: Checkout this repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set ALR version
|
||||
run: |
|
||||
echo "NEW_ALR_VERSION=$(alr helper git-version)" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout alr-default repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: Plemya-x/alr-default
|
||||
token: ${{ secrets.GITEAPUBLIC }}
|
||||
path: alr-default
|
||||
|
||||
- name: Update version
|
||||
working-directory: ./alr-default/alr-git
|
||||
run: |
|
||||
alr-spec set-field version $NEW_ALR_VERSION
|
||||
alr-spec set-field release 1
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
cd alr-default
|
||||
git config user.name "gitea"
|
||||
git config user.email "admin@plemya-x.ru"
|
||||
git add .
|
||||
git commit -m "Обновление версии до $NEW_ALR_VERSION"
|
||||
git push
|
@ -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
|
||||
|
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
|
17
Makefile
17
Makefile
@ -1,6 +1,6 @@
|
||||
NAME := alr
|
||||
GIT_VERSION = $(shell git describe --tags )
|
||||
|
||||
IGNORE_ROOT_CHECK ?= 0
|
||||
DESTDIR ?=
|
||||
PREFIX ?= /usr/local
|
||||
BIN := ./$(NAME)
|
||||
@ -24,8 +24,9 @@ $(BIN):
|
||||
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
|
||||
|
||||
@ -38,6 +39,12 @@ install: \
|
||||
$(INSTALED_BIN): $(BIN)
|
||||
install -Dm755 $< $@
|
||||
setcap cap_setuid,cap_setgid+ep $(INSTALED_BIN)
|
||||
@if id alr >/dev/null 2>&1; then \
|
||||
echo "User 'alr' already exists. Skipping."; \
|
||||
else \
|
||||
useradd -r -s /usr/sbin/nologin alr; \
|
||||
fi
|
||||
install -d -o alr -g alr -m 755 /var/cache/alr /etc/alr
|
||||
|
||||
$(INSTALLED_BASH_COMPLETION): $(BASH_COMPLETION)
|
||||
install -Dm755 $< $@
|
||||
@ -54,7 +61,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)
|
||||
@ -76,7 +83,9 @@ test-coverage:
|
||||
update-deps-cve:
|
||||
bash scripts/update-deps-cve.sh
|
||||
|
||||
e2e-test: clean build
|
||||
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 ./...
|
16
README.md
16
README.md
@ -20,10 +20,10 @@ ALR написан на чистом Go и после сборки не имее
|
||||
Установочный скрипт автоматически загрузит и установит соответствующий пакет ALR в вашей системе. Чтобы использовать его, просто выполните следующую команду:
|
||||
|
||||
```bash
|
||||
curl -fsSL plemya-x.ru/alr/install.sh | bash
|
||||
curl -fsSL https://gitea.plemya-x.ru/Plemya-x/ALR/raw/branch/master/scripts/install.sh | bash
|
||||
```
|
||||
|
||||
**ВАЖНО**: При этом скрипт будет загружен и запущен с <https://plemya-x.ru/alr/install.sh>. Пожалуйста, просматривайте любые скрипты, которые вы скачиваете из Интернета (включая этот), прежде чем запускать их.
|
||||
**ВАЖНО**: При этом скрипт будет загружен и запущен [скрипт](https://gitea.plemya-x.ru/Plemya-x/ALR/src/branch/master/scripts/install.sh). Пожалуйста, просматривайте любые скрипты, которые вы скачиваете из Интернета (включая этот), прежде чем запускать их.
|
||||
|
||||
### Сборка из исходного кода
|
||||
|
||||
@ -52,9 +52,17 @@ ALR был создан потому, что упаковка программн
|
||||
|
||||
Репозитории 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 [Plemya-x/alr-default](https://gitea.plemya-x.ru/Plemya-x/alr-default.git)
|
||||
```
|
||||
alr addrepo --name alr-repo --url https://gitea.plemya-x.ru/Plemya-x/alr-repo.git
|
||||
alr repo add alr-default https://gitea.plemya-x.ru/Plemya-x/alr-default.git
|
||||
```
|
||||
Репозиторий пакетов [Plemya-x/alr-repo](https://gitea.plemya-x.ru/Plemya-x/alr-repo.git) можно подключить так:
|
||||
```
|
||||
alr repo add alr-repo https://gitea.plemya-x.ru/Plemya-x/alr-repo.git
|
||||
```
|
||||
Репозиторий Linux-Gaming [Plemya-x/alr-LG](https://gitea.plemya-x.ru/Plemya-x/alr-LG.git) можно подключить так:
|
||||
```
|
||||
alr repo add alr-LG https://gitea.plemya-x.ru/Plemya-x/alr-LG.git
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -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">16.4%</text>
|
||||
<text x="86" y="14">16.4%</text>
|
||||
<text x="86" y="15" fill="#010101" fill-opacity=".3">19.0%</text>
|
||||
<text x="86" y="14">19.0%</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 926 B After Width: | Height: | Size: 926 B |
22
build.go
22
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
|
||||
@ -28,12 +28,12 @@ import (
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/build"
|
||||
"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/types"
|
||||
)
|
||||
|
||||
func BuildCmd() *cli.Command {
|
||||
@ -97,7 +97,7 @@ func BuildCmd() *cli.Command {
|
||||
var script string
|
||||
var packages []string
|
||||
|
||||
var res *build.BuildResult
|
||||
var res []*build.BuiltDep
|
||||
|
||||
var scriptArgs *build.BuildPackageFromScriptArgs
|
||||
var dbArgs *build.BuildPackageFromDbArgs
|
||||
@ -118,7 +118,11 @@ func BuildCmd() *cli.Command {
|
||||
return cliutils.FormatCliExit(gotext.Get("Cannot get absolute script path"), err)
|
||||
}
|
||||
|
||||
packages = append(packages, c.String("script-package"))
|
||||
subpackage := c.String("subpackage")
|
||||
|
||||
if subpackage != "" {
|
||||
packages = append(packages, subpackage)
|
||||
}
|
||||
|
||||
scriptArgs = &build.BuildPackageFromScriptArgs{
|
||||
Script: script,
|
||||
@ -218,9 +222,9 @@ func BuildCmd() *cli.Command {
|
||||
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))
|
||||
for _, pkg := range res {
|
||||
name := filepath.Base(pkg.Path)
|
||||
err = osutils.Move(pkg.Path, filepath.Join(wd, name))
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error moving the package"), err)
|
||||
}
|
||||
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,10 +30,7 @@ func TestE2EBashCompletion(t *testing.T) {
|
||||
"bash-completion",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
err := r.Exec(e2e.NewCommand(
|
||||
"alr", "install", "--generate-bash-completion",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
execShouldNoError(t, r, "alr", "install", "--generate-bash-completion")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
@ -25,7 +25,6 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -121,29 +120,6 @@ var COMMON_SYSTEMS []string = []string{
|
||||
"ubuntu-24.04",
|
||||
}
|
||||
|
||||
func init() {
|
||||
for _, id := range ALL_SYSTEMS {
|
||||
buildAlrTestImage(id)
|
||||
}
|
||||
}
|
||||
|
||||
func buildAlrTestImage(id string) {
|
||||
cmd := exec.Command(
|
||||
"docker",
|
||||
"build",
|
||||
"-t", fmt.Sprintf("alr-testimage-%s", id),
|
||||
"-f", fmt.Sprintf("images/Dockerfile.%s", id),
|
||||
".",
|
||||
)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -158,23 +134,39 @@ func dockerMultipleRun(t *testing.T, name string, ids []string, f func(t *testin
|
||||
e, err := e2e.New(e2e.WithVerbose(), e2e.WithName(fmt.Sprintf("alr-%s", truncatedHash)))
|
||||
assert.NoError(t, err)
|
||||
t.Cleanup(e.Close)
|
||||
imageId := fmt.Sprintf("alr-testimage-%s", id)
|
||||
imageId := fmt.Sprintf("ghcr.io/maks1ms/alr-e2e-test-image-%s", id)
|
||||
runnable := e.Runnable(dockerName).Init(
|
||||
e2e.StartOptions{
|
||||
Image: imageId,
|
||||
Image: imageId,
|
||||
Volumes: []string{
|
||||
// "./alr:/usr/bin/alr",
|
||||
"./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,
|
||||
@ -188,3 +180,23 @@ func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expect
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
const REPO_NAME_FOR_E2E_TESTS = "alr-repo"
|
||||
const REPO_URL_FOR_E2E_TESTS = "https://gitea.plemya-x.ru/Plemya-x/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",
|
||||
)
|
||||
}
|
||||
|
41
e2e-tests/firejailed_package_test.go
Normal file
41
e2e-tests/firejailed_package_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
func TestE2EFirejailedPackage(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"firejailed-package",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "alr", "build", "-p", fmt.Sprintf("%s/firejailed-pkg", REPO_NAME_FOR_E2E_TESTS))
|
||||
execShouldError(t, r, "alr", "build", "-p", fmt.Sprintf("%s/firejailed-pkg-incorrect", REPO_NAME_FOR_E2E_TESTS))
|
||||
execShouldNoError(t, r, "sh", "-c", "dpkg -c *.deb | grep -q '/usr/lib/alr/firejailed/_usr_bin_danger.sh'")
|
||||
execShouldNoError(t, r, "sh", "-c", "dpkg -c *.deb | grep -q '/usr/lib/alr/firejailed/_usr_bin_danger.sh.profile'")
|
||||
},
|
||||
)
|
||||
}
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,26 +30,9 @@ func TestE2EGroupAndSummaryField(t *testing.T) {
|
||||
"group-and-summary-field",
|
||||
RPM_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/Maks1mS/repo-for-tests.git",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group}}\" | grep ^System/Base$",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary}}\" | grep \"^Custom summary$\"",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group.Resolved}}\" | grep ^System/Base$")
|
||||
execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary.Resolved}}\" | grep \"^Custom summary$\"")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
FROM alpine:latest
|
||||
RUN adduser -s /bin/bash alr-user
|
||||
USER alr-user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -1,6 +0,0 @@
|
||||
FROM registry.altlinux.org/sisyphus/alt:latest
|
||||
RUN apt-get update && apt-get install -y ca-certificates rpm-build
|
||||
RUN useradd -m -s /bin/bash alr-user
|
||||
USER alr-user
|
||||
WORKDIR /home/alr-user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -1,4 +0,0 @@
|
||||
FROM archlinux:latest
|
||||
RUN useradd -m -s /bin/bash alr-user
|
||||
USER alr-user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -1,18 +0,0 @@
|
||||
FROM fedora:41
|
||||
RUN dnf install -y ca-certificates sudo rpm-build bindfs
|
||||
RUN <<EOF
|
||||
useradd -m -s /bin/bash -G wheel user
|
||||
echo "user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/user
|
||||
chmod 0440 /etc/sudoers.d/user
|
||||
|
||||
useradd -m -s /bin/bash alr
|
||||
mkdir -p /var/cache/alr /etc/alr
|
||||
chown alr:alr /var/cache/alr /etc/alr
|
||||
EOF
|
||||
COPY ./alr /usr/bin
|
||||
RUN <<EOF
|
||||
setcap cap_setuid,cap_setgid+ep /usr/bin/alr
|
||||
EOF
|
||||
USER user
|
||||
WORKDIR /home/user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -1,4 +0,0 @@
|
||||
FROM opensuse/leap:latest
|
||||
RUN useradd -m -s /bin/bash alr-user
|
||||
USER alr-user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -1,4 +0,0 @@
|
||||
FROM registry.red-soft.ru/ubi8/ubi:latest
|
||||
RUN useradd -m -s /bin/bash alr-user
|
||||
USER alr-user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -1,17 +0,0 @@
|
||||
FROM ubuntu:24.10
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates sudo libcap2-bin
|
||||
RUN <<EOF
|
||||
useradd -m -s /bin/bash user
|
||||
echo "user ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/user
|
||||
chmod 0440 /etc/sudoers.d/user
|
||||
|
||||
useradd -m -s /bin/bash alr
|
||||
mkdir -p /var/cache/alr /etc/alr
|
||||
chown alr:alr /var/cache/alr /etc/alr
|
||||
EOF
|
||||
COPY ./alr /usr/bin
|
||||
RUN <<EOF
|
||||
setcap cap_setuid,cap_setgid+ep /usr/bin/alr
|
||||
EOF
|
||||
USER user
|
||||
ENTRYPOINT ["tail", "-f", "/dev/null"]
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,21 +30,11 @@ func TestE2EIssue32Interactive(t *testing.T) {
|
||||
"issue-32-interactive",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
assert.NoError(t, r.Exec(e2e.NewCommand(
|
||||
"sudo", "alr", "--interactive=false", "remove", "ca-certificates",
|
||||
)))
|
||||
|
||||
assert.NoError(t, r.Exec(e2e.NewCommand(
|
||||
"sudo", "alr", "--interactive=false", "remove", "openssl",
|
||||
)))
|
||||
|
||||
assert.NoError(t, r.Exec(e2e.NewCommand(
|
||||
"alr", "fix",
|
||||
)))
|
||||
|
||||
assert.NoError(t, r.Exec(e2e.NewCommand(
|
||||
"sudo", "alr", "--interactive=false", "install", "ca-certificates",
|
||||
)))
|
||||
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")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,51 +30,11 @@ func TestE2EIssue41AutoreqSkiplist(t *testing.T) {
|
||||
"issue-41-autoreq-skiplist",
|
||||
AUTOREQ_AUTOPROV_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/Maks1mS/repo-for-tests.git",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"alr",
|
||||
"ref",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"alr",
|
||||
"build",
|
||||
"-p",
|
||||
"alr-repo/test-autoreq-autoprov",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sh",
|
||||
"-c",
|
||||
"rpm -qp --requires *.rpm | grep \"^/bin/sh$\"",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sh",
|
||||
"-c",
|
||||
"rpm -qp --requires *.rpm | grep \"^/bin/bash$\"",
|
||||
))
|
||||
assert.Error(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sh",
|
||||
"-c",
|
||||
"rpm -qp --requires *.rpm | grep \"^/bin/zsh$\"",
|
||||
))
|
||||
assert.Error(t, err)
|
||||
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$\"")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,26 +30,10 @@ func TestE2EIssue50InstallMultiple(t *testing.T) {
|
||||
"issue-50-install-multiple",
|
||||
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/Maks1mS/repo-for-tests.git",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sudo", "alr", "in", "foo-pkg", "bar-pkg",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand("cat", "/opt/foo"))
|
||||
assert.NoError(t, err)
|
||||
err = r.Exec(e2e.NewCommand("cat", "/opt/bar"))
|
||||
assert.NoError(t, err)
|
||||
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")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,23 +30,8 @@ func TestE2EIssue53LcAllCInfo(t *testing.T) {
|
||||
"issue-53-lc-all-c-info",
|
||||
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",
|
||||
"LANG=C alr info alr-bin",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
defaultPrepare(t, r)
|
||||
execShouldNoError(t, r, "bash", "-c", "LANG=C alr info foo-pkg")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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
|
||||
@ -21,7 +21,6 @@ package e2etests_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/efficientgo/e2e"
|
||||
)
|
||||
|
||||
@ -31,28 +30,11 @@ func TestE2EIssue59RmCompletion(t *testing.T) {
|
||||
"issue-59-rm-completion",
|
||||
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/Maks1mS/repo-for-tests.git",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand(
|
||||
"sudo", "alr", "in", "foo-pkg", "bar-pkg",
|
||||
))
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = r.Exec(e2e.NewCommand("sh", "-c", "alr rm --generate-bash-completion | grep ^foo-pkg$"))
|
||||
assert.NoError(t, err)
|
||||
err = r.Exec(e2e.NewCommand("sh", "-c", "alr rm --generate-bash-completion | grep ^bar-pkg$"))
|
||||
assert.NoError(t, err)
|
||||
err = r.Exec(e2e.NewCommand("sh", "-c", "alr rm --generate-bash-completion | grep ^test-autoreq-autoprov$"))
|
||||
assert.Error(t, err)
|
||||
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")
|
||||
},
|
||||
)
|
||||
}
|
53
e2e-tests/issue_76_single_package_repo_test.go
Normal file
53
e2e-tests/issue_76_single_package_repo_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
// 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 Test75SinglePackageRepo(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-76-single-package-repo",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
execShouldNoError(t, r,
|
||||
"sudo",
|
||||
"alr",
|
||||
"repo",
|
||||
"add",
|
||||
REPO_NAME_FOR_E2E_TESTS,
|
||||
"https://gitea.plemya-x.ru/Maks1mS/test-single-package-alr-repo.git",
|
||||
)
|
||||
execShouldNoError(t, r, "sudo", "alr", "repo", "set-ref", REPO_NAME_FOR_E2E_TESTS, "1075c918be")
|
||||
execShouldNoError(t, r, "alr", "ref")
|
||||
execShouldNoError(t, r, "sudo", "alr", "in", "test-single-repo")
|
||||
execShouldNoError(t, r, "sh", "-c", "alr list -U")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 0 || exit 1")
|
||||
execShouldNoError(t, r, "sudo", "alr", "repo", "set-ref", REPO_NAME_FOR_E2E_TESTS, "5e361c50d7")
|
||||
execShouldNoError(t, r, "sudo", "alr", "ref")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 1 || exit 1")
|
||||
execShouldNoError(t, r, "sudo", "alr", "up")
|
||||
execShouldNoError(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 0 || 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")
|
||||
},
|
||||
)
|
||||
}
|
49
e2e-tests/issue_94_twice_build_test.go
Normal file
49
e2e-tests/issue_94_twice_build_test.go
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/>.
|
||||
|
||||
//go:build e2e
|
||||
|
||||
package e2etests_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/efficientgo/e2e"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestE2EIssue94TwiceBuild(t *testing.T) {
|
||||
dockerMultipleRun(
|
||||
t,
|
||||
"issue-94-twice-build",
|
||||
COMMON_SYSTEMS,
|
||||
func(t *testing.T, r e2e.Runnable) {
|
||||
defaultPrepare(t, r)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
err := r.Exec(
|
||||
e2e.NewCommand("sudo", "alr", "in", "test-94-app"),
|
||||
e2e.WithExecOptionStderr(&stderr),
|
||||
)
|
||||
assert.NoError(t, err, "command failed")
|
||||
|
||||
output := stderr.String()
|
||||
assert.Equal(t, 1, strings.Count(output, "Building package name=test-94-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
|
||||
|
34
fix.go
34
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
|
||||
@ -20,6 +20,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -57,7 +58,6 @@ func FixCmd() *cli.Command {
|
||||
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 {
|
||||
@ -71,7 +71,13 @@ func FixCmd() *cli.Command {
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
err = os.RemoveAll(filepath.Join(paths.CacheDir, entry))
|
||||
fullPath := filepath.Join(paths.CacheDir, entry)
|
||||
|
||||
if err := makeWritableRecursive(fullPath); err != nil {
|
||||
slog.Debug("Failed to make path writable", "path", fullPath, "error", err)
|
||||
}
|
||||
|
||||
err = os.RemoveAll(fullPath)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Unable to remove cache item (%s)", entry), err)
|
||||
}
|
||||
@ -101,3 +107,23 @@ func FixCmd() *cli.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func makeWritableRecursive(path string) error {
|
||||
return filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newMode := info.Mode() | 0o200
|
||||
if d.IsDir() {
|
||||
newMode |= 0o100
|
||||
}
|
||||
|
||||
return os.Chmod(path, newMode)
|
||||
})
|
||||
}
|
||||
|
6
gen.go
6
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
|
||||
@ -25,7 +25,7 @@ import (
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/gen"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/gen"
|
||||
)
|
||||
|
||||
func GenCmd() *cli.Command {
|
||||
|
12
go.mod
12
go.mod
@ -8,7 +8,6 @@ require (
|
||||
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
|
||||
@ -42,6 +41,7 @@ require (
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.25.0
|
||||
mvdan.cc/sh/v3 v3.10.0
|
||||
xorm.io/xorm v1.3.9
|
||||
)
|
||||
|
||||
require (
|
||||
@ -52,7 +52,6 @@ require (
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // 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
|
||||
@ -79,6 +78,7 @@ require (
|
||||
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/goccy/go-json v0.8.1 // 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
|
||||
@ -90,10 +90,10 @@ require (
|
||||
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
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
@ -105,6 +105,8 @@ require (
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
@ -117,9 +119,10 @@ require (
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
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/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
@ -145,4 +148,5 @@ require (
|
||||
modernc.org/opt v0.1.3 // indirect
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.0.1 // indirect
|
||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect
|
||||
)
|
||||
|
43
go.sum
43
go.sum
@ -17,6 +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.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||
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=
|
||||
@ -137,6 +139,7 @@ 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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
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=
|
||||
@ -153,10 +156,13 @@ github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
|
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/goccy/go-json v0.8.1 h1:4/Wjm0JIJaTDm8K1KcGrLHJoa8EsJ13YWeX+6Kfq6uI=
|
||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -176,6 +182,7 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
|
||||
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.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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=
|
||||
@ -187,6 +194,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
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=
|
||||
@ -229,6 +237,8 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq
|
||||
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=
|
||||
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@ -245,6 +255,8 @@ 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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
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=
|
||||
@ -269,8 +281,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leonelquinteros/gotext v1.7.0 h1:jcJmF4AXqyamP7vuw2MMIKs+O3jAEmvrc5JQiI8Ht/8=
|
||||
github.com/leonelquinteros/gotext v1.7.0/go.mod h1:qJdoQuERPpccw7L70uoU+K/BvTfRBHYsisCQyFLXyvw=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
|
||||
@ -306,6 +319,11 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
@ -320,6 +338,10 @@ github.com/nwaples/rardecode/v2 v2.0.0-beta.2 h1:e3mzJFJs4k83GXBEiTaQ5HgSc/kOK8q
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
|
||||
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/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
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=
|
||||
@ -358,8 +380,9 @@ github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtC
|
||||
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
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/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
@ -374,6 +397,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@ -382,6 +406,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/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
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=
|
||||
@ -453,6 +479,7 @@ 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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@ -488,6 +515,7 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
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-20180909124046-d0be0721c37e/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=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -612,8 +640,13 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
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=
|
||||
@ -659,3 +692,7 @@ mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 h1:bvLlAPW1ZMTWA32LuZMBEGHAUOcATZjzHcotf3SWweM=
|
||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
|
||||
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||
|
@ -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
info.go
19
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
|
||||
@ -30,9 +30,9 @@ import (
|
||||
|
||||
"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/overrides"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
)
|
||||
|
||||
@ -67,15 +67,8 @@ func InfoCmd() *cli.Command {
|
||||
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)
|
||||
}
|
||||
|
||||
for _, pkg := range result {
|
||||
fmt.Println(pkg.Name)
|
||||
}
|
||||
return nil
|
||||
@ -96,6 +89,7 @@ func InfoCmd() *cli.Command {
|
||||
New(ctx).
|
||||
WithConfig().
|
||||
WithDB().
|
||||
WithDistroInfo().
|
||||
WithRepos().
|
||||
Build()
|
||||
if err != nil {
|
||||
@ -144,7 +138,8 @@ func InfoCmd() *cli.Command {
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
if !all {
|
||||
err = yaml.NewEncoder(os.Stdout).Encode(overrides.ResolvePackage(&pkg, names))
|
||||
alrsh.ResolvePackage(&pkg, names)
|
||||
err = yaml.NewEncoder(os.Stdout).Encode(pkg)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error encoding script variables"), err)
|
||||
}
|
||||
|
50
install.go
50
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
|
||||
@ -25,13 +25,12 @@ import (
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/build"
|
||||
"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/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
"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/types"
|
||||
)
|
||||
|
||||
func InstallCmd() *cli.Command {
|
||||
@ -46,11 +45,7 @@ func InstallCmd() *cli.Command {
|
||||
Usage: gotext.Get("Build package from scratch even if there's an already built package available"),
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
if err := utils.ExitIfNotRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if args.Len() < 1 {
|
||||
return cliutils.FormatCliExit(gotext.Get("Command install expected at least 1 argument, got %d", args.Len()), nil)
|
||||
@ -102,7 +97,7 @@ func InstallCmd() *cli.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
err = builder.InstallPkgs(
|
||||
_, err = builder.InstallPkgs(
|
||||
ctx,
|
||||
&build.BuildArgs{
|
||||
Opts: &types.BuildOpts{
|
||||
@ -115,11 +110,11 @@ func InstallCmd() *cli.Command {
|
||||
args.Slice(),
|
||||
)
|
||||
if err != nil {
|
||||
return cliutils.FormatCliExit(gotext.Get("Error parsing os release"), err)
|
||||
return cliutils.FormatCliExit(gotext.Get("Error when installing the package"), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}),
|
||||
BashComplete: cliutils.BashCompleteWithError(func(c *cli.Context) error {
|
||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||
return err
|
||||
@ -140,15 +135,8 @@ func InstallCmd() *cli.Command {
|
||||
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)
|
||||
}
|
||||
|
||||
for _, pkg := range result {
|
||||
fmt.Println(pkg.Name)
|
||||
}
|
||||
|
||||
@ -194,30 +182,18 @@ func RemoveCmd() *cli.Command {
|
||||
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)
|
||||
}
|
||||
|
||||
for _, pkg := range result {
|
||||
_, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println(pkg.Name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
Action: func(c *cli.Context) error {
|
||||
if err := utils.ExitIfNotRoot(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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)
|
||||
@ -239,6 +215,6 @@ func RemoveCmd() *cli.Command {
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -32,14 +32,14 @@ import (
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/build"
|
||||
"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/manager"
|
||||
"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 {
|
||||
|
@ -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,18 +24,17 @@ import (
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"mvdan.cc/sh/v3/syntax"
|
||||
"mvdan.cc/sh/v3/syntax/typedjson"
|
||||
|
||||
"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/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"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/types"
|
||||
)
|
||||
|
||||
type BuildInput struct {
|
||||
@ -133,54 +132,33 @@ type RepositoryProvider interface {
|
||||
|
||||
// ================================================
|
||||
|
||||
type ScriptFile struct {
|
||||
File *syntax.File
|
||||
type BuiltDep struct {
|
||||
Name string
|
||||
Path string
|
||||
}
|
||||
|
||||
func (s *ScriptFile) GobEncode() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
if err := enc.Encode(s.Path); err != nil {
|
||||
return nil, err
|
||||
func Map[T, R any](items []T, f func(T) R) []R {
|
||||
res := make([]R, len(items))
|
||||
for i, item := range items {
|
||||
res[i] = f(item)
|
||||
}
|
||||
var fileBuf bytes.Buffer
|
||||
if err := typedjson.Encode(&fileBuf, s.File); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileData := fileBuf.Bytes()
|
||||
if err := enc.Encode(fileData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *ScriptFile) GobDecode(data []byte) error {
|
||||
buf := bytes.NewBuffer(data)
|
||||
dec := gob.NewDecoder(buf)
|
||||
if err := dec.Decode(&s.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
var fileData []byte
|
||||
if err := dec.Decode(&fileData); err != nil {
|
||||
return err
|
||||
}
|
||||
fileReader := bytes.NewReader(fileData)
|
||||
file, err := typedjson.Decode(fileReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.File = file.(*syntax.File)
|
||||
return nil
|
||||
func GetBuiltPaths(deps []*BuiltDep) []string {
|
||||
return Map(deps, func(dep *BuiltDep) string {
|
||||
return dep.Path
|
||||
})
|
||||
}
|
||||
|
||||
type BuildResult struct {
|
||||
PackagePaths []string
|
||||
PackageNames []string
|
||||
func GetBuiltName(deps []*BuiltDep) []string {
|
||||
return Map(deps, func(dep *BuiltDep) string {
|
||||
return dep.Name
|
||||
})
|
||||
}
|
||||
|
||||
type PackageFinder interface {
|
||||
FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error)
|
||||
FindPkgs(ctx context.Context, pkgs []string) (map[string][]alrsh.Package, []string, error)
|
||||
}
|
||||
|
||||
type Config interface {
|
||||
@ -195,12 +173,12 @@ type FunctionsOutput struct {
|
||||
// EXECUTORS
|
||||
|
||||
type ScriptResolverExecutor interface {
|
||||
ResolveScript(ctx context.Context, pkg *db.Package) *ScriptInfo
|
||||
ResolveScript(ctx context.Context, pkg *alrsh.Package) *ScriptInfo
|
||||
}
|
||||
|
||||
type ScriptExecutor interface {
|
||||
ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error)
|
||||
ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error)
|
||||
ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error)
|
||||
ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error)
|
||||
PrepareDirs(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
@ -209,27 +187,27 @@ type ScriptExecutor interface {
|
||||
ExecuteSecondPass(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
sf *ScriptFile,
|
||||
varsOfPackages []*types.BuildVars,
|
||||
sf *alrsh.ScriptFile,
|
||||
varsOfPackages []*alrsh.Package,
|
||||
repoDeps []string,
|
||||
builtNames []string,
|
||||
builtDeps []*BuiltDep,
|
||||
basePkg string,
|
||||
) (*SecondPassResult, error)
|
||||
) ([]*BuiltDep, error)
|
||||
}
|
||||
|
||||
type CacheExecutor interface {
|
||||
CheckForBuiltPackage(ctx context.Context, input *BuildInput, vars *types.BuildVars) (string, bool, error)
|
||||
CheckForBuiltPackage(ctx context.Context, input *BuildInput, vars *alrsh.Package) (string, bool, error)
|
||||
}
|
||||
|
||||
type ScriptViewerExecutor interface {
|
||||
ViewScript(ctx context.Context, input *BuildInput, sf *ScriptFile, basePkg string) error
|
||||
ViewScript(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile, basePkg string) error
|
||||
}
|
||||
|
||||
type CheckerExecutor interface {
|
||||
PerformChecks(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
vars *types.BuildVars,
|
||||
vars *alrsh.Package,
|
||||
) (bool, error)
|
||||
}
|
||||
|
||||
@ -307,7 +285,7 @@ func (b *BuildArgs) PkgFormat() string {
|
||||
|
||||
type BuildPackageFromDbArgs struct {
|
||||
BuildArgs
|
||||
Package *db.Package
|
||||
Package *alrsh.Package
|
||||
Packages []string
|
||||
}
|
||||
|
||||
@ -320,7 +298,7 @@ type BuildPackageFromScriptArgs struct {
|
||||
func (b *Builder) BuildPackageFromDb(
|
||||
ctx context.Context,
|
||||
args *BuildPackageFromDbArgs,
|
||||
) (*BuildResult, error) {
|
||||
) ([]*BuiltDep, error) {
|
||||
scriptInfo := b.scriptResolver.ResolveScript(ctx, args.Package)
|
||||
|
||||
return b.BuildPackage(ctx, &BuildInput{
|
||||
@ -336,7 +314,7 @@ func (b *Builder) BuildPackageFromDb(
|
||||
func (b *Builder) BuildPackageFromScript(
|
||||
ctx context.Context,
|
||||
args *BuildPackageFromScriptArgs,
|
||||
) (*BuildResult, error) {
|
||||
) ([]*BuiltDep, error) {
|
||||
return b.BuildPackage(ctx, &BuildInput{
|
||||
script: args.Script,
|
||||
repository: "default",
|
||||
@ -350,43 +328,46 @@ func (b *Builder) BuildPackageFromScript(
|
||||
func (b *Builder) BuildPackage(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
) (*BuildResult, error) {
|
||||
) ([]*BuiltDep, error) {
|
||||
scriptPath := input.script
|
||||
|
||||
slog.Debug("ReadScript")
|
||||
sf, err := b.scriptExecutor.ReadScript(ctx, scriptPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed reading script: %w", err)
|
||||
}
|
||||
|
||||
slog.Debug("ExecuteFirstPass")
|
||||
basePkg, varsOfPackages, err := b.scriptExecutor.ExecuteFirstPass(ctx, input, sf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed ExecuteFirstPass: %w", err)
|
||||
}
|
||||
|
||||
builtPaths := make([]string, 0)
|
||||
var builtDeps []*BuiltDep
|
||||
|
||||
if !input.opts.Clean {
|
||||
var remainingVars []*types.BuildVars
|
||||
var remainingVars []*alrsh.Package
|
||||
for _, vars := range varsOfPackages {
|
||||
builtPkgPath, ok, err := b.cacheExecutor.CheckForBuiltPackage(ctx, input, vars)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
builtPaths = append(builtPaths, builtPkgPath)
|
||||
builtDeps = append(builtDeps, &BuiltDep{
|
||||
Path: builtPkgPath,
|
||||
})
|
||||
} else {
|
||||
remainingVars = append(remainingVars, vars)
|
||||
}
|
||||
}
|
||||
|
||||
if len(remainingVars) == 0 {
|
||||
return &BuildResult{builtPaths, nil}, nil
|
||||
return builtDeps, nil
|
||||
}
|
||||
}
|
||||
|
||||
slog.Debug("ViewScript")
|
||||
slog.Debug("", "varsOfPackages", varsOfPackages)
|
||||
err = b.scriptViewerExecutor.ViewScript(ctx, input, sf, basePkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -410,11 +391,11 @@ func (b *Builder) BuildPackage(
|
||||
sources := []string{}
|
||||
checksums := []string{}
|
||||
for _, vars := range varsOfPackages {
|
||||
buildDepends = append(buildDepends, vars.BuildDepends...)
|
||||
optDepends = append(optDepends, vars.OptDepends...)
|
||||
depends = append(depends, vars.Depends...)
|
||||
sources = append(sources, vars.Sources...)
|
||||
checksums = append(checksums, vars.Checksums...)
|
||||
buildDepends = append(buildDepends, vars.BuildDepends.Resolved()...)
|
||||
optDepends = append(optDepends, vars.OptDepends.Resolved()...)
|
||||
depends = append(depends, vars.Depends.Resolved()...)
|
||||
sources = append(sources, vars.Sources.Resolved()...)
|
||||
checksums = append(checksums, vars.Checksums.Resolved()...)
|
||||
}
|
||||
buildDepends = removeDuplicates(buildDepends)
|
||||
optDepends = removeDuplicates(optDepends)
|
||||
@ -427,19 +408,32 @@ func (b *Builder) BuildPackage(
|
||||
sources, checksums = removeDuplicatesSources(sources, checksums)
|
||||
|
||||
slog.Debug("installBuildDeps")
|
||||
err = b.installBuildDeps(ctx, input, buildDepends)
|
||||
alrBuildDeps, err := b.installBuildDeps(ctx, input, buildDepends)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
slog.Debug("installOptDeps")
|
||||
err = b.installOptDeps(ctx, input, optDepends)
|
||||
_, err = b.installOptDeps(ctx, input, optDepends)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
depNames := make(map[string]struct{})
|
||||
for _, dep := range alrBuildDeps {
|
||||
depNames[dep.Name] = struct{}{}
|
||||
}
|
||||
|
||||
// We filter so as not to re-build what has already been built at the `installBuildDeps` stage.
|
||||
var filteredDepends []string
|
||||
for _, d := range depends {
|
||||
if _, found := depNames[d]; !found {
|
||||
filteredDepends = append(filteredDepends, d)
|
||||
}
|
||||
}
|
||||
|
||||
slog.Debug("BuildALRDeps")
|
||||
_, builtNames, repoDeps, err := b.BuildALRDeps(ctx, input, depends)
|
||||
newBuiltDeps, repoDeps, err := b.BuildALRDeps(ctx, input, filteredDepends)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -450,8 +444,6 @@ func (b *Builder) BuildPackage(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// builtPaths = append(builtPaths, newBuildPaths...)
|
||||
|
||||
slog.Info(gotext.Get("Downloading sources"))
|
||||
slog.Debug("DownloadSources")
|
||||
err = b.sourceExecutor.DownloadSources(
|
||||
@ -467,6 +459,8 @@ func (b *Builder) BuildPackage(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builtDeps = removeDuplicates(append(builtDeps, newBuiltDeps...))
|
||||
|
||||
slog.Debug("ExecuteSecondPass")
|
||||
res, err := b.scriptExecutor.ExecuteSecondPass(
|
||||
ctx,
|
||||
@ -474,25 +468,21 @@ func (b *Builder) BuildPackage(
|
||||
sf,
|
||||
varsOfPackages,
|
||||
repoDeps,
|
||||
builtNames,
|
||||
builtDeps,
|
||||
basePkg,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pkgPaths := removeDuplicates(res.BuiltPaths)
|
||||
pkgNames := removeDuplicates(res.BuiltNames)
|
||||
builtDeps = removeDuplicates(append(builtDeps, res...))
|
||||
|
||||
return &BuildResult{
|
||||
PackagePaths: pkgPaths,
|
||||
PackageNames: pkgNames,
|
||||
}, nil
|
||||
return builtDeps, nil
|
||||
}
|
||||
|
||||
type InstallPkgsArgs struct {
|
||||
BuildArgs
|
||||
AlrPkgs []db.Package
|
||||
AlrPkgs []alrsh.Package
|
||||
NativePkgs []string
|
||||
}
|
||||
|
||||
@ -503,7 +493,7 @@ func (b *Builder) InstallALRPackages(
|
||||
BuildOptsProvider
|
||||
PkgFormatProvider
|
||||
},
|
||||
alrPkgs []db.Package,
|
||||
alrPkgs []alrsh.Package,
|
||||
) error {
|
||||
for _, pkg := range alrPkgs {
|
||||
res, err := b.BuildPackageFromDb(
|
||||
@ -523,7 +513,7 @@ func (b *Builder) InstallALRPackages(
|
||||
}
|
||||
|
||||
err = b.installerExecutor.InstallLocal(
|
||||
res.PackagePaths,
|
||||
GetBuiltPaths(res),
|
||||
&manager.Opts{
|
||||
NoConfirm: !input.BuildOpts().Interactive,
|
||||
},
|
||||
@ -544,13 +534,13 @@ func (b *Builder) BuildALRDeps(
|
||||
PkgFormatProvider
|
||||
},
|
||||
depends []string,
|
||||
) (builtPaths, builtNames, repoDeps []string, err error) {
|
||||
) (buildDeps []*BuiltDep, repoDeps []string, err error) {
|
||||
if len(depends) > 0 {
|
||||
slog.Info(gotext.Get("Installing dependencies"))
|
||||
|
||||
found, notFound, err := b.repos.FindPkgs(ctx, depends) // Поиск зависимостей
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, fmt.Errorf("failed FindPkgs: %w", err)
|
||||
}
|
||||
repoDeps = notFound
|
||||
|
||||
@ -562,7 +552,7 @@ func (b *Builder) BuildALRDeps(
|
||||
input.BuildOpts().Interactive,
|
||||
)
|
||||
type item struct {
|
||||
pkg *db.Package
|
||||
pkg *alrsh.Package
|
||||
packages []string
|
||||
}
|
||||
pkgsMap := make(map[string]*item)
|
||||
@ -597,20 +587,17 @@ func (b *Builder) BuildALRDeps(
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, nil, fmt.Errorf("failed build package from db: %w", err)
|
||||
}
|
||||
|
||||
builtPaths = append(builtPaths, res.PackagePaths...)
|
||||
builtNames = append(builtNames, res.PackageNames...)
|
||||
buildDeps = append(buildDeps, res...)
|
||||
}
|
||||
}
|
||||
|
||||
// Удаляем возможные дубликаты, которые могут быть введены, если
|
||||
// несколько зависимостей зависят от одних и тех же пакетов.
|
||||
repoDeps = removeDuplicates(repoDeps)
|
||||
builtPaths = removeDuplicates(builtPaths)
|
||||
builtNames = removeDuplicates(builtNames)
|
||||
return builtPaths, builtNames, repoDeps, nil
|
||||
buildDeps = removeDuplicates(buildDeps)
|
||||
|
||||
return buildDeps, repoDeps, nil
|
||||
}
|
||||
|
||||
func (i *Builder) installBuildDeps(
|
||||
@ -621,19 +608,20 @@ func (i *Builder) installBuildDeps(
|
||||
PkgFormatProvider
|
||||
},
|
||||
pkgs []string,
|
||||
) error {
|
||||
) ([]*BuiltDep, error) {
|
||||
var builtDeps []*BuiltDep
|
||||
if len(pkgs) > 0 {
|
||||
deps, err := i.installerExecutor.RemoveAlreadyInstalled(pkgs)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = i.InstallPkgs(ctx, input, deps) // Устанавливаем выбранные пакеты
|
||||
builtDeps, err = i.InstallPkgs(ctx, input, deps) // Устанавливаем выбранные пакеты
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return builtDeps, nil
|
||||
}
|
||||
|
||||
func (i *Builder) installOptDeps(
|
||||
@ -644,10 +632,11 @@ func (i *Builder) installOptDeps(
|
||||
PkgFormatProvider
|
||||
},
|
||||
pkgs []string,
|
||||
) error {
|
||||
) ([]*BuiltDep, error) {
|
||||
var builtDeps []*BuiltDep
|
||||
optDeps, err := i.installerExecutor.RemoveAlreadyInstalled(pkgs)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if len(optDeps) > 0 {
|
||||
optDeps, err := cliutils.ChooseOptDepends(
|
||||
@ -657,19 +646,19 @@ func (i *Builder) installOptDeps(
|
||||
input.BuildOpts().Interactive,
|
||||
) // Пользователя просят выбрать опциональные зависимости
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(optDeps) == 0 {
|
||||
return nil
|
||||
return builtDeps, nil
|
||||
}
|
||||
|
||||
err = i.InstallPkgs(ctx, input, optDeps) // Устанавливаем выбранные пакеты
|
||||
builtDeps, err = i.InstallPkgs(ctx, input, optDeps) // Устанавливаем выбранные пакеты
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return builtDeps, nil
|
||||
}
|
||||
|
||||
func (i *Builder) InstallPkgs(
|
||||
@ -680,18 +669,18 @@ func (i *Builder) InstallPkgs(
|
||||
PkgFormatProvider
|
||||
},
|
||||
pkgs []string,
|
||||
) error {
|
||||
builtPaths, _, repoDeps, err := i.BuildALRDeps(ctx, input, pkgs)
|
||||
) ([]*BuiltDep, error) {
|
||||
builtDeps, repoDeps, err := i.BuildALRDeps(ctx, input, pkgs)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(builtPaths) > 0 {
|
||||
err = i.installerExecutor.InstallLocal(builtPaths, &manager.Opts{
|
||||
if len(builtDeps) > 0 {
|
||||
err = i.installerExecutor.InstallLocal(GetBuiltPaths(builtDeps), &manager.Opts{
|
||||
NoConfirm: !input.BuildOpts().Interactive,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,9 +689,9 @@ func (i *Builder) InstallPkgs(
|
||||
NoConfirm: !input.BuildOpts().Interactive,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return builtDeps, nil
|
||||
}
|
@ -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
|
||||
@ -28,9 +28,9 @@ import (
|
||||
|
||||
"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/types"
|
||||
"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/internal/manager"
|
||||
)
|
||||
|
||||
type TestPackageFinder struct {
|
@ -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
|
||||
@ -23,7 +23,7 @@ import (
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
@ -33,7 +33,7 @@ type Cache struct {
|
||||
func (c *Cache) CheckForBuiltPackage(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
vars *types.BuildVars,
|
||||
vars *alrsh.Package,
|
||||
) (string, bool, error) {
|
||||
filename, err := pkgFileName(input, vars)
|
||||
if err != nil {
|
||||
@ -56,7 +56,7 @@ func pkgFileName(
|
||||
PkgFormatProvider
|
||||
RepositoryProvider
|
||||
},
|
||||
vars *types.BuildVars,
|
||||
vars *alrsh.Package,
|
||||
) (string, error) {
|
||||
pkgInfo := getBasePkgInfo(vars, input)
|
||||
|
@ -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
|
||||
@ -24,8 +24,8 @@ import (
|
||||
|
||||
"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"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
type Checker struct {
|
||||
@ -35,7 +35,7 @@ type Checker struct {
|
||||
func (c *Checker) PerformChecks(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
vars *types.BuildVars,
|
||||
vars *alrsh.Package,
|
||||
) (bool, error) {
|
||||
if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) { // Проверяем совместимость архитектуры
|
||||
cont, err := cliutils.YesNoPrompt(
|
@ -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
|
||||
@ -19,7 +19,7 @@ package build
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
type BaseDirProvider interface {
|
@ -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
|
||||
@ -27,7 +27,7 @@ import (
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
func rpmFindDependenciesALTLinux(ctx context.Context, pkgInfo *nfpm.Info, dirs types.Directories, command string, envs []string, updateFunc func(string)) error {
|
@ -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
|
||||
@ -23,7 +23,7 @@ import (
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
type EmptyFindProvReq struct{}
|
@ -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
|
||||
@ -28,7 +28,7 @@ import (
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
type FedoraFindProvReq struct{}
|
@ -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
|
||||
@ -21,8 +21,8 @@ import (
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
|
||||
"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/types"
|
||||
)
|
||||
|
||||
type ProvReqFinder interface {
|
237
internal/build/firejail.go
Normal file
237
internal/build/firejail.go
Normal file
@ -0,0 +1,237 @@
|
||||
// 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2/files"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/osutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
const (
|
||||
firejailedDir = "/usr/lib/alr/firejailed"
|
||||
defaultDirMode = 0o755
|
||||
defaultScriptMode = 0o755
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidDestination = errors.New("invalid destination path")
|
||||
ErrMissingProfile = errors.New("default profile is missing")
|
||||
ErrEmptyPackageName = errors.New("package name cannot be empty")
|
||||
)
|
||||
|
||||
var binaryDirectories = []string{
|
||||
"/usr/bin/",
|
||||
"/bin/",
|
||||
"/usr/local/bin/",
|
||||
}
|
||||
|
||||
func applyFirejailIntegration(
|
||||
vars *alrsh.Package,
|
||||
dirs types.Directories,
|
||||
contents []*files.Content,
|
||||
) ([]*files.Content, error) {
|
||||
slog.Info(gotext.Get("Applying FireJail integration"), "package", vars.Name)
|
||||
|
||||
if err := createFirejailedDirectory(dirs.PkgDir); err != nil {
|
||||
return nil, fmt.Errorf("failed to create firejailed directory: %w", err)
|
||||
}
|
||||
|
||||
newContents, err := processBinaryFiles(vars, contents, dirs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to process binary files: %w", err)
|
||||
}
|
||||
|
||||
return append(contents, newContents...), nil
|
||||
}
|
||||
|
||||
func createFirejailedDirectory(pkgDir string) error {
|
||||
firejailedPath := filepath.Join(pkgDir, firejailedDir)
|
||||
return os.MkdirAll(firejailedPath, defaultDirMode)
|
||||
}
|
||||
|
||||
func processBinaryFiles(pkg *alrsh.Package, contents []*files.Content, dirs types.Directories) ([]*files.Content, error) {
|
||||
var newContents []*files.Content
|
||||
|
||||
for _, content := range contents {
|
||||
if content.Type == "dir" {
|
||||
continue
|
||||
}
|
||||
|
||||
if !isBinaryFile(content.Destination) {
|
||||
slog.Debug("content not binary file", "content", content)
|
||||
continue
|
||||
}
|
||||
|
||||
slog.Debug("process content", "content", content)
|
||||
|
||||
newContent, err := createFirejailedBinary(pkg, content, dirs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create firejailed binary for %s: %w", content.Destination, err)
|
||||
}
|
||||
|
||||
if newContent != nil {
|
||||
newContents = append(newContents, newContent...)
|
||||
}
|
||||
}
|
||||
|
||||
return newContents, nil
|
||||
}
|
||||
|
||||
func isBinaryFile(destination string) bool {
|
||||
for _, binDir := range binaryDirectories {
|
||||
if strings.HasPrefix(destination, binDir) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func createFirejailedBinary(
|
||||
pkg *alrsh.Package,
|
||||
content *files.Content,
|
||||
dirs types.Directories,
|
||||
) ([]*files.Content, error) {
|
||||
origFilePath, err := generateFirejailedPath(content.Destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
profiles := pkg.FireJailProfiles.Resolved()
|
||||
sourceProfilePath, ok := profiles[content.Destination]
|
||||
|
||||
if !ok {
|
||||
sourceProfilePath, ok = profiles["default"]
|
||||
if !ok {
|
||||
return nil, errors.New("default profile is missing")
|
||||
}
|
||||
}
|
||||
|
||||
sourceProfilePath = filepath.Join(dirs.ScriptDir, sourceProfilePath)
|
||||
dest, err := createFirejailProfilePath(content.Destination)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = createProfile(filepath.Join(dirs.PkgDir, dest), sourceProfilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := osutils.Move(content.Source, filepath.Join(dirs.PkgDir, origFilePath)); err != nil {
|
||||
return nil, fmt.Errorf("failed to move original binary: %w", err)
|
||||
}
|
||||
|
||||
// Create wrapper script
|
||||
if err := createWrapperScript(content.Source, origFilePath, dest); err != nil {
|
||||
return nil, fmt.Errorf("failed to create wrapper script: %w", err)
|
||||
}
|
||||
|
||||
profile, err := getContentFromPath(dest, dirs.PkgDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bin, err := getContentFromPath(origFilePath, dirs.PkgDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []*files.Content{
|
||||
bin,
|
||||
profile,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getContentFromPath(path, base string) (*files.Content, error) {
|
||||
absPath := filepath.Join(base, path)
|
||||
|
||||
fi, err := os.Lstat(absPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get file info: %w", err)
|
||||
}
|
||||
|
||||
return &files.Content{
|
||||
Source: absPath,
|
||||
Destination: path,
|
||||
FileInfo: &files.ContentFileInfo{
|
||||
MTime: fi.ModTime(),
|
||||
Mode: fi.Mode(),
|
||||
Size: fi.Size(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func generateSafeName(destination string) (string, error) {
|
||||
cleanPath := strings.TrimPrefix(destination, ".")
|
||||
if cleanPath == "" {
|
||||
return "", fmt.Errorf("invalid destination path: %s", destination)
|
||||
}
|
||||
return strings.ReplaceAll(cleanPath, "/", "_"), nil
|
||||
}
|
||||
|
||||
func generateFirejailedPath(destination string) (string, error) {
|
||||
safeName, err := generateSafeName(destination)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(firejailedDir, safeName), nil
|
||||
}
|
||||
|
||||
func createProfile(destProfilePath, profilePath string) error {
|
||||
srcFile, err := os.Open(profilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
destFile, err := os.Create(destProfilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destFile.Close()
|
||||
|
||||
_, err = io.Copy(destFile, srcFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return destFile.Sync()
|
||||
}
|
||||
|
||||
func createWrapperScript(scriptPath, origFilePath, profilePath string) error {
|
||||
scriptContent := fmt.Sprintf("#!/bin/bash\nexec firejail --profile=%q %q \"$@\"\n", profilePath, origFilePath)
|
||||
return os.WriteFile(scriptPath, []byte(scriptContent), defaultDirMode)
|
||||
}
|
||||
|
||||
func createFirejailProfilePath(binaryPath string) (string, error) {
|
||||
name, err := generateSafeName(binaryPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(firejailedDir, fmt.Sprintf("%s.profile", name)), nil
|
||||
}
|
316
internal/build/firejail_test.go
Normal file
316
internal/build/firejail_test.go
Normal file
@ -0,0 +1,316 @@
|
||||
// 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 (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2/files"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
func TestIsBinaryFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
destination string
|
||||
expected bool
|
||||
}{
|
||||
{"usr/bin binary", "/usr/bin/test", true},
|
||||
{"bin binary", "/bin/test", true},
|
||||
{"usr/local/bin binary", "/usr/local/bin/test", true},
|
||||
{"lib file", "/usr/lib/test.so", false},
|
||||
{"etc file", "/etc/config", false},
|
||||
{"empty destination", "", false},
|
||||
{"root level file", "./test", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := isBinaryFile(tt.destination)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateSafeName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
destination string
|
||||
expected string
|
||||
expectError bool
|
||||
}{
|
||||
{"usr/bin path", "./usr/bin/test", "_usr_bin_test", false},
|
||||
{"bin path", "./bin/test", "_bin_test", false},
|
||||
{"nested path", "./usr/local/bin/app", "_usr_local_bin_app", false},
|
||||
{"path with spaces", "./usr/bin/my app", "_usr_bin_my app", false},
|
||||
{"empty after trim", ".", "", true},
|
||||
{"empty string", "", "", true},
|
||||
{"only dots", "..", ".", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := generateSafeName(tt.destination)
|
||||
if tt.expectError {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateWrapperScript(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
origFilePath string
|
||||
profilePath string
|
||||
expectedContent string
|
||||
}{
|
||||
{
|
||||
"basic wrapper",
|
||||
"/usr/lib/alr/firejailed/_usr_bin_test",
|
||||
"/usr/lib/alr/firejailed/_usr_bin_test.profile",
|
||||
"#!/bin/bash\nexec firejail --profile=\"/usr/lib/alr/firejailed/_usr_bin_test.profile\" \"/usr/lib/alr/firejailed/_usr_bin_test\" \"$@\"\n",
|
||||
},
|
||||
{
|
||||
"path with spaces",
|
||||
"/usr/lib/alr/firejailed/_usr_bin_my_app",
|
||||
"/usr/lib/alr/firejailed/_usr_bin_my_app.profile",
|
||||
"#!/bin/bash\nexec firejail --profile=\"/usr/lib/alr/firejailed/_usr_bin_my_app.profile\" \"/usr/lib/alr/firejailed/_usr_bin_my_app\" \"$@\"\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
scriptPath := filepath.Join(tmpDir, "wrapper.sh")
|
||||
|
||||
err := createWrapperScript(scriptPath, tt.origFilePath, tt.profilePath)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.FileExists(t, scriptPath)
|
||||
|
||||
content, err := os.ReadFile(scriptPath)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expectedContent, string(content))
|
||||
|
||||
// Check file permissions
|
||||
info, err := os.Stat(scriptPath)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, os.FileMode(defaultDirMode), info.Mode())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateFirejailedBinary(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
setupFunc func(string) (*alrsh.Package, *files.Content, types.Directories)
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
"successful creation with default profile",
|
||||
func(tmpDir string) (*alrsh.Package, *files.Content, types.Directories) {
|
||||
pkgDir := filepath.Join(tmpDir, "pkg")
|
||||
scriptDir := filepath.Join(tmpDir, "scripts")
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "test-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho test"), 0o755)
|
||||
|
||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||
os.WriteFile(defaultProfile, []byte("include /etc/firejail/default.profile\nnet none"), 0o644)
|
||||
|
||||
pkg := &alrsh.Package{
|
||||
Name: "test-pkg",
|
||||
FireJailProfiles: alrsh.OverridableFromMap(map[string]map[string]string{
|
||||
"": {"default": "default.profile"},
|
||||
}),
|
||||
}
|
||||
alrsh.ResolvePackage(pkg, []string{""})
|
||||
|
||||
content := &files.Content{
|
||||
Source: srcBinary,
|
||||
Destination: "./usr/bin/test-binary",
|
||||
Type: "file",
|
||||
}
|
||||
|
||||
dirs := types.Directories{PkgDir: pkgDir, ScriptDir: scriptDir}
|
||||
return pkg, content, dirs
|
||||
},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"successful creation with specific profile",
|
||||
func(tmpDir string) (*alrsh.Package, *files.Content, types.Directories) {
|
||||
pkgDir := filepath.Join(tmpDir, "pkg")
|
||||
scriptDir := filepath.Join(tmpDir, "scripts")
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "special-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho special"), 0o755)
|
||||
|
||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||
os.WriteFile(defaultProfile, []byte("include /etc/firejail/default.profile"), 0o644)
|
||||
|
||||
specialProfile := filepath.Join(scriptDir, "special.profile")
|
||||
os.WriteFile(specialProfile, []byte("include /etc/firejail/default.profile\nnet none\nprivate-tmp"), 0o644)
|
||||
|
||||
pkg := &alrsh.Package{
|
||||
Name: "test-pkg",
|
||||
FireJailProfiles: alrsh.OverridableFromMap(map[string]map[string]string{
|
||||
"": {"default": "default.profile", "/usr/bin/special-binary": "special.profile"},
|
||||
}),
|
||||
}
|
||||
alrsh.ResolvePackage(pkg, []string{""})
|
||||
|
||||
content := &files.Content{
|
||||
Source: srcBinary,
|
||||
Destination: "./usr/bin/special-binary",
|
||||
Type: "file",
|
||||
}
|
||||
|
||||
dirs := types.Directories{PkgDir: pkgDir, ScriptDir: scriptDir}
|
||||
return pkg, content, dirs
|
||||
},
|
||||
false,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"missing default profile",
|
||||
func(tmpDir string) (*alrsh.Package, *files.Content, types.Directories) {
|
||||
pkgDir := filepath.Join(tmpDir, "pkg")
|
||||
scriptDir := filepath.Join(tmpDir, "scripts")
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "test-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho test"), 0o755)
|
||||
|
||||
pkg := &alrsh.Package{
|
||||
Name: "test-pkg",
|
||||
FireJailProfiles: alrsh.OverridableFromMap(map[string]map[string]string{"": {}}),
|
||||
}
|
||||
alrsh.ResolvePackage(pkg, []string{""})
|
||||
|
||||
content := &files.Content{Source: srcBinary, Destination: "./usr/bin/test-binary", Type: "file"}
|
||||
dirs := types.Directories{PkgDir: pkgDir, ScriptDir: scriptDir}
|
||||
return pkg, content, dirs
|
||||
},
|
||||
true,
|
||||
"default profile is missing",
|
||||
},
|
||||
{
|
||||
"profile file not found",
|
||||
func(tmpDir string) (*alrsh.Package, *files.Content, types.Directories) {
|
||||
pkgDir := filepath.Join(tmpDir, "pkg")
|
||||
scriptDir := filepath.Join(tmpDir, "scripts")
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "test-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho test"), 0o755)
|
||||
|
||||
pkg := &alrsh.Package{
|
||||
Name: "test-pkg",
|
||||
FireJailProfiles: alrsh.OverridableFromMap(map[string]map[string]string{"": {"default": "nonexistent.profile"}}),
|
||||
}
|
||||
alrsh.ResolvePackage(pkg, []string{""})
|
||||
|
||||
content := &files.Content{Source: srcBinary, Destination: "./usr/bin/test-binary", Type: "file"}
|
||||
dirs := types.Directories{PkgDir: pkgDir, ScriptDir: scriptDir}
|
||||
return pkg, content, dirs
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"invalid destination path",
|
||||
func(tmpDir string) (*alrsh.Package, *files.Content, types.Directories) {
|
||||
pkgDir := filepath.Join(tmpDir, "pkg")
|
||||
scriptDir := filepath.Join(tmpDir, "scripts")
|
||||
os.MkdirAll(pkgDir, 0o755)
|
||||
os.MkdirAll(scriptDir, 0o755)
|
||||
|
||||
srcBinary := filepath.Join(tmpDir, "test-binary")
|
||||
os.WriteFile(srcBinary, []byte("#!/bin/bash\necho test"), 0o755)
|
||||
|
||||
defaultProfile := filepath.Join(scriptDir, "default.profile")
|
||||
os.WriteFile(defaultProfile, []byte("include /etc/firejail/default.profile"), 0o644)
|
||||
|
||||
pkg := &alrsh.Package{Name: "test-pkg", FireJailProfiles: alrsh.OverridableFromMap(map[string]map[string]string{"": {"default": "default.profile"}})}
|
||||
alrsh.ResolvePackage(pkg, []string{""})
|
||||
|
||||
content := &files.Content{Source: srcBinary, Destination: ".", Type: "file"}
|
||||
dirs := types.Directories{PkgDir: pkgDir, ScriptDir: scriptDir}
|
||||
return pkg, content, dirs
|
||||
},
|
||||
true,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
pkg, content, dirs := tt.setupFunc(tmpDir)
|
||||
|
||||
err := createFirejailedDirectory(dirs.PkgDir)
|
||||
assert.NoError(t, err)
|
||||
|
||||
result, err := createFirejailedBinary(pkg, content, dirs)
|
||||
|
||||
if tt.expectError {
|
||||
assert.Error(t, err)
|
||||
if tt.errorMsg != "" {
|
||||
assert.Contains(t, err.Error(), tt.errorMsg)
|
||||
}
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, result, 2)
|
||||
|
||||
binContent := result[0]
|
||||
assert.Contains(t, binContent.Destination, "usr/lib/alr/firejailed/")
|
||||
assert.FileExists(t, binContent.Source)
|
||||
|
||||
profileContent := result[1]
|
||||
assert.Contains(t, profileContent.Destination, "usr/lib/alr/firejailed/")
|
||||
assert.Contains(t, profileContent.Destination, ".profile")
|
||||
assert.FileExists(t, profileContent.Source)
|
||||
|
||||
assert.FileExists(t, content.Source)
|
||||
wrapperBytes, err := os.ReadFile(content.Source)
|
||||
assert.NoError(t, err)
|
||||
wrapper := string(wrapperBytes)
|
||||
assert.Contains(t, wrapper, "#!/bin/bash")
|
||||
assert.Contains(t, wrapper, "firejail --profile=")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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
|
||||
@ -17,7 +17,7 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
)
|
||||
|
||||
func NewInstaller(mgr manager.Manager) *Installer {
|
@ -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
|
||||
@ -17,7 +17,7 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
)
|
||||
|
||||
func NewMainBuilder(
|
@ -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
|
||||
@ -28,7 +28,7 @@ import (
|
||||
"github.com/hashicorp/go-plugin"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
)
|
||||
|
||||
type InstallerPlugin struct {
|
@ -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
|
||||
@ -28,7 +28,7 @@ import (
|
||||
"github.com/hashicorp/go-plugin"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/logger"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
var HandshakeConfig = plugin.HandshakeConfig{
|
||||
@ -50,13 +50,13 @@ type ScriptExecutorRPCServer struct {
|
||||
// ReadScript
|
||||
//
|
||||
|
||||
func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) {
|
||||
var resp *ScriptFile
|
||||
func (s *ScriptExecutorRPC) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error) {
|
||||
var resp *alrsh.ScriptFile
|
||||
err := s.client.Call("Plugin.ReadScript", scriptPath, &resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile) error {
|
||||
func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *alrsh.ScriptFile) error {
|
||||
file, err := s.Impl.ReadScript(context.Background(), scriptPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -72,15 +72,15 @@ func (s *ScriptExecutorRPCServer) ReadScript(scriptPath string, resp *ScriptFile
|
||||
|
||||
type ExecuteFirstPassArgs struct {
|
||||
Input *BuildInput
|
||||
Sf *ScriptFile
|
||||
Sf *alrsh.ScriptFile
|
||||
}
|
||||
|
||||
type ExecuteFirstPassResp struct {
|
||||
BasePkg string
|
||||
VarsOfPackages []*types.BuildVars
|
||||
VarsOfPackages []*alrsh.Package
|
||||
}
|
||||
|
||||
func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) {
|
||||
func (s *ScriptExecutorRPC) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error) {
|
||||
var resp *ExecuteFirstPassResp
|
||||
err := s.client.Call("Plugin.ExecuteFirstPass", &ExecuteFirstPassArgs{
|
||||
Input: input,
|
||||
@ -148,29 +148,29 @@ func (s *ScriptExecutorRPCServer) PrepareDirs(args *PrepareDirsArgs, reply *stru
|
||||
|
||||
type ExecuteSecondPassArgs struct {
|
||||
Input *BuildInput
|
||||
Sf *ScriptFile
|
||||
VarsOfPackages []*types.BuildVars
|
||||
Sf *alrsh.ScriptFile
|
||||
VarsOfPackages []*alrsh.Package
|
||||
RepoDeps []string
|
||||
BuiltNames []string
|
||||
BuiltDeps []*BuiltDep
|
||||
BasePkg string
|
||||
}
|
||||
|
||||
func (s *ScriptExecutorRPC) ExecuteSecondPass(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
sf *ScriptFile,
|
||||
varsOfPackages []*types.BuildVars,
|
||||
sf *alrsh.ScriptFile,
|
||||
varsOfPackages []*alrsh.Package,
|
||||
repoDeps []string,
|
||||
builtNames []string,
|
||||
builtDeps []*BuiltDep,
|
||||
basePkg string,
|
||||
) (*SecondPassResult, error) {
|
||||
var resp *SecondPassResult
|
||||
) ([]*BuiltDep, error) {
|
||||
var resp []*BuiltDep
|
||||
err := s.client.Call("Plugin.ExecuteSecondPass", &ExecuteSecondPassArgs{
|
||||
Input: input,
|
||||
Sf: sf,
|
||||
VarsOfPackages: varsOfPackages,
|
||||
RepoDeps: repoDeps,
|
||||
BuiltNames: builtNames,
|
||||
BuiltDeps: builtDeps,
|
||||
BasePkg: basePkg,
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
@ -179,20 +179,20 @@ func (s *ScriptExecutorRPC) ExecuteSecondPass(
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (s *ScriptExecutorRPCServer) ExecuteSecondPass(args *ExecuteSecondPassArgs, resp *SecondPassResult) error {
|
||||
func (s *ScriptExecutorRPCServer) ExecuteSecondPass(args *ExecuteSecondPassArgs, resp *[]*BuiltDep) error {
|
||||
res, err := s.Impl.ExecuteSecondPass(
|
||||
context.Background(),
|
||||
args.Input,
|
||||
args.Sf,
|
||||
args.VarsOfPackages,
|
||||
args.RepoDeps,
|
||||
args.BuiltNames,
|
||||
args.BuiltDeps,
|
||||
args.BasePkg,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*resp = *res
|
||||
*resp = res
|
||||
return err
|
||||
}
|
||||
|
||||
@ -237,6 +237,7 @@ func GetSafeScriptExecutor() (ScriptExecutor, func(), error) {
|
||||
UnixSocketConfig: &plugin.UnixSocketConfig{
|
||||
Group: "alr",
|
||||
},
|
||||
SyncStderr: os.Stderr,
|
||||
})
|
||||
rpcClient, err := client.Client()
|
||||
if err != nil {
|
@ -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
|
||||
@ -19,7 +19,6 @@ package build
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
@ -36,12 +35,12 @@ import (
|
||||
"mvdan.cc/sh/v3/interp"
|
||||
"mvdan.cc/sh/v3/syntax"
|
||||
|
||||
finddeps "gitea.plemya-x.ru/Plemya-x/ALR/internal/build/find_deps"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
finddeps "gitea.plemya-x.ru/Plemya-x/ALR/pkg/build/find_deps"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
type LocalScriptExecutor struct {
|
||||
@ -54,103 +53,12 @@ func NewLocalScriptExecutor(cfg Config) *LocalScriptExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*ScriptFile, error) {
|
||||
fl, err := readScript(scriptPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ScriptFile{
|
||||
Path: scriptPath,
|
||||
File: fl,
|
||||
}, nil
|
||||
func (e *LocalScriptExecutor) ReadScript(ctx context.Context, scriptPath string) (*alrsh.ScriptFile, error) {
|
||||
return alrsh.ReadFromLocal(scriptPath)
|
||||
}
|
||||
|
||||
func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *ScriptFile) (string, []*types.BuildVars, error) {
|
||||
varsOfPackages := []*types.BuildVars{}
|
||||
|
||||
scriptDir := filepath.Dir(sf.Path)
|
||||
env := createBuildEnvVars(input.info, types.Directories{ScriptDir: scriptDir})
|
||||
|
||||
runner, err := interp.New(
|
||||
interp.Env(expand.ListEnviron(env...)), // Устанавливаем окружение
|
||||
interp.StdIO(os.Stdin, os.Stdout, os.Stderr), // Устанавливаем стандартный ввод-вывод
|
||||
interp.ExecHandler(helpers.Restricted.ExecHandler(handlers.NopExec)), // Ограничиваем выполнение
|
||||
interp.ReadDirHandler2(handlers.RestrictedReadDir(scriptDir)), // Ограничиваем чтение директорий
|
||||
interp.StatHandler(handlers.RestrictedStat(scriptDir)), // Ограничиваем доступ к статистике файлов
|
||||
interp.OpenHandler(handlers.RestrictedOpen(scriptDir)), // Ограничиваем открытие файлов
|
||||
interp.Dir(scriptDir),
|
||||
)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
err = runner.Run(ctx, sf.File) // Запускаем скрипт
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
dec := decoder.New(input.info, runner) // Создаём новый декодер
|
||||
|
||||
type packages struct {
|
||||
BasePkgName string `sh:"basepkg_name"`
|
||||
Names []string `sh:"name"`
|
||||
}
|
||||
|
||||
var pkgs packages
|
||||
err = dec.DecodeVars(&pkgs)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if len(pkgs.Names) == 0 {
|
||||
return "", nil, errors.New("package name is missing")
|
||||
}
|
||||
|
||||
var vars types.BuildVars
|
||||
|
||||
if len(pkgs.Names) == 1 {
|
||||
err = dec.DecodeVars(&vars) // Декодируем переменные
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
varsOfPackages = append(varsOfPackages, &vars)
|
||||
|
||||
return vars.Name, varsOfPackages, nil
|
||||
}
|
||||
|
||||
if len(input.packages) == 0 {
|
||||
return "", nil, errors.New("script has multiple packages but package is not specified")
|
||||
}
|
||||
|
||||
for _, pkgName := range input.packages {
|
||||
var preVars types.BuildVarsPre
|
||||
funcName := fmt.Sprintf("meta_%s", pkgName)
|
||||
meta, ok := dec.GetFuncWithSubshell(funcName)
|
||||
if !ok {
|
||||
return "", nil, errors.New("func is missing")
|
||||
}
|
||||
r, err := meta(ctx)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
d := decoder.New(&distro.OSRelease{}, r)
|
||||
err = d.DecodeVars(&preVars)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
vars := preVars.ToBuildVars()
|
||||
vars.Name = pkgName
|
||||
vars.Base = pkgs.BasePkgName
|
||||
|
||||
varsOfPackages = append(varsOfPackages, &vars)
|
||||
}
|
||||
|
||||
return pkgs.BasePkgName, varsOfPackages, nil
|
||||
}
|
||||
|
||||
type SecondPassResult struct {
|
||||
BuiltPaths []string
|
||||
BuiltNames []string
|
||||
func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *BuildInput, sf *alrsh.ScriptFile) (string, []*alrsh.Package, error) {
|
||||
return sf.ParseBuildVars(ctx, input.info, input.packages)
|
||||
}
|
||||
|
||||
func (e *LocalScriptExecutor) PrepareDirs(
|
||||
@ -178,13 +86,13 @@ func (e *LocalScriptExecutor) PrepareDirs(
|
||||
func (e *LocalScriptExecutor) ExecuteSecondPass(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
sf *ScriptFile,
|
||||
varsOfPackages []*types.BuildVars,
|
||||
sf *alrsh.ScriptFile,
|
||||
varsOfPackages []*alrsh.Package,
|
||||
repoDeps []string,
|
||||
builtNames []string,
|
||||
builtDeps []*BuiltDep,
|
||||
basePkg string,
|
||||
) (*SecondPassResult, error) {
|
||||
dirs, err := getDirs(e.cfg, sf.Path, basePkg)
|
||||
) ([]*BuiltDep, error) {
|
||||
dirs, err := getDirs(e.cfg, sf.Path(), basePkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -193,7 +101,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
|
||||
fakeroot := handlers.FakerootExecHandler(2 * time.Second)
|
||||
runner, err := interp.New(
|
||||
interp.Env(expand.ListEnviron(env...)), // Устанавливаем окружение
|
||||
interp.StdIO(os.Stdin, os.Stdout, os.Stderr), // Устанавливаем стандартный ввод-вывод
|
||||
interp.StdIO(os.Stdin, os.Stderr, os.Stderr), // Устанавливаем стандартный ввод-вывод
|
||||
interp.ExecHandlers(func(next interp.ExecHandlerFunc) interp.ExecHandlerFunc {
|
||||
return helpers.Helpers.ExecHandler(fakeroot)
|
||||
}), // Обрабатываем выполнение через fakeroot
|
||||
@ -202,14 +110,14 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = runner.Run(ctx, sf.File)
|
||||
err = runner.Run(ctx, sf.File())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dec := decoder.New(input.info, runner)
|
||||
|
||||
var builtPaths []string
|
||||
// var builtPaths []string
|
||||
|
||||
err = e.ExecuteFunctions(ctx, dirs, dec)
|
||||
if err != nil {
|
||||
@ -218,7 +126,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
|
||||
|
||||
for _, vars := range varsOfPackages {
|
||||
packageName := ""
|
||||
if vars.Base != "" {
|
||||
if vars.BasePkgName != "" {
|
||||
packageName = vars.Name
|
||||
}
|
||||
|
||||
@ -243,7 +151,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
|
||||
dirs,
|
||||
append(
|
||||
repoDeps,
|
||||
builtNames...,
|
||||
GetBuiltName(builtDeps)...,
|
||||
),
|
||||
funcOut.Contents,
|
||||
)
|
||||
@ -269,14 +177,13 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
builtPaths = append(builtPaths, pkgPath)
|
||||
builtNames = append(builtNames, vars.Name)
|
||||
builtDeps = append(builtDeps, &BuiltDep{
|
||||
Name: vars.Name,
|
||||
Path: pkgPath,
|
||||
})
|
||||
}
|
||||
|
||||
return &SecondPassResult{
|
||||
BuiltPaths: builtPaths,
|
||||
BuiltNames: builtNames,
|
||||
}, nil
|
||||
return builtDeps, nil
|
||||
}
|
||||
|
||||
func buildPkgMetadata(
|
||||
@ -287,24 +194,24 @@ func buildPkgMetadata(
|
||||
PkgFormatProvider
|
||||
RepositoryProvider
|
||||
},
|
||||
vars *types.BuildVars,
|
||||
vars *alrsh.Package,
|
||||
dirs types.Directories,
|
||||
deps []string,
|
||||
preferedContents *[]string,
|
||||
) (*nfpm.Info, error) {
|
||||
pkgInfo := getBasePkgInfo(vars, input)
|
||||
pkgInfo.Description = vars.Description
|
||||
pkgInfo.Description = vars.Description.Resolved()
|
||||
pkgInfo.Platform = "linux"
|
||||
pkgInfo.Homepage = vars.Homepage
|
||||
pkgInfo.Homepage = vars.Homepage.Resolved()
|
||||
pkgInfo.License = strings.Join(vars.Licenses, ", ")
|
||||
pkgInfo.Maintainer = vars.Maintainer
|
||||
pkgInfo.Maintainer = vars.Maintainer.Resolved()
|
||||
pkgInfo.Overridables = nfpm.Overridables{
|
||||
Conflicts: append(vars.Conflicts, vars.Name),
|
||||
Replaces: vars.Replaces,
|
||||
Provides: append(vars.Provides, vars.Name),
|
||||
Depends: deps,
|
||||
}
|
||||
pkgInfo.Section = vars.Group
|
||||
pkgInfo.Section = vars.Group.Resolved()
|
||||
|
||||
pkgFormat := input.PkgFormat()
|
||||
info := input.OSRelease()
|
||||
@ -317,12 +224,12 @@ func buildPkgMetadata(
|
||||
}
|
||||
|
||||
if pkgFormat == "rpm" {
|
||||
pkgInfo.RPM.Group = vars.Group
|
||||
pkgInfo.RPM.Group = vars.Group.Resolved()
|
||||
|
||||
if vars.Summary != "" {
|
||||
pkgInfo.RPM.Summary = vars.Summary
|
||||
if vars.Summary.Resolved() != "" {
|
||||
pkgInfo.RPM.Summary = vars.Summary.Resolved()
|
||||
} else {
|
||||
lines := strings.SplitN(vars.Description, "\n", 2)
|
||||
lines := strings.SplitN(vars.Description.Resolved(), "\n", 2)
|
||||
pkgInfo.RPM.Summary = lines[0]
|
||||
}
|
||||
}
|
||||
@ -341,19 +248,29 @@ func buildPkgMetadata(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkgInfo.Overridables.Contents = contents
|
||||
|
||||
if len(vars.AutoProv) == 1 && decoder.IsTruthy(vars.AutoProv[0]) {
|
||||
f := finddeps.New(info, pkgFormat)
|
||||
err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList)
|
||||
normalizeContents(contents)
|
||||
|
||||
if vars.FireJailed.Resolved() {
|
||||
contents, err = applyFirejailIntegration(vars, dirs, contents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(vars.AutoReq) == 1 && decoder.IsTruthy(vars.AutoReq[0]) {
|
||||
pkgInfo.Overridables.Contents = contents
|
||||
|
||||
if len(vars.AutoProv.Resolved()) == 1 && decoder.IsTruthy(vars.AutoProv.Resolved()[0]) {
|
||||
f := finddeps.New(info, pkgFormat)
|
||||
err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList)
|
||||
err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList.Resolved())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(vars.AutoReq.Resolved()) == 1 && decoder.IsTruthy(vars.AutoReq.Resolved()[0]) {
|
||||
f := finddeps.New(info, pkgFormat)
|
||||
err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList.Resolved())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
@ -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,9 +18,10 @@ package build
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
type ScriptResolver struct {
|
||||
@ -34,16 +35,27 @@ type ScriptInfo struct {
|
||||
|
||||
func (s *ScriptResolver) ResolveScript(
|
||||
ctx context.Context,
|
||||
pkg *db.Package,
|
||||
pkg *alrsh.Package,
|
||||
) *ScriptInfo {
|
||||
var repository, script string
|
||||
|
||||
repodir := s.cfg.GetPaths().RepoDir
|
||||
repository = pkg.Repository
|
||||
if pkg.BasePkgName != "" {
|
||||
script = filepath.Join(repodir, repository, pkg.BasePkgName, "alr.sh")
|
||||
|
||||
// First, we check if there is a root alr.sh in the repository
|
||||
rootScriptPath := filepath.Join(repodir, repository, "alr.sh")
|
||||
if _, err := os.Stat(rootScriptPath); err == nil {
|
||||
// A repository with a single alr.sh at the root
|
||||
script = rootScriptPath
|
||||
} else {
|
||||
script = filepath.Join(repodir, repository, pkg.Name, "alr.sh")
|
||||
// Multi-package repository - we are looking for alr.sh in the subfolder
|
||||
var scriptPath string
|
||||
if pkg.BasePkgName != "" {
|
||||
scriptPath = filepath.Join(repodir, repository, pkg.BasePkgName, "alr.sh")
|
||||
} else {
|
||||
scriptPath = filepath.Join(repodir, repository, pkg.Name, "alr.sh")
|
||||
}
|
||||
script = scriptPath
|
||||
}
|
||||
|
||||
return &ScriptInfo{
|
@ -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
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
type ScriptViewerConfig interface {
|
||||
@ -33,12 +34,12 @@ type ScriptViewer struct {
|
||||
func (s *ScriptViewer) ViewScript(
|
||||
ctx context.Context,
|
||||
input *BuildInput,
|
||||
sf *ScriptFile,
|
||||
a *alrsh.ScriptFile,
|
||||
basePkg string,
|
||||
) error {
|
||||
return cliutils.PromptViewScript(
|
||||
ctx,
|
||||
sf.Path,
|
||||
a.Path(),
|
||||
basePkg,
|
||||
s.config.PagerStyle(),
|
||||
input.opts.Interactive,
|
@ -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
|
||||
@ -33,34 +33,18 @@ import (
|
||||
_ "github.com/goreleaser/nfpm/v2/arch"
|
||||
_ "github.com/goreleaser/nfpm/v2/deb"
|
||||
_ "github.com/goreleaser/nfpm/v2/rpm"
|
||||
"mvdan.cc/sh/v3/syntax"
|
||||
|
||||
"github.com/goreleaser/nfpm/v2"
|
||||
"github.com/goreleaser/nfpm/v2/files"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
"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/types"
|
||||
)
|
||||
|
||||
// Функция readScript анализирует скрипт сборки с использованием встроенной реализации bash
|
||||
func readScript(script string) (*syntax.File, error) {
|
||||
fl, err := os.Open(script) // Открываем файл скрипта
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fl.Close() // Закрываем файл после выполнения
|
||||
|
||||
file, err := syntax.NewParser().Parse(fl, "alr.sh") // Парсим скрипт с помощью синтаксического анализатора
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return file, nil // Возвращаем синтаксическое дерево
|
||||
}
|
||||
|
||||
// Функция prepareDirs подготавливает директории для сборки.
|
||||
func prepareDirs(dirs types.Directories) error {
|
||||
err := os.RemoveAll(dirs.BaseDir) // Удаляем базовую директорию, если она существует
|
||||
@ -76,7 +60,7 @@ func prepareDirs(dirs types.Directories) error {
|
||||
|
||||
// Функция buildContents создает секцию содержимого пакета, которая содержит файлы,
|
||||
// которые будут включены в конечный пакет.
|
||||
func buildContents(vars *types.BuildVars, dirs types.Directories, preferedContents *[]string) ([]*files.Content, error) {
|
||||
func buildContents(vars *alrsh.Package, dirs types.Directories, preferedContents *[]string) ([]*files.Content, error) {
|
||||
contents := []*files.Content{}
|
||||
|
||||
processPath := func(path, trimmed string, prefered bool) error {
|
||||
@ -139,7 +123,7 @@ func buildContents(vars *types.BuildVars, dirs types.Directories, preferedConten
|
||||
},
|
||||
}
|
||||
|
||||
if slices.Contains(vars.Backup, trimmed) {
|
||||
if slices.Contains(vars.Backup.Resolved(), trimmed) {
|
||||
fileContent.Type = "config|noreplace"
|
||||
}
|
||||
|
||||
@ -170,9 +154,15 @@ func buildContents(vars *types.BuildVars, dirs types.Directories, preferedConten
|
||||
return contents, nil
|
||||
}
|
||||
|
||||
func normalizeContents(contents []*files.Content) {
|
||||
for _, content := range contents {
|
||||
content.Destination = filepath.Join("/", content.Destination)
|
||||
}
|
||||
}
|
||||
|
||||
var RegexpALRPackageName = regexp.MustCompile(`^(?P<package>[^+]+)\+alr-(?P<repo>.+)$`)
|
||||
|
||||
func getBasePkgInfo(vars *types.BuildVars, input interface {
|
||||
func getBasePkgInfo(vars *alrsh.Package, input interface {
|
||||
RepositoryProvider
|
||||
OsInfoProvider
|
||||
},
|
||||
@ -228,39 +218,39 @@ func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string
|
||||
}
|
||||
|
||||
// Функция setScripts добавляет скрипты-перехватчики к метаданным пакета.
|
||||
func setScripts(vars *types.BuildVars, info *nfpm.Info, scriptDir string) {
|
||||
if vars.Scripts.PreInstall != "" {
|
||||
info.Scripts.PreInstall = filepath.Join(scriptDir, vars.Scripts.PreInstall)
|
||||
func setScripts(vars *alrsh.Package, info *nfpm.Info, scriptDir string) {
|
||||
if vars.Scripts.Resolved().PreInstall != "" {
|
||||
info.Scripts.PreInstall = filepath.Join(scriptDir, vars.Scripts.Resolved().PreInstall)
|
||||
}
|
||||
|
||||
if vars.Scripts.PostInstall != "" {
|
||||
info.Scripts.PostInstall = filepath.Join(scriptDir, vars.Scripts.PostInstall)
|
||||
if vars.Scripts.Resolved().PostInstall != "" {
|
||||
info.Scripts.PostInstall = filepath.Join(scriptDir, vars.Scripts.Resolved().PostInstall)
|
||||
}
|
||||
|
||||
if vars.Scripts.PreRemove != "" {
|
||||
info.Scripts.PreRemove = filepath.Join(scriptDir, vars.Scripts.PreRemove)
|
||||
if vars.Scripts.Resolved().PreRemove != "" {
|
||||
info.Scripts.PreRemove = filepath.Join(scriptDir, vars.Scripts.Resolved().PreRemove)
|
||||
}
|
||||
|
||||
if vars.Scripts.PostRemove != "" {
|
||||
info.Scripts.PostRemove = filepath.Join(scriptDir, vars.Scripts.PostRemove)
|
||||
if vars.Scripts.Resolved().PostRemove != "" {
|
||||
info.Scripts.PostRemove = filepath.Join(scriptDir, vars.Scripts.Resolved().PostRemove)
|
||||
}
|
||||
|
||||
if vars.Scripts.PreUpgrade != "" {
|
||||
info.ArchLinux.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.PreUpgrade)
|
||||
info.APK.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.PreUpgrade)
|
||||
if vars.Scripts.Resolved().PreUpgrade != "" {
|
||||
info.ArchLinux.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PreUpgrade)
|
||||
info.APK.Scripts.PreUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PreUpgrade)
|
||||
}
|
||||
|
||||
if vars.Scripts.PostUpgrade != "" {
|
||||
info.ArchLinux.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.PostUpgrade)
|
||||
info.APK.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.PostUpgrade)
|
||||
if vars.Scripts.Resolved().PostUpgrade != "" {
|
||||
info.ArchLinux.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PostUpgrade)
|
||||
info.APK.Scripts.PostUpgrade = filepath.Join(scriptDir, vars.Scripts.Resolved().PostUpgrade)
|
||||
}
|
||||
|
||||
if vars.Scripts.PreTrans != "" {
|
||||
info.RPM.Scripts.PreTrans = filepath.Join(scriptDir, vars.Scripts.PreTrans)
|
||||
if vars.Scripts.Resolved().PreTrans != "" {
|
||||
info.RPM.Scripts.PreTrans = filepath.Join(scriptDir, vars.Scripts.Resolved().PreTrans)
|
||||
}
|
||||
|
||||
if vars.Scripts.PostTrans != "" {
|
||||
info.RPM.Scripts.PostTrans = filepath.Join(scriptDir, vars.Scripts.PostTrans)
|
||||
if vars.Scripts.Resolved().PostTrans != "" {
|
||||
info.RPM.Scripts.PostTrans = filepath.Join(scriptDir, vars.Scripts.Resolved().PostTrans)
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,14 +278,14 @@ func packageNames(pkgs []db.Package) []string {
|
||||
*/
|
||||
|
||||
// Функция removeDuplicates убирает любые дубликаты из предоставленного среза.
|
||||
func removeDuplicates(slice []string) []string {
|
||||
seen := map[string]struct{}{}
|
||||
result := []string{}
|
||||
func removeDuplicates[T comparable](slice []T) []T {
|
||||
seen := map[T]struct{}{}
|
||||
result := []T{}
|
||||
|
||||
for _, s := range slice {
|
||||
if _, ok := seen[s]; !ok {
|
||||
seen[s] = struct{}{}
|
||||
result = append(result, s)
|
||||
for _, item := range slice {
|
||||
if _, ok := seen[item]; !ok {
|
||||
seen[item] = struct{}{}
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
@ -26,9 +26,9 @@ import (
|
||||
"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/manager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/repos"
|
||||
"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 {
|
||||
@ -123,8 +123,15 @@ func (b *AppBuilder) withRepos(enablePull, forcePull bool) *AppBuilder {
|
||||
|
||||
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")
|
||||
info := b.deps.Info
|
||||
|
||||
if info == nil {
|
||||
b.WithDistroInfo()
|
||||
info = b.deps.Info
|
||||
}
|
||||
|
||||
if cfg == nil || db == nil || info == nil {
|
||||
b.err = errors.New("config, db and info are required before initializing repos")
|
||||
return b
|
||||
}
|
||||
|
||||
|
@ -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,8 +28,8 @@ import (
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/pager"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
// YesNoPrompt asks the user a yes or no question, using def as the default answer
|
||||
@ -102,8 +102,8 @@ func ShowScript(path, name, style string) error {
|
||||
|
||||
// FlattenPkgs attempts to flatten the a map of slices of packages into a single slice
|
||||
// of packages by prompting the user if multiple packages match.
|
||||
func FlattenPkgs(ctx context.Context, found map[string][]db.Package, verb string, interactive bool) []db.Package {
|
||||
var outPkgs []db.Package
|
||||
func FlattenPkgs(ctx context.Context, found map[string][]alrsh.Package, verb string, interactive bool) []alrsh.Package {
|
||||
var outPkgs []alrsh.Package
|
||||
for _, pkgs := range found {
|
||||
if len(pkgs) > 1 && interactive {
|
||||
choice, err := PkgPrompt(ctx, pkgs, verb, interactive)
|
||||
@ -120,7 +120,7 @@ func FlattenPkgs(ctx context.Context, found map[string][]db.Package, verb string
|
||||
}
|
||||
|
||||
// PkgPrompt asks the user to choose between multiple packages.
|
||||
func PkgPrompt(ctx context.Context, options []db.Package, verb string, interactive bool) (db.Package, error) {
|
||||
func PkgPrompt(ctx context.Context, options []alrsh.Package, verb string, interactive bool) (alrsh.Package, error) {
|
||||
if !interactive {
|
||||
return options[0], nil
|
||||
}
|
||||
@ -138,7 +138,7 @@ func PkgPrompt(ctx context.Context, options []db.Package, verb string, interacti
|
||||
var choice int
|
||||
err := survey.AskOne(prompt, &choice)
|
||||
if err != nil {
|
||||
return db.Package{}, err
|
||||
return alrsh.Package{}, err
|
||||
}
|
||||
|
||||
return options[choice], nil
|
||||
|
@ -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
|
||||
@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@ -61,3 +62,11 @@ func FormatCliExitWithCode(msg string, err error, exitCode int) cli.ExitCoder {
|
||||
}
|
||||
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
|
||||
@ -29,7 +29,7 @@ import (
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/constants"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
|
||||
)
|
||||
|
||||
type ALRConfig struct {
|
||||
@ -39,6 +39,7 @@ type ALRConfig struct {
|
||||
|
||||
var defaultConfig = &types.Config{
|
||||
RootCmd: "sudo",
|
||||
UseRootCmd: true,
|
||||
PagerStyle: "native",
|
||||
IgnorePkgUpdates: []string{},
|
||||
AutoPull: true,
|
||||
@ -142,6 +143,10 @@ 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
|
||||
}
|
||||
|
@ -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,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
|
||||
@ -23,41 +23,18 @@ import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
_ "modernc.org/sqlite"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
|
||||
)
|
||||
|
||||
// CurrentVersion is the current version of the database.
|
||||
// The database is reset if its version doesn't match this.
|
||||
const CurrentVersion = 4
|
||||
const CurrentVersion = 5
|
||||
|
||||
// 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"`
|
||||
Licenses JSON[[]string] `sh:"license" db:"licenses"`
|
||||
Provides JSON[[]string] `sh:"provides" db:"provides"`
|
||||
Conflicts JSON[[]string] `sh:"conflicts" db:"conflicts"`
|
||||
Replaces JSON[[]string] `sh:"replaces" db:"replaces"`
|
||||
Depends JSON[map[string][]string] `db:"depends"`
|
||||
BuildDepends JSON[map[string][]string] `db:"builddepends"`
|
||||
OptDepends JSON[map[string][]string] `db:"optdepends"`
|
||||
Repository string `db:"repository"`
|
||||
}
|
||||
|
||||
type version struct {
|
||||
Version int `db:"version"`
|
||||
type Version struct {
|
||||
Version int `xorm:"'version'"`
|
||||
}
|
||||
|
||||
type Config interface {
|
||||
@ -65,7 +42,7 @@ type Config interface {
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
conn *sqlx.DB
|
||||
engine *xorm.Engine
|
||||
config Config
|
||||
}
|
||||
|
||||
@ -75,181 +52,100 @@ func New(config Config) *Database {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Database) Init(ctx context.Context) error {
|
||||
err := d.Connect(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return d.initDB(ctx)
|
||||
}
|
||||
|
||||
func (d *Database) Connect(ctx context.Context) error {
|
||||
func (d *Database) Connect() error {
|
||||
dsn := d.config.GetPaths().DBPath
|
||||
db, err := sqlx.Open("sqlite", dsn)
|
||||
engine, err := xorm.NewEngine("sqlite", dsn)
|
||||
// engine.SetLogLevel(log.LOG_DEBUG)
|
||||
// engine.ShowSQL(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.conn = db
|
||||
d.engine = engine
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Database) GetConn() *sqlx.DB {
|
||||
return d.conn
|
||||
}
|
||||
|
||||
func (d *Database) initDB(ctx context.Context) error {
|
||||
d.conn = d.conn.Unsafe()
|
||||
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')),
|
||||
licenses TEXT CHECK(licenses = 'null' OR (JSON_VALID(licenses) AND JSON_TYPE(licenses) = 'array')),
|
||||
provides TEXT CHECK(provides = 'null' OR (JSON_VALID(provides) AND JSON_TYPE(provides) = 'array')),
|
||||
conflicts TEXT CHECK(conflicts = 'null' OR (JSON_VALID(conflicts) AND JSON_TYPE(conflicts) = 'array')),
|
||||
replaces TEXT CHECK(replaces = 'null' OR (JSON_VALID(replaces) AND JSON_TYPE(replaces) = 'array')),
|
||||
depends TEXT CHECK(depends = 'null' OR (JSON_VALID(depends) AND JSON_TYPE(depends) = 'object')),
|
||||
builddepends TEXT CHECK(builddepends = 'null' OR (JSON_VALID(builddepends) AND JSON_TYPE(builddepends) = 'object')),
|
||||
optdepends TEXT CHECK(optdepends = 'null' OR (JSON_VALID(optdepends) AND JSON_TYPE(optdepends) = 'object')),
|
||||
UNIQUE(name, repository)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS alr_db_version (
|
||||
version INT NOT NULL
|
||||
);
|
||||
`)
|
||||
if err != nil {
|
||||
func (d *Database) Init(ctx context.Context) error {
|
||||
if err := d.Connect(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.engine.Sync2(new(alrsh.Package), new(Version)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ver, ok := d.GetVersion(ctx)
|
||||
if ok && ver != CurrentVersion {
|
||||
slog.Warn(gotext.Get("Database version mismatch; resetting"), "version", ver, "expected", CurrentVersion)
|
||||
err = d.reset(ctx)
|
||||
if err != nil {
|
||||
if err := d.reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.initDB(ctx)
|
||||
return d.Init(ctx)
|
||||
} else if !ok {
|
||||
slog.Warn(gotext.Get("Database version does not exist. Run alr fix if something isn't working."), "version", ver, "expected", CurrentVersion)
|
||||
return d.addVersion(ctx, CurrentVersion)
|
||||
slog.Warn(gotext.Get("Database version does not exist. Run alr fix if something isn't working."))
|
||||
return d.addVersion(CurrentVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Database) GetVersion(ctx context.Context) (int, bool) {
|
||||
var ver version
|
||||
err := d.conn.GetContext(ctx, &ver, "SELECT * FROM alr_db_version LIMIT 1;")
|
||||
if err != nil {
|
||||
var v Version
|
||||
has, err := d.engine.Get(&v)
|
||||
if err != nil || !has {
|
||||
return 0, false
|
||||
}
|
||||
return ver.Version, true
|
||||
return v.Version, true
|
||||
}
|
||||
|
||||
func (d *Database) addVersion(ctx context.Context, ver int) error {
|
||||
_, err := d.conn.ExecContext(ctx, `INSERT INTO alr_db_version(version) VALUES (?);`, ver)
|
||||
func (d *Database) addVersion(ver int) error {
|
||||
_, err := d.engine.Insert(&Version{Version: ver})
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Database) reset(ctx context.Context) error {
|
||||
_, err := d.conn.ExecContext(ctx, "DROP TABLE IF EXISTS pkgs;")
|
||||
func (d *Database) reset() error {
|
||||
return d.engine.DropTables(new(alrsh.Package), new(Version))
|
||||
}
|
||||
|
||||
func (d *Database) InsertPackage(ctx context.Context, pkg alrsh.Package) error {
|
||||
session := d.engine.Context(ctx)
|
||||
|
||||
affected, err := session.Where("name = ? AND repository = ?", pkg.Name, pkg.Repository).Update(&pkg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.conn.ExecContext(ctx, "DROP TABLE IF EXISTS alr_db_version;")
|
||||
return err
|
||||
|
||||
if affected == 0 {
|
||||
_, err = session.Insert(&pkg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Database) GetPkgs(ctx context.Context, where string, args ...any) (*sqlx.Rows, error) {
|
||||
stream, err := d.conn.QueryxContext(ctx, "SELECT * FROM pkgs WHERE "+where, args...)
|
||||
if err != nil {
|
||||
func (d *Database) GetPkgs(_ context.Context, where string, args ...any) ([]alrsh.Package, error) {
|
||||
var pkgs []alrsh.Package
|
||||
err := d.engine.Where(where, args...).Find(&pkgs)
|
||||
return pkgs, err
|
||||
}
|
||||
|
||||
func (d *Database) GetPkg(where string, args ...any) (*alrsh.Package, error) {
|
||||
var pkg alrsh.Package
|
||||
has, err := d.engine.Where(where, args...).Get(&pkg)
|
||||
if err != nil || !has {
|
||||
return nil, err
|
||||
}
|
||||
return stream, nil
|
||||
return &pkg, nil
|
||||
}
|
||||
|
||||
func (d *Database) GetPkg(ctx context.Context, where string, args ...any) (*Package, error) {
|
||||
out := &Package{}
|
||||
err := d.conn.GetContext(ctx, out, "SELECT * FROM pkgs WHERE "+where+" LIMIT 1", args...)
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (d *Database) DeletePkgs(ctx context.Context, where string, args ...any) error {
|
||||
_, err := d.conn.ExecContext(ctx, "DELETE FROM pkgs WHERE "+where, args...)
|
||||
func (d *Database) DeletePkgs(_ context.Context, where string, args ...any) error {
|
||||
_, err := d.engine.Where(where, args...).Delete(&alrsh.Package{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Database) IsEmpty(ctx context.Context) bool {
|
||||
var count int
|
||||
err := d.conn.GetContext(ctx, &count, "SELECT count(1) FROM pkgs;")
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return count == 0
|
||||
}
|
||||
|
||||
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,
|
||||
licenses,
|
||||
provides,
|
||||
conflicts,
|
||||
replaces,
|
||||
depends,
|
||||
builddepends,
|
||||
optdepends
|
||||
) VALUES (
|
||||
:basepkg_name,
|
||||
:name,
|
||||
:repository,
|
||||
:version,
|
||||
:release,
|
||||
:epoch,
|
||||
:summary,
|
||||
:description,
|
||||
:group_name,
|
||||
:homepage,
|
||||
:maintainer,
|
||||
:architectures,
|
||||
:licenses,
|
||||
:provides,
|
||||
:conflicts,
|
||||
:replaces,
|
||||
:depends,
|
||||
:builddepends,
|
||||
:optdepends
|
||||
);
|
||||
`, pkg)
|
||||
return err
|
||||
func (d *Database) IsEmpty() bool {
|
||||
count, err := d.engine.Count(new(alrsh.Package))
|
||||
return err != nil || count == 0
|
||||
}
|
||||
|
||||
func (d *Database) Close() error {
|
||||
if d.conn != nil {
|
||||
return d.conn.Close()
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return d.engine.Close()
|
||||
}
|
||||
|
@ -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
|
||||
@ -25,10 +25,11 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"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/alrsh"
|
||||
)
|
||||
|
||||
type TestALRConfig struct{}
|
||||
@ -45,35 +46,38 @@ func prepareDb() *db.Database {
|
||||
return database
|
||||
}
|
||||
|
||||
var testPkg = db.Package{
|
||||
var testPkg = alrsh.Package{
|
||||
Name: "test",
|
||||
Version: "0.0.1",
|
||||
Release: 1,
|
||||
Epoch: 2,
|
||||
Description: db.NewJSON(map[string]string{
|
||||
Description: alrsh.OverridableFromMap(map[string]string{
|
||||
"en": "Test package",
|
||||
"ru": "Проверочный пакет",
|
||||
}),
|
||||
Homepage: db.NewJSON(map[string]string{
|
||||
Homepage: alrsh.OverridableFromMap(map[string]string{
|
||||
"en": "https://gitea.plemya-x.ru/xpamych/ALR",
|
||||
}),
|
||||
Maintainer: db.NewJSON(map[string]string{
|
||||
Maintainer: alrsh.OverridableFromMap(map[string]string{
|
||||
"en": "Evgeniy Khramov <xpamych@yandex.ru>",
|
||||
"ru": "Евгений Храмов <xpamych@yandex.ru>",
|
||||
}),
|
||||
Architectures: db.NewJSON([]string{"arm64", "amd64"}),
|
||||
Licenses: db.NewJSON([]string{"GPL-3.0-or-later"}),
|
||||
Provides: db.NewJSON([]string{"test"}),
|
||||
Conflicts: db.NewJSON([]string{"test"}),
|
||||
Replaces: db.NewJSON([]string{"test-old"}),
|
||||
Depends: db.NewJSON(map[string][]string{
|
||||
Architectures: []string{"arm64", "amd64"},
|
||||
Licenses: []string{"GPL-3.0-or-later"},
|
||||
Provides: []string{"test"},
|
||||
Conflicts: []string{"test"},
|
||||
Replaces: []string{"test-old"},
|
||||
Depends: alrsh.OverridableFromMap(map[string][]string{
|
||||
"": {"sudo"},
|
||||
}),
|
||||
BuildDepends: db.NewJSON(map[string][]string{
|
||||
BuildDepends: alrsh.OverridableFromMap(map[string][]string{
|
||||
"": {"golang"},
|
||||
"arch": {"go"},
|
||||
}),
|
||||
Repository: "default",
|
||||
Summary: alrsh.OverridableFromMap(map[string]string{}),
|
||||
Group: alrsh.OverridableFromMap(map[string]string{}),
|
||||
OptDepends: alrsh.OverridableFromMap(map[string][]string{}),
|
||||
}
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
@ -99,15 +103,16 @@ func TestInsertPackage(t *testing.T) {
|
||||
t.Fatalf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
dbPkg := db.Package{}
|
||||
err = sqlx.Get(database.GetConn(), &dbPkg, "SELECT * FROM pkgs WHERE name = 'test' AND repository = 'default'")
|
||||
pkgs, err := database.GetPkgs(ctx, "name = 'test' AND repository = 'default'")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(testPkg, dbPkg) {
|
||||
t.Errorf("Expected test package to be the same as database package")
|
||||
if len(pkgs) != 1 {
|
||||
t.Fatalf("Expected 1 package, got %d", len(pkgs))
|
||||
}
|
||||
|
||||
assert.Equal(t, testPkg, pkgs[0])
|
||||
}
|
||||
|
||||
func TestGetPkgs(t *testing.T) {
|
||||
@ -130,18 +135,12 @@ func TestGetPkgs(t *testing.T) {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
result, err := database.GetPkgs(ctx, "name LIKE 'x%'")
|
||||
pkgs, err := database.GetPkgs(ctx, "name LIKE 'x%'")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
for result.Next() {
|
||||
var dbPkg db.Package
|
||||
err = result.StructScan(&dbPkg)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
for _, dbPkg := range pkgs {
|
||||
if !strings.HasPrefix(dbPkg.Name, "x") {
|
||||
t.Errorf("Expected package name to start with 'x', got %s", dbPkg.Name)
|
||||
}
|
||||
@ -168,7 +167,7 @@ func TestGetPkg(t *testing.T) {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
pkg, err := database.GetPkg(ctx, "name LIKE 'x%' ORDER BY name")
|
||||
pkg, err := database.GetPkg("name LIKE 'x%'")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %s", err)
|
||||
}
|
||||
@ -206,16 +205,6 @@ func TestDeletePkgs(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
var dbPkg db.Package
|
||||
err = database.GetConn().Get(&dbPkg, "SELECT * FROM pkgs WHERE name LIKE 'x%' ORDER BY name LIMIT 1;")
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
if dbPkg.Name != "x2" {
|
||||
t.Errorf("Expected x2 package, got %s", dbPkg.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonArrayContains(t *testing.T) {
|
||||
@ -227,7 +216,7 @@ func TestJsonArrayContains(t *testing.T) {
|
||||
x1.Name = "x1"
|
||||
x2 := testPkg
|
||||
x2.Name = "x2"
|
||||
x2.Provides.Val = append(x2.Provides.Val, "x")
|
||||
x2.Provides = append(x2.Provides, "x")
|
||||
|
||||
err := database.InsertPackage(ctx, x1)
|
||||
if err != nil {
|
||||
@ -239,13 +228,24 @@ func TestJsonArrayContains(t *testing.T) {
|
||||
t.Errorf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
var dbPkg db.Package
|
||||
err = database.GetConn().Get(&dbPkg, "SELECT * FROM pkgs WHERE json_array_contains(provides, 'x');")
|
||||
pkgs, err := database.GetPkgs(ctx, "name = 'x2'")
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got %s", err)
|
||||
}
|
||||
|
||||
if dbPkg.Name != "x2" {
|
||||
t.Errorf("Expected x2 package, got %s", dbPkg.Name)
|
||||
if len(pkgs) != 1 || pkgs[0].Name != "x2" {
|
||||
t.Errorf("Expected x2 package, got %v", pkgs)
|
||||
}
|
||||
|
||||
// Verify the provides field contains 'x'
|
||||
found := false
|
||||
for _, p := range pkgs[0].Provides {
|
||||
if p == "x" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("Expected provides to contain 'x'")
|
||||
}
|
||||
}
|
||||
|
@ -1,80 +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 (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// JSON represents a JSON value in the database
|
||||
type JSON[T any] struct {
|
||||
Val T
|
||||
}
|
||||
|
||||
// NewJSON creates a new database JSON value
|
||||
func NewJSON[T any](v T) JSON[T] {
|
||||
return JSON[T]{Val: v}
|
||||
}
|
||||
|
||||
func (s *JSON[T]) Scan(val any) error {
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch val := val.(type) {
|
||||
case string:
|
||||
err := json.Unmarshal([]byte(val), &s.Val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case sql.NullString:
|
||||
if val.Valid {
|
||||
err := json.Unmarshal([]byte(val.String), &s.Val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
return errors.New("sqlite json types must be strings")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSON[T]) Value() (driver.Value, error) {
|
||||
data, err := json.Marshal(s.Val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func (s JSON[T]) MarshalYAML() (any, error) {
|
||||
return s.Val, nil
|
||||
}
|
||||
|
||||
func (s JSON[T]) String() string {
|
||||
return fmt.Sprint(s.Val)
|
||||
}
|
||||
|
||||
func (s JSON[T]) GoString() string {
|
||||
return fmt.Sprintf("%#v", s.Val)
|
||||
}
|
@ -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
|
||||
|
@ -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,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
|
||||
|
@ -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
|
@ -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
|
||||
@ -17,7 +17,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/>.
|
||||
|
||||
name='{{.Info.Name | tolower}}'
|
||||
name='python3-{{.Info.Name | tolower}}'
|
||||
version='{{.Info.Version}}'
|
||||
release='1'
|
||||
desc='{{.Info.Summary}}'
|
||||
@ -48,3 +48,8 @@ package() {
|
||||
cd "$srcdir/{{.Info.Name}}-${version}"
|
||||
pip install --root="${pkgdir}/" . --no-deps --ignore-installed --disable-pip-version-check
|
||||
}
|
||||
|
||||
files() {
|
||||
printf '"%s" ' ./usr/local/lib/python3.*/site-packages/{{.Info.Name | tolower}}/*
|
||||
printf '"%s" ' ./usr/local/lib/python3.*/site-packages/{{.Info.Name | tolower}}-${version}.dist-info/*
|
||||
}
|
@ -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,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
|
||||
@ -67,7 +67,7 @@ func (a *APTRpm) Sync(opts *Opts) error {
|
||||
|
||||
func (a *APTRpm) Install(opts *Opts, pkgs ...string) error {
|
||||
opts = ensureOpts(opts)
|
||||
cmd := a.getCmd(opts, "apt-get", "install")
|
||||
cmd := a.getCmd(opts, "apt-get", "install", "-o", "APT::Install::Virtual=true")
|
||||
cmd.Args = append(cmd.Args, pkgs...)
|
||||
setCmdEnv(cmd)
|
||||
cmd.Stdout = cmd.Stderr
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user