Compare commits
10 Commits
v0.0.13
...
a785df1ec6
Author | SHA1 | Date | |
---|---|---|---|
a785df1ec6 | |||
131f455eff | |||
1e52d30f4c | |||
40ec0ac6e1 | |||
443e481561 | |||
c892310f69 | |||
750513b119 | |||
ce1836b646 | |||
56b9f3211c | |||
fae63e28f9 |
49
.gitea/workflows/e2e-tests.yaml
Normal file
49
.gitea/workflows/e2e-tests.yaml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# ALR - Any Linux Repository
|
||||||
|
# Copyright (C) 2025 The ALR Authors
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
name: E2E
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
container:
|
||||||
|
image: altlinux.space/maks1ms/actions-container-runner:latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: https://github.com/actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Start Podman service
|
||||||
|
run: nohup podman system service -t 0 unix:/tmp/podman.sock &
|
||||||
|
|
||||||
|
- name: Run E2E tests
|
||||||
|
env:
|
||||||
|
DOCKER_HOST: unix:/tmp/podman.sock
|
||||||
|
IGNORE_ROOT_CHECK: 1
|
||||||
|
run: |
|
||||||
|
make e2e-test
|
49
.gitea/workflows/pre-commit.yaml
Normal file
49
.gitea/workflows/pre-commit.yaml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# ALR - Any Linux Repository
|
||||||
|
# Copyright (C) 2025 The ALR Authors
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
name: Pre-commit
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: https://github.com/actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Set up Python for pre-commit
|
||||||
|
uses: https://github.com/actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
|
|
||||||
|
- name: Install deps
|
||||||
|
run: apt-get update && apt-get install -y gettext bc
|
||||||
|
|
||||||
|
- run: pip install pre-commit
|
||||||
|
- run: pre-commit install
|
||||||
|
- run: pre-commit run --all-files
|
11
Makefile
11
Makefile
@ -1,6 +1,6 @@
|
|||||||
NAME := alr
|
NAME := alr
|
||||||
GIT_VERSION = $(shell git describe --tags )
|
GIT_VERSION = $(shell git describe --tags )
|
||||||
|
IGNORE_ROOT_CHECK ?= 0
|
||||||
DESTDIR ?=
|
DESTDIR ?=
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
BIN := ./$(NAME)
|
BIN := ./$(NAME)
|
||||||
@ -24,8 +24,9 @@ $(BIN):
|
|||||||
go build -ldflags="-X 'gitea.plemya-x.ru/Plemya-x/ALR/internal/config.Version=$(GIT_VERSION)'" -o $@
|
go build -ldflags="-X 'gitea.plemya-x.ru/Plemya-x/ALR/internal/config.Version=$(GIT_VERSION)'" -o $@
|
||||||
|
|
||||||
check-no-root:
|
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 "This target shouldn't run as root" 1>&2; \
|
||||||
|
echo "Set IGNORE_ROOT_CHECK=1 to override" 1>&2; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ uninstall:
|
|||||||
clean clear:
|
clean clear:
|
||||||
rm -f $(BIN)
|
rm -f $(BIN)
|
||||||
|
|
||||||
OLD_FILES=$$(< old-files)
|
OLD_FILES=$(shell cat old-files)
|
||||||
IGNORE_OLD_FILES := $(foreach file,$(shell cat old-files),-ignore $(file))
|
IGNORE_OLD_FILES := $(foreach file,$(shell cat old-files),-ignore $(file))
|
||||||
update-license:
|
update-license:
|
||||||
$(ADD_LICENSE_BIN) -v -f license-header-old-files.tmpl $(OLD_FILES)
|
$(ADD_LICENSE_BIN) -v -f license-header-old-files.tmpl $(OLD_FILES)
|
||||||
@ -76,7 +77,9 @@ test-coverage:
|
|||||||
update-deps-cve:
|
update-deps-cve:
|
||||||
bash scripts/update-deps-cve.sh
|
bash scripts/update-deps-cve.sh
|
||||||
|
|
||||||
e2e-test: clean build
|
prepare-for-e2e-test: clean build
|
||||||
rm -f ./e2e-tests/alr
|
rm -f ./e2e-tests/alr
|
||||||
cp alr e2e-tests
|
cp alr e2e-tests
|
||||||
|
|
||||||
|
e2e-test: prepare-for-e2e-test
|
||||||
go test -tags=e2e ./...
|
go test -tags=e2e ./...
|
@ -12,7 +12,7 @@
|
|||||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||||
<text x="37" y="15" fill="#010101" fill-opacity=".3">ru translate</text>
|
<text x="37" y="15" fill="#010101" fill-opacity=".3">ru translate</text>
|
||||||
<text x="37" y="14">ru translate</text>
|
<text x="37" y="14">ru translate</text>
|
||||||
<text x="100" y="15" fill="#010101" fill-opacity=".3">100.00%</text>
|
<text x="100" y="15" fill="#010101" fill-opacity=".3">96.00%</text>
|
||||||
<text x="100" y="14">100.00%</text>
|
<text x="100" y="14">96.00%</text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 942 B After Width: | Height: | Size: 940 B |
6
build.go
6
build.go
@ -118,7 +118,11 @@ func BuildCmd() *cli.Command {
|
|||||||
return cliutils.FormatCliExit(gotext.Get("Cannot get absolute script path"), err)
|
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{
|
scriptArgs = &build.BuildPackageFromScriptArgs{
|
||||||
Script: script,
|
Script: script,
|
||||||
|
@ -175,6 +175,11 @@ func dockerMultipleRun(t *testing.T, name string, ids []string, f func(t *testin
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func simpleExec(t *testing.T, r e2e.Runnable, cmd string, args ...string) {
|
||||||
|
err := r.Exec(e2e.NewCommand(cmd, args...))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expects []expect.Batcher) {
|
func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expects []expect.Batcher) {
|
||||||
exp, _, err, _ := e2eSpawn(
|
exp, _, err, _ := e2eSpawn(
|
||||||
r,
|
r,
|
||||||
@ -188,3 +193,5 @@ func runTestCommands(t *testing.T, r e2e.Runnable, timeout time.Duration, expect
|
|||||||
)
|
)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REPO_FOR_E2E_TESTS = "https://gitea.plemya-x.ru/Maks1mS/repo-for-tests.git"
|
||||||
|
50
e2e-tests/issue_74_upgradable_test.go
Normal file
50
e2e-tests/issue_74_upgradable_test.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// 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) {
|
||||||
|
simpleExec(t, r, "sudo",
|
||||||
|
"alr",
|
||||||
|
"addrepo",
|
||||||
|
"--name",
|
||||||
|
"alr-repo",
|
||||||
|
"--url",
|
||||||
|
REPO_FOR_E2E_TESTS,
|
||||||
|
)
|
||||||
|
simpleExec(t, r, "sudo", "sh", "-c", "sed -i 's/ref = .*/ref = \"bd26236cd7\"/' /etc/alr/alr.toml")
|
||||||
|
simpleExec(t, r, "alr", "ref")
|
||||||
|
simpleExec(t, r, "sudo", "alr", "in", "bar-pkg")
|
||||||
|
simpleExec(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 0 || exit 1")
|
||||||
|
simpleExec(t, r, "sudo", "sh", "-c", "sed -i 's/ref = .*/ref = \"d9a3541561\"/' /etc/alr/alr.toml")
|
||||||
|
simpleExec(t, r, "sudo", "alr", "ref")
|
||||||
|
simpleExec(t, r, "sh", "-c", "test $(alr list -U | wc -l) -eq 1 || exit 1")
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
59
e2e-tests/issue_81_multiple_packages_test.go
Normal file
59
e2e-tests/issue_81_multiple_packages_test.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// 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"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestE2EIssue81MultiplePackages(t *testing.T) {
|
||||||
|
dockerMultipleRun(
|
||||||
|
t,
|
||||||
|
"issue-81-multiple-packages",
|
||||||
|
COMMON_SYSTEMS,
|
||||||
|
func(t *testing.T, r e2e.Runnable) {
|
||||||
|
err := r.Exec(e2e.NewCommand(
|
||||||
|
"sudo",
|
||||||
|
"alr",
|
||||||
|
"addrepo",
|
||||||
|
"--name",
|
||||||
|
"alr-repo",
|
||||||
|
"--url",
|
||||||
|
REPO_FOR_E2E_TESTS,
|
||||||
|
))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = r.Exec(e2e.NewCommand(
|
||||||
|
"sudo", "alr", "ref",
|
||||||
|
))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = r.Exec(e2e.NewCommand(
|
||||||
|
"sudo", "alr", "in", "first-package-with-dashes",
|
||||||
|
))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = r.Exec(e2e.NewCommand("cat", "/opt/first-package"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
@ -21,6 +21,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
"github.com/urfave/cli/v2"
|
"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)
|
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,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -104,7 +104,7 @@ func Resolve(info *distro.OSRelease, opts *Opts) ([]string, error) {
|
|||||||
out = append(out, opts.Name)
|
out = append(out, opts.Name)
|
||||||
|
|
||||||
for index, item := range out {
|
for index, item := range out {
|
||||||
out[index] = strings.TrimPrefix(strings.ReplaceAll(item, "-", "_"), "_")
|
out[index] = strings.TrimPrefix(item, "_")
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
|
@ -38,23 +38,23 @@ msgstr ""
|
|||||||
msgid "Cannot get absolute script path"
|
msgid "Cannot get absolute script path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build.go:148
|
#: build.go:152
|
||||||
msgid "Package not found"
|
msgid "Package not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build.go:161
|
#: build.go:165
|
||||||
msgid "Nothing to build"
|
msgid "Nothing to build"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build.go:218
|
#: build.go:222
|
||||||
msgid "Error building package"
|
msgid "Error building package"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build.go:225
|
#: build.go:229
|
||||||
msgid "Error moving the package"
|
msgid "Error moving the package"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: build.go:229
|
#: build.go:233
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -278,6 +278,12 @@ msgstr ""
|
|||||||
msgid "OPTIONS"
|
msgid "OPTIONS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: internal/cliutils/utils.go:69
|
||||||
|
msgid ""
|
||||||
|
"This command is deprecated and would be removed in the future, use \"%s\" "
|
||||||
|
"instead!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: internal/db/db.go:137
|
#: internal/db/db.go:137
|
||||||
msgid "Database version mismatch; resetting"
|
msgid "Database version mismatch; resetting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -327,10 +333,30 @@ msgstr ""
|
|||||||
msgid "You need to be root to perform this action"
|
msgid "You need to be root to perform this action"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: list.go:41
|
#: list.go:43
|
||||||
msgid "List ALR repo packages"
|
msgid "List ALR repo packages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: list.go:57
|
||||||
|
msgid "Format output using a Go template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: list.go:89
|
||||||
|
msgid "Error getting packages for upgrade"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: list.go:92
|
||||||
|
msgid "No packages for upgrade"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: list.go:102 list.go:187
|
||||||
|
msgid "Error parsing format template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: list.go:108 list.go:191
|
||||||
|
msgid "Error executing template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: main.go:45
|
#: main.go:45
|
||||||
msgid "Print the current ALR version and exit"
|
msgid "Print the current ALR version and exit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -343,11 +369,11 @@ msgstr ""
|
|||||||
msgid "Enable interactive questions and prompts"
|
msgid "Enable interactive questions and prompts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main.go:145
|
#: main.go:146
|
||||||
msgid "Show help"
|
msgid "Show help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: main.go:149
|
#: main.go:150
|
||||||
msgid "Error while running app"
|
msgid "Error while running app"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -397,82 +423,94 @@ msgstr ""
|
|||||||
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
msgid "AutoReq is not implemented for this package format, so it's skipped"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:237
|
#: pkg/build/script_executor.go:241
|
||||||
msgid "Building package metadata"
|
msgid "Building package metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:368
|
#: pkg/build/script_executor.go:372
|
||||||
msgid "Executing prepare()"
|
msgid "Executing prepare()"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:377
|
#: pkg/build/script_executor.go:381
|
||||||
msgid "Executing build()"
|
msgid "Executing build()"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:406 pkg/build/script_executor.go:426
|
#: pkg/build/script_executor.go:410 pkg/build/script_executor.go:430
|
||||||
msgid "Executing %s()"
|
msgid "Executing %s()"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/repos/pull.go:80
|
#: pkg/repos/pull.go:77
|
||||||
msgid "Pulling repository"
|
msgid "Pulling repository"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/repos/pull.go:116
|
#: pkg/repos/pull.go:113
|
||||||
msgid "Repository up to date"
|
msgid "Repository up to date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/repos/pull.go:207
|
#: pkg/repos/pull.go:204
|
||||||
msgid "Git repository does not appear to be a valid ALR repo"
|
msgid "Git repository does not appear to be a valid ALR repo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: pkg/repos/pull.go:223
|
#: pkg/repos/pull.go:220
|
||||||
msgid ""
|
msgid ""
|
||||||
"ALR repo's minimum ALR version is greater than the current version. Try "
|
"ALR repo's minimum ALR version is greater than the current version. Try "
|
||||||
"updating ALR if something doesn't work."
|
"updating ALR if something doesn't work."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:39
|
#: refresh.go:30
|
||||||
msgid "Add a new repository"
|
msgid "Pull all repositories that have changed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:46
|
#: repo.go:39
|
||||||
msgid "Name of the new repo"
|
msgid "Manage repos"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:50 repo.go:220
|
||||||
|
msgid "Remove an existing repository"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:52
|
#: repo.go:52
|
||||||
msgid "URL of the new repo"
|
msgid "<name>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:75
|
#: repo.go:82
|
||||||
msgid "Repo \"%s\" already exists"
|
msgid "Repo \"%s\" does not exist"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:86 repo.go:159
|
#: repo.go:89
|
||||||
|
msgid "Error removing repo directory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:93 repo.go:160
|
||||||
msgid "Error saving config"
|
msgid "Error saving config"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:112
|
#: repo.go:112
|
||||||
msgid "Remove an existing repository"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: repo.go:119
|
|
||||||
msgid "Name of the repo to be deleted"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: repo.go:148
|
|
||||||
msgid "Repo \"%s\" does not exist"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: repo.go:155
|
|
||||||
msgid "Error removing repo directory"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: repo.go:178
|
|
||||||
msgid "Error removing packages from database"
|
msgid "Error removing packages from database"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:189
|
#: repo.go:123 repo.go:190
|
||||||
msgid "Pull all repositories that have changed"
|
msgid "Add a new repository"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:124
|
||||||
|
msgid "<name> <url>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:149
|
||||||
|
msgid "Repo \"%s\" already exists"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:197
|
||||||
|
msgid "Name of the new repo"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:203
|
||||||
|
msgid "URL of the new repo"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:227
|
||||||
|
msgid "Name of the repo to be deleted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: search.go:40
|
#: search.go:40
|
||||||
@ -495,22 +533,10 @@ msgstr ""
|
|||||||
msgid "Search by provides"
|
msgid "Search by provides"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: search.go:71
|
|
||||||
msgid "Format output using a Go template"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: search.go:130
|
#: search.go:130
|
||||||
msgid "Error while executing search"
|
msgid "Error while executing search"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: search.go:138
|
|
||||||
msgid "Error parsing format template"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: search.go:153
|
|
||||||
msgid "Error executing template"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: upgrade.go:47
|
#: upgrade.go:47
|
||||||
msgid "Upgrade all installed packages"
|
msgid "Upgrade all installed packages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: unnamed project\n"
|
"Project-Id-Version: unnamed project\n"
|
||||||
"PO-Revision-Date: 2025-04-27 18:27+0300\n"
|
"PO-Revision-Date: 2025-05-13 23:24+0300\n"
|
||||||
"Last-Translator: Maxim Slipenko <maks1ms@alt-gnome.ru>\n"
|
"Last-Translator: Maxim Slipenko <maks1ms@alt-gnome.ru>\n"
|
||||||
"Language-Team: Russian\n"
|
"Language-Team: Russian\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@ -45,23 +45,23 @@ msgstr "Ошибка при получении рабочего каталога
|
|||||||
msgid "Cannot get absolute script path"
|
msgid "Cannot get absolute script path"
|
||||||
msgstr "Невозможно получить абсолютный путь к скрипту"
|
msgstr "Невозможно получить абсолютный путь к скрипту"
|
||||||
|
|
||||||
#: build.go:148
|
#: build.go:152
|
||||||
msgid "Package not found"
|
msgid "Package not found"
|
||||||
msgstr "Пакет не найден"
|
msgstr "Пакет не найден"
|
||||||
|
|
||||||
#: build.go:161
|
#: build.go:165
|
||||||
msgid "Nothing to build"
|
msgid "Nothing to build"
|
||||||
msgstr "Нечего собирать"
|
msgstr "Нечего собирать"
|
||||||
|
|
||||||
#: build.go:218
|
#: build.go:222
|
||||||
msgid "Error building package"
|
msgid "Error building package"
|
||||||
msgstr "Ошибка при сборке пакета"
|
msgstr "Ошибка при сборке пакета"
|
||||||
|
|
||||||
#: build.go:225
|
#: build.go:229
|
||||||
msgid "Error moving the package"
|
msgid "Error moving the package"
|
||||||
msgstr "Ошибка при перемещении пакета"
|
msgstr "Ошибка при перемещении пакета"
|
||||||
|
|
||||||
#: build.go:229
|
#: build.go:233
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr "Сделано"
|
msgstr "Сделано"
|
||||||
|
|
||||||
@ -285,6 +285,12 @@ msgstr "КАТЕГОРИЯ"
|
|||||||
msgid "OPTIONS"
|
msgid "OPTIONS"
|
||||||
msgstr "ПАРАМЕТРЫ"
|
msgstr "ПАРАМЕТРЫ"
|
||||||
|
|
||||||
|
#: internal/cliutils/utils.go:69
|
||||||
|
msgid ""
|
||||||
|
"This command is deprecated and would be removed in the future, use \"%s\" "
|
||||||
|
"instead!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: internal/db/db.go:137
|
#: internal/db/db.go:137
|
||||||
msgid "Database version mismatch; resetting"
|
msgid "Database version mismatch; resetting"
|
||||||
msgstr "Несоответствие версий базы данных; сброс настроек"
|
msgstr "Несоответствие версий базы данных; сброс настроек"
|
||||||
@ -335,10 +341,30 @@ msgstr "Вы должны быть членом %s чтобы выполнить
|
|||||||
msgid "You need to be root to perform this action"
|
msgid "You need to be root to perform this action"
|
||||||
msgstr "Вы должны быть root чтобы выполнить это"
|
msgstr "Вы должны быть root чтобы выполнить это"
|
||||||
|
|
||||||
#: list.go:41
|
#: list.go:43
|
||||||
msgid "List ALR repo packages"
|
msgid "List ALR repo packages"
|
||||||
msgstr "Список пакетов репозитория ALR"
|
msgstr "Список пакетов репозитория ALR"
|
||||||
|
|
||||||
|
#: list.go:57
|
||||||
|
msgid "Format output using a Go template"
|
||||||
|
msgstr "Формат выходных данных с использованием шаблона Go"
|
||||||
|
|
||||||
|
#: list.go:89
|
||||||
|
msgid "Error getting packages for upgrade"
|
||||||
|
msgstr "Ошибка при получении пакетов для обновления"
|
||||||
|
|
||||||
|
#: list.go:92
|
||||||
|
msgid "No packages for upgrade"
|
||||||
|
msgstr "Нет пакетов к обновлению"
|
||||||
|
|
||||||
|
#: list.go:102 list.go:187
|
||||||
|
msgid "Error parsing format template"
|
||||||
|
msgstr "Ошибка при разборе шаблона"
|
||||||
|
|
||||||
|
#: list.go:108 list.go:191
|
||||||
|
msgid "Error executing template"
|
||||||
|
msgstr "Ошибка при выполнении шаблона"
|
||||||
|
|
||||||
#: main.go:45
|
#: main.go:45
|
||||||
msgid "Print the current ALR version and exit"
|
msgid "Print the current ALR version and exit"
|
||||||
msgstr "Показать текущую версию ALR и выйти"
|
msgstr "Показать текущую версию ALR и выйти"
|
||||||
@ -351,11 +377,11 @@ msgstr "Аргументы, которые будут переданы мене
|
|||||||
msgid "Enable interactive questions and prompts"
|
msgid "Enable interactive questions and prompts"
|
||||||
msgstr "Включение интерактивных вопросов и запросов"
|
msgstr "Включение интерактивных вопросов и запросов"
|
||||||
|
|
||||||
#: main.go:145
|
#: main.go:146
|
||||||
msgid "Show help"
|
msgid "Show help"
|
||||||
msgstr "Показать справку"
|
msgstr "Показать справку"
|
||||||
|
|
||||||
#: main.go:149
|
#: main.go:150
|
||||||
msgid "Error while running app"
|
msgid "Error while running app"
|
||||||
msgstr "Ошибка при запуске приложения"
|
msgstr "Ошибка при запуске приложения"
|
||||||
|
|
||||||
@ -409,35 +435,35 @@ msgid "AutoReq is not implemented for this package format, so it's skipped"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
|
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:237
|
#: pkg/build/script_executor.go:241
|
||||||
msgid "Building package metadata"
|
msgid "Building package metadata"
|
||||||
msgstr "Сборка метаданных пакета"
|
msgstr "Сборка метаданных пакета"
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:368
|
#: pkg/build/script_executor.go:372
|
||||||
msgid "Executing prepare()"
|
msgid "Executing prepare()"
|
||||||
msgstr "Выполнение prepare()"
|
msgstr "Выполнение prepare()"
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:377
|
#: pkg/build/script_executor.go:381
|
||||||
msgid "Executing build()"
|
msgid "Executing build()"
|
||||||
msgstr "Выполнение build()"
|
msgstr "Выполнение build()"
|
||||||
|
|
||||||
#: pkg/build/script_executor.go:406 pkg/build/script_executor.go:426
|
#: pkg/build/script_executor.go:410 pkg/build/script_executor.go:430
|
||||||
msgid "Executing %s()"
|
msgid "Executing %s()"
|
||||||
msgstr "Выполнение %s()"
|
msgstr "Выполнение %s()"
|
||||||
|
|
||||||
#: pkg/repos/pull.go:80
|
#: pkg/repos/pull.go:77
|
||||||
msgid "Pulling repository"
|
msgid "Pulling repository"
|
||||||
msgstr "Скачивание репозитория"
|
msgstr "Скачивание репозитория"
|
||||||
|
|
||||||
#: pkg/repos/pull.go:116
|
#: pkg/repos/pull.go:113
|
||||||
msgid "Repository up to date"
|
msgid "Repository up to date"
|
||||||
msgstr "Репозиторий уже обновлён"
|
msgstr "Репозиторий уже обновлён"
|
||||||
|
|
||||||
#: pkg/repos/pull.go:207
|
#: pkg/repos/pull.go:204
|
||||||
msgid "Git repository does not appear to be a valid ALR repo"
|
msgid "Git repository does not appear to be a valid ALR repo"
|
||||||
msgstr "Репозиторий Git не поддерживается репозиторием ALR"
|
msgstr "Репозиторий Git не поддерживается репозиторием ALR"
|
||||||
|
|
||||||
#: pkg/repos/pull.go:223
|
#: pkg/repos/pull.go:220
|
||||||
msgid ""
|
msgid ""
|
||||||
"ALR repo's minimum ALR version is greater than the current version. Try "
|
"ALR repo's minimum ALR version is greater than the current version. Try "
|
||||||
"updating ALR if something doesn't work."
|
"updating ALR if something doesn't work."
|
||||||
@ -445,49 +471,61 @@ msgstr ""
|
|||||||
"Минимальная версия ALR для ALR-репозитория выше текущей версии. Попробуйте "
|
"Минимальная версия ALR для ALR-репозитория выше текущей версии. Попробуйте "
|
||||||
"обновить ALR, если что-то не работает."
|
"обновить ALR, если что-то не работает."
|
||||||
|
|
||||||
#: repo.go:39
|
#: refresh.go:30
|
||||||
msgid "Add a new repository"
|
msgid "Pull all repositories that have changed"
|
||||||
msgstr "Добавить новый репозиторий"
|
msgstr "Скачать все изменённые репозитории"
|
||||||
|
|
||||||
#: repo.go:46
|
#: repo.go:39
|
||||||
msgid "Name of the new repo"
|
msgid "Manage repos"
|
||||||
msgstr "Название нового репозитория"
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:50 repo.go:220
|
||||||
|
msgid "Remove an existing repository"
|
||||||
|
msgstr "Удалить существующий репозиторий"
|
||||||
|
|
||||||
#: repo.go:52
|
#: repo.go:52
|
||||||
msgid "URL of the new repo"
|
msgid "<name>"
|
||||||
msgstr "URL-адрес нового репозитория"
|
msgstr ""
|
||||||
|
|
||||||
#: repo.go:75
|
#: repo.go:82
|
||||||
msgid "Repo \"%s\" already exists"
|
msgid "Repo \"%s\" does not exist"
|
||||||
msgstr "Репозиторий \"%s\" уже существует"
|
msgstr "Репозитория \"%s\" не существует"
|
||||||
|
|
||||||
#: repo.go:86 repo.go:159
|
#: repo.go:89
|
||||||
|
msgid "Error removing repo directory"
|
||||||
|
msgstr "Ошибка при удалении каталога репозитория"
|
||||||
|
|
||||||
|
#: repo.go:93 repo.go:160
|
||||||
msgid "Error saving config"
|
msgid "Error saving config"
|
||||||
msgstr "Ошибка при сохранении конфигурации"
|
msgstr "Ошибка при сохранении конфигурации"
|
||||||
|
|
||||||
#: repo.go:112
|
#: repo.go:112
|
||||||
msgid "Remove an existing repository"
|
|
||||||
msgstr "Удалить существующий репозиторий"
|
|
||||||
|
|
||||||
#: repo.go:119
|
|
||||||
msgid "Name of the repo to be deleted"
|
|
||||||
msgstr "Название репозитория удалён"
|
|
||||||
|
|
||||||
#: repo.go:148
|
|
||||||
msgid "Repo \"%s\" does not exist"
|
|
||||||
msgstr "Репозитория \"%s\" не существует"
|
|
||||||
|
|
||||||
#: repo.go:155
|
|
||||||
msgid "Error removing repo directory"
|
|
||||||
msgstr "Ошибка при удалении каталога репозитория"
|
|
||||||
|
|
||||||
#: repo.go:178
|
|
||||||
msgid "Error removing packages from database"
|
msgid "Error removing packages from database"
|
||||||
msgstr "Ошибка при удалении пакетов из базы данных"
|
msgstr "Ошибка при удалении пакетов из базы данных"
|
||||||
|
|
||||||
#: repo.go:189
|
#: repo.go:123 repo.go:190
|
||||||
msgid "Pull all repositories that have changed"
|
msgid "Add a new repository"
|
||||||
msgstr "Скачать все изменённые репозитории"
|
msgstr "Добавить новый репозиторий"
|
||||||
|
|
||||||
|
#: repo.go:124
|
||||||
|
msgid "<name> <url>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: repo.go:149
|
||||||
|
msgid "Repo \"%s\" already exists"
|
||||||
|
msgstr "Репозиторий \"%s\" уже существует"
|
||||||
|
|
||||||
|
#: repo.go:197
|
||||||
|
msgid "Name of the new repo"
|
||||||
|
msgstr "Название нового репозитория"
|
||||||
|
|
||||||
|
#: repo.go:203
|
||||||
|
msgid "URL of the new repo"
|
||||||
|
msgstr "URL-адрес нового репозитория"
|
||||||
|
|
||||||
|
#: repo.go:227
|
||||||
|
msgid "Name of the repo to be deleted"
|
||||||
|
msgstr "Название репозитория удалён"
|
||||||
|
|
||||||
#: search.go:40
|
#: search.go:40
|
||||||
msgid "Search packages"
|
msgid "Search packages"
|
||||||
@ -509,22 +547,10 @@ msgstr "Искать по репозиторию"
|
|||||||
msgid "Search by provides"
|
msgid "Search by provides"
|
||||||
msgstr "Иcкать по provides"
|
msgstr "Иcкать по provides"
|
||||||
|
|
||||||
#: search.go:71
|
|
||||||
msgid "Format output using a Go template"
|
|
||||||
msgstr "Формат выходных данных с использованием шаблона Go"
|
|
||||||
|
|
||||||
#: search.go:130
|
#: search.go:130
|
||||||
msgid "Error while executing search"
|
msgid "Error while executing search"
|
||||||
msgstr "Ошибка при выполнении поиска"
|
msgstr "Ошибка при выполнении поиска"
|
||||||
|
|
||||||
#: search.go:138
|
|
||||||
msgid "Error parsing format template"
|
|
||||||
msgstr "Ошибка при разборе шаблона"
|
|
||||||
|
|
||||||
#: search.go:153
|
|
||||||
msgid "Error executing template"
|
|
||||||
msgstr "Ошибка при выполнении шаблона"
|
|
||||||
|
|
||||||
#: upgrade.go:47
|
#: upgrade.go:47
|
||||||
msgid "Upgrade all installed packages"
|
msgid "Upgrade all installed packages"
|
||||||
msgstr "Обновить все установленные пакеты"
|
msgstr "Обновить все установленные пакеты"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
ALR - Any Linux Repository
|
ALR - Any Linux Repository
|
||||||
Copyright (C) {{ .Year }} Евгений Храмов
|
Copyright (C) {{ .Year }} The ALR Authors
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
72
list.go
72
list.go
@ -22,10 +22,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"slices"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"github.com/leonelquinteros/gotext"
|
"github.com/leonelquinteros/gotext"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
|
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
|
||||||
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||||
@ -45,6 +47,15 @@ func ListCmd() *cli.Command {
|
|||||||
Name: "installed",
|
Name: "installed",
|
||||||
Aliases: []string{"I"},
|
Aliases: []string{"I"},
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "upgradable",
|
||||||
|
Aliases: []string{"U"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "format",
|
||||||
|
Aliases: []string{"f"},
|
||||||
|
Usage: gotext.Get("Format output using a Go template"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
||||||
@ -57,8 +68,10 @@ func ListCmd() *cli.Command {
|
|||||||
New(ctx).
|
New(ctx).
|
||||||
WithConfig().
|
WithConfig().
|
||||||
WithDB().
|
WithDB().
|
||||||
|
WithManager().
|
||||||
// autoPull only
|
// autoPull only
|
||||||
WithRepos().
|
WithRepos().
|
||||||
|
WithDistroInfo().
|
||||||
Build()
|
Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -67,6 +80,39 @@ func ListCmd() *cli.Command {
|
|||||||
|
|
||||||
cfg := deps.Cfg
|
cfg := deps.Cfg
|
||||||
db := deps.DB
|
db := deps.DB
|
||||||
|
mgr := deps.Manager
|
||||||
|
info := deps.Info
|
||||||
|
|
||||||
|
if c.Bool("upgradable") {
|
||||||
|
updates, err := checkForUpdates(ctx, mgr, db, info)
|
||||||
|
if err != nil {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Error getting packages for upgrade"), err)
|
||||||
|
}
|
||||||
|
if len(updates) == 0 {
|
||||||
|
slog.Info(gotext.Get("No packages for upgrade"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
format := c.String("format")
|
||||||
|
if format == "" {
|
||||||
|
format = "{{.Package.Repository}}/{{.Package.Name}} {{.FromVersion}} -> {{.ToVersion}}\n"
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("format").Parse(format)
|
||||||
|
if err != nil {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Error parsing format template"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, updateInfo := range updates {
|
||||||
|
err = tmpl.Execute(os.Stdout, updateInfo)
|
||||||
|
if err != nil {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: refactor code below
|
||||||
|
|
||||||
where := "true"
|
where := "true"
|
||||||
args := []any(nil)
|
args := []any(nil)
|
||||||
@ -115,17 +161,35 @@ func ListCmd() *cli.Command {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
version := pkg.Version
|
type packageInfo struct {
|
||||||
|
Package *database.Package
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgInfo := &packageInfo{}
|
||||||
|
pkgInfo.Package = &pkg
|
||||||
|
pkgInfo.Version = pkg.Version
|
||||||
if c.Bool("installed") {
|
if c.Bool("installed") {
|
||||||
instVersion, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)]
|
instVersion, ok := installedAlrPackages[fmt.Sprintf("%s/%s", pkg.Repository, pkg.Name)]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
version = instVersion
|
pkgInfo.Version = instVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%s/%s %s\n", pkg.Repository, pkg.Name, version)
|
format := c.String("format")
|
||||||
|
if format == "" {
|
||||||
|
format = "{{.Package.Repository}}/{{.Package.Name}} {{.Version}}\n"
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("format").Parse(format)
|
||||||
|
if err != nil {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Error parsing format template"), err)
|
||||||
|
}
|
||||||
|
err = tmpl.Execute(os.Stdout, pkgInfo)
|
||||||
|
if err != nil {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
5
main.go
5
main.go
@ -74,14 +74,15 @@ func GetApp() *cli.App {
|
|||||||
InfoCmd(),
|
InfoCmd(),
|
||||||
ListCmd(),
|
ListCmd(),
|
||||||
BuildCmd(),
|
BuildCmd(),
|
||||||
AddRepoCmd(),
|
LegacyAddRepoCmd(),
|
||||||
RemoveRepoCmd(),
|
LegacyRemoveRepoCmd(),
|
||||||
RefreshCmd(),
|
RefreshCmd(),
|
||||||
FixCmd(),
|
FixCmd(),
|
||||||
GenCmd(),
|
GenCmd(),
|
||||||
HelperCmd(),
|
HelperCmd(),
|
||||||
VersionCmd(),
|
VersionCmd(),
|
||||||
SearchCmd(),
|
SearchCmd(),
|
||||||
|
RepoCmd(),
|
||||||
// Internal commands
|
// Internal commands
|
||||||
InternalBuildCmd(),
|
InternalBuildCmd(),
|
||||||
InternalInstallCmd(),
|
InternalInstallCmd(),
|
||||||
|
@ -118,16 +118,20 @@ func (e *LocalScriptExecutor) ExecuteFirstPass(ctx context.Context, input *Build
|
|||||||
return vars.Name, varsOfPackages, nil
|
return vars.Name, varsOfPackages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(input.packages) == 0 {
|
var pkgNames []string
|
||||||
return "", nil, errors.New("script has multiple packages but package is not specified")
|
|
||||||
|
if len(input.packages) != 0 {
|
||||||
|
pkgNames = input.packages
|
||||||
|
} else {
|
||||||
|
pkgNames = pkgs.Names
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pkgName := range input.packages {
|
for _, pkgName := range pkgNames {
|
||||||
var preVars types.BuildVarsPre
|
var preVars types.BuildVarsPre
|
||||||
funcName := fmt.Sprintf("meta_%s", pkgName)
|
funcName := fmt.Sprintf("meta_%s", pkgName)
|
||||||
meta, ok := dec.GetFuncWithSubshell(funcName)
|
meta, ok := dec.GetFuncWithSubshell(funcName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", nil, errors.New("func is missing")
|
return "", nil, fmt.Errorf("func %s is missing", funcName)
|
||||||
}
|
}
|
||||||
r, err := meta(ctx)
|
r, err := meta(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
38
pkg/parser/parser.go
Normal file
38
pkg/parser/parser.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/>.
|
||||||
|
|
||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PackageNames struct {
|
||||||
|
BasePkgName string `sh:"basepkg_name"`
|
||||||
|
Names []string `sh:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseNames(dec *decoder.Decoder) (*PackageNames, error) {
|
||||||
|
var pkgs PackageNames
|
||||||
|
err := dec.DecodeVars(&pkgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("fail parse names: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pkgs, nil
|
||||||
|
}
|
@ -43,11 +43,8 @@ import (
|
|||||||
"mvdan.cc/sh/v3/syntax"
|
"mvdan.cc/sh/v3/syntax"
|
||||||
|
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
|
"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/shutils/decoder"
|
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers"
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers"
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type actionType uint8
|
type actionType uint8
|
||||||
@ -231,79 +228,19 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
|
|||||||
func (rs *Repos) updatePkg(ctx context.Context, repo types.Repo, runner *interp.Runner, scriptFl io.ReadCloser) error {
|
func (rs *Repos) updatePkg(ctx context.Context, repo types.Repo, runner *interp.Runner, scriptFl io.ReadCloser) error {
|
||||||
parser := syntax.NewParser()
|
parser := syntax.NewParser()
|
||||||
|
|
||||||
defer scriptFl.Close()
|
pkgs, err := parseScript(ctx, repo, parser, runner, scriptFl)
|
||||||
fl, err := parser.Parse(scriptFl, "alr.sh")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.Reset()
|
for _, pkg := range pkgs {
|
||||||
err = runner.Run(ctx, fl)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type packages struct {
|
|
||||||
BasePkgName string `sh:"basepkg_name"`
|
|
||||||
Names []string `sh:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var pkgs packages
|
|
||||||
|
|
||||||
d := decoder.New(&distro.OSRelease{}, runner)
|
|
||||||
d.Overrides = false
|
|
||||||
d.LikeDistros = false
|
|
||||||
err = d.DecodeVars(&pkgs)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pkgs.Names) > 1 {
|
|
||||||
if pkgs.BasePkgName == "" {
|
|
||||||
pkgs.BasePkgName = pkgs.Names[0]
|
|
||||||
}
|
|
||||||
for _, pkgName := range pkgs.Names {
|
|
||||||
pkgInfo := PackageInfo{}
|
|
||||||
funcName := fmt.Sprintf("meta_%s", pkgName)
|
|
||||||
runner.Reset()
|
|
||||||
err = runner.Run(ctx, fl)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
meta, ok := d.GetFuncWithSubshell(funcName)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("func is missing")
|
|
||||||
}
|
|
||||||
r, err := meta(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d := decoder.New(&distro.OSRelease{}, r)
|
|
||||||
d.Overrides = false
|
|
||||||
d.LikeDistros = false
|
|
||||||
err = d.DecodeVars(&pkgInfo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
pkg := pkgInfo.ToPackage(repo.Name)
|
|
||||||
resolveOverrides(r, pkg)
|
|
||||||
pkg.Name = pkgName
|
|
||||||
pkg.BasePkgName = pkgs.BasePkgName
|
|
||||||
err = rs.db.InsertPackage(ctx, *pkg)
|
err = rs.db.InsertPackage(ctx, *pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg := EmptyPackage(repo.Name)
|
return nil
|
||||||
err = d.DecodeVars(pkg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
resolveOverrides(runner, pkg)
|
|
||||||
return rs.db.InsertPackage(ctx, *pkg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *Repos) processRepoChangesRunner(repoDir, scriptDir string) (*interp.Runner, error) {
|
func (rs *Repos) processRepoChangesRunner(repoDir, scriptDir string) (*interp.Runner, error) {
|
||||||
@ -399,16 +336,17 @@ func (rs *Repos) processRepoChanges(ctx context.Context, repo types.Repo, r *git
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var pkg db.Package
|
pkgs, err := parseScript(ctx, repo, parser, runner, r)
|
||||||
err = parseScript(ctx, parser, runner, r, &pkg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, pkg := range pkgs {
|
||||||
err = rs.db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name)
|
err = rs.db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case actionUpdate:
|
case actionUpdate:
|
||||||
if filepath.Base(action.File) != "alr.sh" {
|
if filepath.Base(action.File) != "alr.sh" {
|
||||||
action.File = filepath.Join(filepath.Dir(action.File), "alr.sh")
|
action.File = filepath.Join(filepath.Dir(action.File), "alr.sh")
|
||||||
|
@ -18,6 +18,7 @@ package repos
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -35,7 +36,9 @@ import (
|
|||||||
|
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
|
||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
|
||||||
|
"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/distro"
|
||||||
|
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/parser"
|
||||||
)
|
)
|
||||||
|
|
||||||
// isValid makes sure the path of the file being updated is valid.
|
// isValid makes sure the path of the file being updated is valid.
|
||||||
@ -54,23 +57,85 @@ func isValid(from, to diff.File) bool {
|
|||||||
return match
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseScript(ctx context.Context, parser *syntax.Parser, runner *interp.Runner, r io.ReadCloser, pkg *db.Package) error {
|
func parseScript(
|
||||||
defer r.Close()
|
ctx context.Context,
|
||||||
fl, err := parser.Parse(r, "alr.sh")
|
repo types.Repo,
|
||||||
|
syntaxParser *syntax.Parser,
|
||||||
|
runner *interp.Runner,
|
||||||
|
r io.ReadCloser,
|
||||||
|
) ([]*db.Package, error) {
|
||||||
|
fl, err := syntaxParser.Parse(r, "alr.sh")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.Reset()
|
runner.Reset()
|
||||||
err = runner.Run(ctx, fl)
|
err = runner.Run(ctx, fl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
d := decoder.New(&distro.OSRelease{}, runner)
|
d := decoder.New(&distro.OSRelease{}, runner)
|
||||||
d.Overrides = false
|
d.Overrides = false
|
||||||
d.LikeDistros = false
|
d.LikeDistros = false
|
||||||
return d.DecodeVars(pkg)
|
|
||||||
|
pkgNames, err := parser.ParseNames(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed parsing package names: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(pkgNames.Names) == 0 {
|
||||||
|
return nil, errors.New("package name is missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbPkgs []*db.Package
|
||||||
|
|
||||||
|
if len(pkgNames.Names) > 1 {
|
||||||
|
if pkgNames.BasePkgName == "" {
|
||||||
|
pkgNames.BasePkgName = pkgNames.Names[0]
|
||||||
|
}
|
||||||
|
for _, pkgName := range pkgNames.Names {
|
||||||
|
pkgInfo := PackageInfo{}
|
||||||
|
funcName := fmt.Sprintf("meta_%s", pkgName)
|
||||||
|
runner.Reset()
|
||||||
|
err = runner.Run(ctx, fl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
meta, ok := d.GetFuncWithSubshell(funcName)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("func %s is missing", funcName)
|
||||||
|
}
|
||||||
|
r, err := meta(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
d := decoder.New(&distro.OSRelease{}, r)
|
||||||
|
d.Overrides = false
|
||||||
|
d.LikeDistros = false
|
||||||
|
err = d.DecodeVars(&pkgInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pkg := pkgInfo.ToPackage(repo.Name)
|
||||||
|
resolveOverrides(r, pkg)
|
||||||
|
pkg.Name = pkgName
|
||||||
|
pkg.BasePkgName = pkgNames.BasePkgName
|
||||||
|
dbPkgs = append(dbPkgs, pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dbPkgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg := EmptyPackage(repo.Name)
|
||||||
|
err = d.DecodeVars(pkg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resolveOverrides(runner, pkg)
|
||||||
|
dbPkgs = append(dbPkgs, pkg)
|
||||||
|
|
||||||
|
return dbPkgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type PackageInfo struct {
|
type PackageInfo struct {
|
||||||
|
52
refresh.go
Normal file
52
refresh.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// ALR - Any Linux Repository
|
||||||
|
// Copyright (C) 2025 The ALR Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/leonelquinteros/gotext"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
appbuilder "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils/app_builder"
|
||||||
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RefreshCmd() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "refresh",
|
||||||
|
Usage: gotext.Get("Pull all repositories that have changed"),
|
||||||
|
Aliases: []string{"ref"},
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := c.Context
|
||||||
|
|
||||||
|
deps, err := appbuilder.
|
||||||
|
New(ctx).
|
||||||
|
WithConfig().
|
||||||
|
WithDB().
|
||||||
|
WithReposForcePull().
|
||||||
|
Build()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer deps.Defer()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
200
repo.go
200
repo.go
@ -33,96 +33,30 @@ import (
|
|||||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddRepoCmd() *cli.Command {
|
func RepoCmd() *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "addrepo",
|
Name: "repo",
|
||||||
Usage: gotext.Get("Add a new repository"),
|
Usage: gotext.Get("Manage repos"),
|
||||||
Aliases: []string{"ar"},
|
Subcommands: []*cli.Command{
|
||||||
Flags: []cli.Flag{
|
RemoveRepoCmd(),
|
||||||
&cli.StringFlag{
|
AddRepoCmd(),
|
||||||
Name: "name",
|
|
||||||
Aliases: []string{"n"},
|
|
||||||
Required: true,
|
|
||||||
Usage: gotext.Get("Name of the new repo"),
|
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "url",
|
|
||||||
Aliases: []string{"u"},
|
|
||||||
Required: true,
|
|
||||||
Usage: gotext.Get("URL of the new repo"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
|
||||||
name := c.String("name")
|
|
||||||
repoURL := c.String("url")
|
|
||||||
|
|
||||||
ctx := c.Context
|
|
||||||
|
|
||||||
deps, err := appbuilder.
|
|
||||||
New(ctx).
|
|
||||||
WithConfig().
|
|
||||||
Build()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer deps.Defer()
|
|
||||||
|
|
||||||
cfg := deps.Cfg
|
|
||||||
|
|
||||||
reposSlice := cfg.Repos()
|
|
||||||
for _, repo := range reposSlice {
|
|
||||||
if repo.URL == repoURL || repo.Name == name {
|
|
||||||
return cliutils.FormatCliExit(gotext.Get("Repo \"%s\" already exists", repo.Name), nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reposSlice = append(reposSlice, types.Repo{
|
|
||||||
Name: name,
|
|
||||||
URL: repoURL,
|
|
||||||
})
|
|
||||||
cfg.SetRepos(reposSlice)
|
|
||||||
|
|
||||||
err = cfg.SaveUserConfig()
|
|
||||||
if err != nil {
|
|
||||||
return cliutils.FormatCliExit(gotext.Get("Error saving config"), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
deps, err = appbuilder.
|
|
||||||
New(ctx).
|
|
||||||
UseConfig(cfg).
|
|
||||||
WithDB().
|
|
||||||
WithReposForcePull().
|
|
||||||
Build()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer deps.Defer()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveRepoCmd() *cli.Command {
|
func RemoveRepoCmd() *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "removerepo",
|
Name: "remove",
|
||||||
Usage: gotext.Get("Remove an existing repository"),
|
Usage: gotext.Get("Remove an existing repository"),
|
||||||
Aliases: []string{"rr"},
|
Aliases: []string{"rm"},
|
||||||
Flags: []cli.Flag{
|
ArgsUsage: gotext.Get("<name>"),
|
||||||
&cli.StringFlag{
|
|
||||||
Name: "name",
|
|
||||||
Aliases: []string{"n"},
|
|
||||||
Required: true,
|
|
||||||
Usage: gotext.Get("Name of the repo to be deleted"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||||
ctx := c.Context
|
if c.Args().Len() < 1 {
|
||||||
|
return cliutils.FormatCliExit("missing args", nil)
|
||||||
|
}
|
||||||
|
name := c.Args().Get(0)
|
||||||
|
|
||||||
name := c.String("name")
|
ctx := c.Context
|
||||||
|
|
||||||
deps, err := appbuilder.
|
deps, err := appbuilder.
|
||||||
New(ctx).
|
New(ctx).
|
||||||
@ -183,21 +117,56 @@ func RemoveRepoCmd() *cli.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RefreshCmd() *cli.Command {
|
func AddRepoCmd() *cli.Command {
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "refresh",
|
Name: "add",
|
||||||
Usage: gotext.Get("Pull all repositories that have changed"),
|
Usage: gotext.Get("Add a new repository"),
|
||||||
Aliases: []string{"ref"},
|
ArgsUsage: gotext.Get("<name> <url>"),
|
||||||
Action: func(c *cli.Context) error {
|
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||||
if err := utils.ExitIfCantDropCapsToAlrUser(); err != nil {
|
if c.Args().Len() < 2 {
|
||||||
return err
|
return cliutils.FormatCliExit("missing args", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := c.Args().Get(0)
|
||||||
|
repoURL := c.Args().Get(1)
|
||||||
|
|
||||||
ctx := c.Context
|
ctx := c.Context
|
||||||
|
|
||||||
deps, err := appbuilder.
|
deps, err := appbuilder.
|
||||||
New(ctx).
|
New(ctx).
|
||||||
WithConfig().
|
WithConfig().
|
||||||
|
Build()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer deps.Defer()
|
||||||
|
|
||||||
|
cfg := deps.Cfg
|
||||||
|
|
||||||
|
reposSlice := cfg.Repos()
|
||||||
|
for _, repo := range reposSlice {
|
||||||
|
if repo.URL == repoURL || repo.Name == name {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Repo \"%s\" already exists", repo.Name), nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reposSlice = append(reposSlice, types.Repo{
|
||||||
|
Name: name,
|
||||||
|
URL: repoURL,
|
||||||
|
})
|
||||||
|
cfg.SetRepos(reposSlice)
|
||||||
|
|
||||||
|
err = cfg.SaveUserConfig()
|
||||||
|
if err != nil {
|
||||||
|
return cliutils.FormatCliExit(gotext.Get("Error saving config"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := utils.ExitIfCantDropCapsToAlrUserNoPrivs(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
deps, err = appbuilder.
|
||||||
|
New(ctx).
|
||||||
|
UseConfig(cfg).
|
||||||
WithDB().
|
WithDB().
|
||||||
WithReposForcePull().
|
WithReposForcePull().
|
||||||
Build()
|
Build()
|
||||||
@ -205,7 +174,62 @@ func RefreshCmd() *cli.Command {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer deps.Defer()
|
defer deps.Defer()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
|
//
|
||||||
|
// Deprecated: use "alr repo add"
|
||||||
|
func LegacyAddRepoCmd() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Hidden: true,
|
||||||
|
Name: "addrepo",
|
||||||
|
Usage: gotext.Get("Add a new repository"),
|
||||||
|
Aliases: []string{"ar"},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "name",
|
||||||
|
Aliases: []string{"n"},
|
||||||
|
Required: true,
|
||||||
|
Usage: gotext.Get("Name of the new repo"),
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "url",
|
||||||
|
Aliases: []string{"u"},
|
||||||
|
Required: true,
|
||||||
|
Usage: gotext.Get("URL of the new repo"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||||
|
cliutils.WarnLegacyCommand("alr repo add <name> <url>")
|
||||||
|
return c.App.RunContext(c.Context, []string{"", "repo", "add", c.String("name"), c.String("url")})
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
|
//
|
||||||
|
// Deprecated: use "alr repo rm"
|
||||||
|
func LegacyRemoveRepoCmd() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Hidden: true,
|
||||||
|
Name: "removerepo",
|
||||||
|
Usage: gotext.Get("Remove an existing repository"),
|
||||||
|
Aliases: []string{"rr"},
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "name",
|
||||||
|
Aliases: []string{"n"},
|
||||||
|
Required: true,
|
||||||
|
Usage: gotext.Get("Name of the repo to be deleted"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: utils.RootNeededAction(func(c *cli.Context) error {
|
||||||
|
cliutils.WarnLegacyCommand("alr repo remove <name>")
|
||||||
|
return c.App.RunContext(c.Context, []string{"", "repo", "remove", c.String("name")})
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
upgrade.go
32
upgrade.go
@ -116,7 +116,7 @@ func UpgradeCmd() *cli.Command {
|
|||||||
Info: deps.Info,
|
Info: deps.Info,
|
||||||
PkgFormat_: build.GetPkgFormat(deps.Manager),
|
PkgFormat_: build.GetPkgFormat(deps.Manager),
|
||||||
},
|
},
|
||||||
updates,
|
mapUptatesInfoToPackages(updates),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cliutils.FormatCliExit(gotext.Get("Error checking for updates"), err)
|
return cliutils.FormatCliExit(gotext.Get("Error checking for updates"), err)
|
||||||
@ -130,12 +130,27 @@ func UpgradeCmd() *cli.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package {
|
||||||
|
var pkgs []database.Package
|
||||||
|
for _, info := range updates {
|
||||||
|
pkgs = append(pkgs, *info.Package)
|
||||||
|
}
|
||||||
|
return pkgs
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateInfo struct {
|
||||||
|
Package *database.Package
|
||||||
|
|
||||||
|
FromVersion string
|
||||||
|
ToVersion string
|
||||||
|
}
|
||||||
|
|
||||||
func checkForUpdates(
|
func checkForUpdates(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
mgr manager.Manager,
|
mgr manager.Manager,
|
||||||
db *database.Database,
|
db *database.Database,
|
||||||
info *distro.OSRelease,
|
info *distro.OSRelease,
|
||||||
) ([]database.Package, error) {
|
) ([]UpdateInfo, error) {
|
||||||
installed, err := mgr.ListInstalled(nil)
|
installed, err := mgr.ListInstalled(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -145,7 +160,7 @@ func checkForUpdates(
|
|||||||
|
|
||||||
s := search.New(db)
|
s := search.New(db)
|
||||||
|
|
||||||
var out []database.Package
|
var out []UpdateInfo
|
||||||
for _, pkgName := range pkgNames {
|
for _, pkgName := range pkgNames {
|
||||||
matches := build.RegexpALRPackageName.FindStringSubmatch(pkgName)
|
matches := build.RegexpALRPackageName.FindStringSubmatch(pkgName)
|
||||||
if matches != nil {
|
if matches != nil {
|
||||||
@ -179,10 +194,13 @@ func checkForUpdates(
|
|||||||
}
|
}
|
||||||
|
|
||||||
c := vercmp.Compare(repoVer, installed[pkgName])
|
c := vercmp.Compare(repoVer, installed[pkgName])
|
||||||
if c == 0 || c == -1 {
|
|
||||||
continue
|
if c == 1 {
|
||||||
} else if c == 1 {
|
out = append(out, UpdateInfo{
|
||||||
out = append(out, pkg)
|
Package: &pkg,
|
||||||
|
FromVersion: installed[pkgName],
|
||||||
|
ToVersion: repoVer,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user