diff --git a/.gitea/workflows/update-alr-git.yaml b/.gitea/workflows/update-alr-git.yaml
new file mode 100644
index 0000000..b4130c5
--- /dev/null
+++ b/.gitea/workflows/update-alr-git.yaml
@@ -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 .
+
+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.4
+
+ - 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-filed version $NEW_ALR_VERSION
+ alr-spec set-filed 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
diff --git a/assets/coverage-badge.svg b/assets/coverage-badge.svg
index a1f8f90..42e7827 100644
--- a/assets/coverage-badge.svg
+++ b/assets/coverage-badge.svg
@@ -11,7 +11,7 @@
coverage
coverage
- 16.9%
- 16.9%
+ 17.6%
+ 17.6%
diff --git a/build.go b/build.go
index ea5aab3..f0eb43d 100644
--- a/build.go
+++ b/build.go
@@ -32,8 +32,8 @@ import (
"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/types"
)
func BuildCmd() *cli.Command {
diff --git a/e2e-tests/group_and_summary_field_test.go b/e2e-tests/group_and_summary_field_test.go
index ec9fb05..93a198c 100644
--- a/e2e-tests/group_and_summary_field_test.go
+++ b/e2e-tests/group_and_summary_field_test.go
@@ -31,8 +31,8 @@ func TestE2EGroupAndSummaryField(t *testing.T) {
RPM_SYSTEMS,
func(t *testing.T, r e2e.Runnable) {
defaultPrepare(t, r)
- execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Group}}\" | grep ^System/Base$")
- execShouldNoError(t, r, "sh", "-c", "alr search --name test-group-and-summary --format \"{{.Summary}}\" | grep \"^Custom summary$\"")
+ 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$\"")
},
)
}
diff --git a/go.mod b/go.mod
index 007dbec..cab744e 100644
--- a/go.mod
+++ b/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
)
diff --git a/go.sum b/go.sum
index 05dd647..b0d5f39 100644
--- a/go.sum
+++ b/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=
diff --git a/helper.go b/helper.go
index 71b4e6b..89b8fe8 100644
--- a/helper.go
+++ b/helper.go
@@ -32,8 +32,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/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/helpers"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
)
func HelperCmd() *cli.Command {
diff --git a/info.go b/info.go
index f1bb398..5652eb5 100644
--- a/info.go
+++ b/info.go
@@ -30,10 +30,10 @@ 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/distro"
"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"
)
func InfoCmd() *cli.Command {
@@ -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)
}
diff --git a/install.go b/install.go
index 1a58611..5385437 100644
--- a/install.go
+++ b/install.go
@@ -28,10 +28,9 @@ import (
"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/manager"
- "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/types"
)
func InstallCmd() *cli.Command {
@@ -136,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)
}
@@ -190,20 +182,12 @@ 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)
}
diff --git a/internal/build/build.go b/internal/build/build.go
index a76074b..ff7a2d2 100644
--- a/internal/build/build.go
+++ b/internal/build/build.go
@@ -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/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/manager"
- "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/types"
)
type BuildInput struct {
@@ -133,47 +132,6 @@ type RepositoryProvider interface {
// ================================================
-type ScriptFile struct {
- File *syntax.File
- 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
- }
- 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
-}
-
-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
-}
-
type BuiltDep struct {
Name string
Path string
@@ -200,7 +158,7 @@ func GetBuiltName(deps []*BuiltDep) []string {
}
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 {
@@ -215,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,
@@ -229,8 +187,8 @@ type ScriptExecutor interface {
ExecuteSecondPass(
ctx context.Context,
input *BuildInput,
- sf *ScriptFile,
- varsOfPackages []*types.BuildVars,
+ sf *alrsh.ScriptFile,
+ varsOfPackages []*alrsh.Package,
repoDeps []string,
builtDeps []*BuiltDep,
basePkg string,
@@ -238,18 +196,18 @@ type ScriptExecutor interface {
}
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)
}
@@ -327,7 +285,7 @@ func (b *BuildArgs) PkgFormat() string {
type BuildPackageFromDbArgs struct {
BuildArgs
- Package *db.Package
+ Package *alrsh.Package
Packages []string
}
@@ -376,19 +334,19 @@ func (b *Builder) BuildPackage(
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)
}
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 {
@@ -409,6 +367,7 @@ func (b *Builder) BuildPackage(
}
slog.Debug("ViewScript")
+ slog.Debug("", "varsOfPackages", varsOfPackages)
err = b.scriptViewerExecutor.ViewScript(ctx, input, sf, basePkg)
if err != nil {
return nil, err
@@ -432,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)
@@ -523,7 +482,7 @@ func (b *Builder) BuildPackage(
type InstallPkgsArgs struct {
BuildArgs
- AlrPkgs []db.Package
+ AlrPkgs []alrsh.Package
NativePkgs []string
}
@@ -534,7 +493,7 @@ func (b *Builder) InstallALRPackages(
BuildOptsProvider
PkgFormatProvider
},
- alrPkgs []db.Package,
+ alrPkgs []alrsh.Package,
) error {
for _, pkg := range alrPkgs {
res, err := b.BuildPackageFromDb(
@@ -581,7 +540,7 @@ func (b *Builder) BuildALRDeps(
found, notFound, err := b.repos.FindPkgs(ctx, depends) // Поиск зависимостей
if err != nil {
- return nil, nil, err
+ return nil, nil, fmt.Errorf("failed FindPkgs: %w", err)
}
repoDeps = notFound
@@ -593,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)
@@ -628,7 +587,7 @@ func (b *Builder) BuildALRDeps(
},
)
if err != nil {
- return nil, nil, err
+ return nil, nil, fmt.Errorf("failed build package from db: %w", err)
}
buildDeps = append(buildDeps, res...)
diff --git a/internal/build/build_internal_test.need-to-update b/internal/build/build_internal_test.need-to-update
index b649815..c411ed6 100644
--- a/internal/build/build_internal_test.need-to-update
+++ b/internal/build/build_internal_test.need-to-update
@@ -28,8 +28,8 @@ 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/internal/distro"
+ "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/internal/manager"
)
diff --git a/internal/build/cache.go b/internal/build/cache.go
index bd205cd..2453090 100644
--- a/internal/build/cache.go
+++ b/internal/build/cache.go
@@ -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)
diff --git a/internal/build/checker.go b/internal/build/checker.go
index 515f71a..94cdc3f 100644
--- a/internal/build/checker.go
+++ b/internal/build/checker.go
@@ -25,7 +25,7 @@ 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/manager"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
+ "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(
diff --git a/internal/build/dirs.go b/internal/build/dirs.go
index ec29456..13408bb 100644
--- a/internal/build/dirs.go
+++ b/internal/build/dirs.go
@@ -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 {
diff --git a/internal/build/find_deps/alt_linux.go b/internal/build/find_deps/alt_linux.go
index 11954b4..ad2eb81 100644
--- a/internal/build/find_deps/alt_linux.go
+++ b/internal/build/find_deps/alt_linux.go
@@ -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 {
diff --git a/internal/build/find_deps/empty.go b/internal/build/find_deps/empty.go
index 4bf30f1..af0e91e 100644
--- a/internal/build/find_deps/empty.go
+++ b/internal/build/find_deps/empty.go
@@ -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{}
diff --git a/internal/build/find_deps/fedora.go b/internal/build/find_deps/fedora.go
index feabfe0..d562a8d 100644
--- a/internal/build/find_deps/fedora.go
+++ b/internal/build/find_deps/fedora.go
@@ -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{}
diff --git a/internal/build/find_deps/find_deps.go b/internal/build/find_deps/find_deps.go
index 1a858f2..3231b1e 100644
--- a/internal/build/find_deps/find_deps.go
+++ b/internal/build/find_deps/find_deps.go
@@ -21,8 +21,8 @@ import (
"github.com/goreleaser/nfpm/v2"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
- "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 {
diff --git a/internal/build/safe_script_executor.go b/internal/build/safe_script_executor.go
index 974aa69..3342e7b 100644
--- a/internal/build/safe_script_executor.go
+++ b/internal/build/safe_script_executor.go
@@ -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,8 +148,8 @@ 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
BuiltDeps []*BuiltDep
BasePkg string
@@ -158,8 +158,8 @@ type ExecuteSecondPassArgs struct {
func (s *ScriptExecutorRPC) ExecuteSecondPass(
ctx context.Context,
input *BuildInput,
- sf *ScriptFile,
- varsOfPackages []*types.BuildVars,
+ sf *alrsh.ScriptFile,
+ varsOfPackages []*alrsh.Package,
repoDeps []string,
builtDeps []*BuiltDep,
basePkg string,
diff --git a/internal/build/script_executor.go b/internal/build/script_executor.go
index 41a0c2e..c67edfd 100644
--- a/internal/build/script_executor.go
+++ b/internal/build/script_executor.go
@@ -19,7 +19,6 @@ package build
import (
"bytes"
"context"
- "errors"
"fmt"
"log/slog"
"os"
@@ -37,11 +36,11 @@ import (
"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/distro"
"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"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
)
type LocalScriptExecutor struct {
@@ -54,102 +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.Stderr, 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
- }
-
- var pkgNames []string
-
- if len(input.packages) != 0 {
- pkgNames = input.packages
- } else {
- pkgNames = pkgs.Names
- }
-
- for _, pkgName := range pkgNames {
- var preVars types.BuildVarsPre
- funcName := fmt.Sprintf("meta_%s", pkgName)
- meta, ok := dec.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)
- 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
+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(
@@ -177,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,
builtDeps []*BuiltDep,
basePkg string,
) ([]*BuiltDep, error) {
- dirs, err := getDirs(e.cfg, sf.Path, basePkg)
+ dirs, err := getDirs(e.cfg, sf.Path(), basePkg)
if err != nil {
return nil, err
}
@@ -201,7 +110,7 @@ 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
}
@@ -217,7 +126,7 @@ func (e *LocalScriptExecutor) ExecuteSecondPass(
for _, vars := range varsOfPackages {
packageName := ""
- if vars.Base != "" {
+ if vars.BasePkgName != "" {
packageName = vars.Name
}
@@ -285,24 +194,25 @@ 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
+ slog.Warn("vars.Description", "vars.Description", vars.Description, "vars.Description.Resolved", vars.Description.Resolved())
+ 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()
@@ -315,12 +225,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,17 +251,17 @@ func buildPkgMetadata(
}
pkgInfo.Overridables.Contents = contents
- if len(vars.AutoProv) == 1 && decoder.IsTruthy(vars.AutoProv[0]) {
+ if len(vars.AutoProv.Resolved()) == 1 && decoder.IsTruthy(vars.AutoProv.Resolved()[0]) {
f := finddeps.New(info, pkgFormat)
- err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList)
+ err = f.FindProvides(ctx, pkgInfo, dirs, vars.AutoProvSkipList.Resolved())
if err != nil {
return nil, err
}
}
- if len(vars.AutoReq) == 1 && decoder.IsTruthy(vars.AutoReq[0]) {
+ 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)
+ err = f.FindRequires(ctx, pkgInfo, dirs, vars.AutoReqSkipList.Resolved())
if err != nil {
return nil, err
}
diff --git a/internal/build/script_resolver.go b/internal/build/script_resolver.go
index 06edcfb..70bf763 100644
--- a/internal/build/script_resolver.go
+++ b/internal/build/script_resolver.go
@@ -20,7 +20,7 @@ import (
"context"
"path/filepath"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
)
type ScriptResolver struct {
@@ -34,7 +34,7 @@ type ScriptInfo struct {
func (s *ScriptResolver) ResolveScript(
ctx context.Context,
- pkg *db.Package,
+ pkg *alrsh.Package,
) *ScriptInfo {
var repository, script string
diff --git a/internal/build/script_view.go b/internal/build/script_view.go
index 2da9250..e72cdfa 100644
--- a/internal/build/script_view.go
+++ b/internal/build/script_view.go
@@ -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,
diff --git a/internal/build/utils.go b/internal/build/utils.go
index ce54b31..1ef2f9d 100644
--- a/internal/build/utils.go
+++ b/internal/build/utils.go
@@ -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/distro"
"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/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"
}
@@ -172,7 +156,7 @@ func buildContents(vars *types.BuildVars, dirs types.Directories, preferedConten
var RegexpALRPackageName = regexp.MustCompile(`^(?P[^+]+)\+alr-(?P.+)$`)
-func getBasePkgInfo(vars *types.BuildVars, input interface {
+func getBasePkgInfo(vars *alrsh.Package, input interface {
RepositoryProvider
OsInfoProvider
},
@@ -228,39 +212,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)
}
}
diff --git a/internal/cliutils/app_builder/builder.go b/internal/cliutils/app_builder/builder.go
index 6276735..a946a12 100644
--- a/internal/cliutils/app_builder/builder.go
+++ b/internal/cliutils/app_builder/builder.go
@@ -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/distro"
"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"
)
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
}
diff --git a/internal/cliutils/prompt.go b/internal/cliutils/prompt.go
index af04fa0..bc07c39 100644
--- a/internal/cliutils/prompt.go
+++ b/internal/cliutils/prompt.go
@@ -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
diff --git a/internal/cliutils/utils.go b/internal/cliutils/utils.go
index 010d2e0..48c4dc7 100644
--- a/internal/cliutils/utils.go
+++ b/internal/cliutils/utils.go
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"log/slog"
+ "runtime/debug"
"github.com/leonelquinteros/gotext"
"github.com/urfave/cli/v2"
@@ -44,10 +45,12 @@ func HandleExitCoder(err error) {
slog.Error(err.Error())
}
}
+ debug.PrintStack()
cli.OsExiter(exitErr.ExitCode())
return
}
+ debug.PrintStack()
slog.Error(err.Error())
cli.OsExiter(1)
}
diff --git a/internal/config/config.go b/internal/config/config.go
index 64d2ce1..b62ca2d 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -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 {
diff --git a/internal/db/db.go b/internal/db/db.go
index 8c2b8b2..ffb9298 100644
--- a/internal/db/db.go
+++ b/internal/db/db.go
@@ -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()
}
diff --git a/internal/db/db_test.go b/internal/db/db_test.go
index 2761cd8..1962604 100644
--- a/internal/db/db_test.go
+++ b/internal/db/db_test.go
@@ -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 ",
"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'")
}
}
diff --git a/internal/db/json.go b/internal/db/json.go
deleted file mode 100644
index d17a137..0000000
--- a/internal/db/json.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// 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 .
-
-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)
-}
diff --git a/internal/overrides/overrides.go b/internal/overrides/overrides.go
index 5f81bd0..00bdc48 100644
--- a/internal/overrides/overrides.go
+++ b/internal/overrides/overrides.go
@@ -21,7 +21,6 @@ package overrides
import (
"fmt"
- "reflect"
"regexp"
"strings"
@@ -29,8 +28,7 @@ import (
"golang.org/x/text/language"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
)
type Opts struct {
@@ -150,65 +148,6 @@ func (o *Opts) WithLanguageTags(langs []string) *Opts {
return out
}
-// ResolvedPackage is a ALR package after its overrides
-// have been resolved
-type ResolvedPackage struct {
- Name string `sh:"name"`
- Version string `sh:"version"`
- Release int `sh:"release"`
- Epoch uint `sh:"epoch"`
- Group string `db:"group_name"`
- Summary string `db:"summary"`
- Description string `db:"description"`
- Homepage string `db:"homepage"`
- Maintainer string `db:"maintainer"`
- Architectures []string `sh:"architectures"`
- Licenses []string `sh:"license"`
- Provides []string `sh:"provides"`
- Conflicts []string `sh:"conflicts"`
- Replaces []string `sh:"replaces"`
- Depends []string `sh:"deps"`
- BuildDepends []string `sh:"build_deps"`
- OptDepends []string `sh:"opt_deps"`
-}
-
-func ResolvePackage(pkg *db.Package, overrides []string) *ResolvedPackage {
- out := &ResolvedPackage{}
- outVal := reflect.ValueOf(out).Elem()
- pkgVal := reflect.ValueOf(pkg).Elem()
-
- for i := 0; i < outVal.NumField(); i++ {
- fieldVal := outVal.Field(i)
- fieldType := fieldVal.Type()
- pkgFieldVal := pkgVal.FieldByName(outVal.Type().Field(i).Name)
- pkgFieldType := pkgFieldVal.Type()
-
- if strings.HasPrefix(pkgFieldType.String(), "db.JSON") {
- pkgFieldVal = pkgFieldVal.FieldByName("Val")
- pkgFieldType = pkgFieldVal.Type()
- }
-
- if pkgFieldType.AssignableTo(fieldType) {
- fieldVal.Set(pkgFieldVal)
- continue
- }
-
- if pkgFieldVal.Kind() == reflect.Map && pkgFieldType.Elem().AssignableTo(fieldType) {
- for _, override := range overrides {
- overrideVal := pkgFieldVal.MapIndex(reflect.ValueOf(override))
- if !overrideVal.IsValid() {
- continue
- }
-
- fieldVal.Set(overrideVal)
- break
- }
- }
- }
-
- return out
-}
-
func parseLangs(langs []string, tags []language.Tag) ([]string, error) {
out := make([]string, len(tags)+len(langs))
for i, tag := range tags {
diff --git a/internal/overrides/overrides_test.go b/internal/overrides/overrides_test.go
index 5177dac..42d985c 100644
--- a/internal/overrides/overrides_test.go
+++ b/internal/overrides/overrides_test.go
@@ -27,8 +27,8 @@ import (
"github.com/stretchr/testify/assert"
"golang.org/x/text/language"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
)
var info = &distro.OSRelease{
diff --git a/internal/repos/find.go b/internal/repos/find.go
index 5c1856e..957b3e3 100644
--- a/internal/repos/find.go
+++ b/internal/repos/find.go
@@ -22,11 +22,11 @@ package repos
import (
"context"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
)
-func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error) {
- found := map[string][]db.Package{}
+func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]alrsh.Package, []string, error) {
+ found := map[string][]alrsh.Package{}
notFound := []string(nil)
for _, pkgName := range pkgs {
@@ -40,17 +40,10 @@ func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.P
}
added := 0
- for result.Next() {
- var pkg db.Package
- err = result.StructScan(&pkg)
- if err != nil {
- return nil, nil, err
- }
-
+ for _, pkg := range result {
added++
found[pkgName] = append(found[pkgName], pkg)
}
- result.Close()
if added == 0 {
result, err := rs.db.GetPkgs(ctx, "name LIKE ?", pkgName)
@@ -58,18 +51,10 @@ func (rs *Repos) FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.P
return nil, nil, err
}
- for result.Next() {
- var pkg db.Package
- err = result.StructScan(&pkg)
- if err != nil {
- return nil, nil, err
- }
-
+ for _, pkg := range result {
added++
found[pkgName] = append(found[pkgName], pkg)
}
-
- result.Close()
}
if added == 0 {
diff --git a/internal/repos/find_test.go b/internal/repos/find_test.go
index 08b79bd..93fbfa9 100644
--- a/internal/repos/find_test.go
+++ b/internal/repos/find_test.go
@@ -24,9 +24,9 @@ import (
"strings"
"testing"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/repos"
- "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/types"
)
func TestFindPkgs(t *testing.T) {
@@ -89,31 +89,31 @@ func TestFindPkgsEmpty(t *testing.T) {
e.Db,
)
- err := e.Db.InsertPackage(e.Ctx, db.Package{
+ err := e.Db.InsertPackage(e.Ctx, alrsh.Package{
Name: "test1",
Repository: "default",
Version: "0.0.1",
Release: 1,
- Description: db.NewJSON(map[string]string{
+ Provides: []string{""},
+ Description: alrsh.OverridableFromMap(map[string]string{
"en": "Test package 1",
"ru": "Проверочный пакет 1",
}),
- Provides: db.NewJSON([]string{""}),
})
if err != nil {
t.Fatalf("Expected no error, got %s", err)
}
- err = e.Db.InsertPackage(e.Ctx, db.Package{
+ err = e.Db.InsertPackage(e.Ctx, alrsh.Package{
Name: "test2",
Repository: "default",
Version: "0.0.1",
Release: 1,
- Description: db.NewJSON(map[string]string{
+ Provides: []string{"test"},
+ Description: alrsh.OverridableFromMap(map[string]string{
"en": "Test package 2",
"ru": "Проверочный пакет 2",
}),
- Provides: db.NewJSON([]string{"test"}),
})
if err != nil {
t.Fatalf("Expected no error, got %s", err)
diff --git a/internal/repos/pull.go b/internal/repos/pull.go
index d443d75..8a926a9 100644
--- a/internal/repos/pull.go
+++ b/internal/repos/pull.go
@@ -44,7 +44,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"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/pkg/types"
)
type actionType uint8
@@ -130,7 +130,7 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
// If the DB was not present at startup, that means it's
// empty. In this case, we need to update the DB fully
// rather than just incrementally.
- if rs.db.IsEmpty(ctx) {
+ if rs.db.IsEmpty() {
err = rs.processRepoFull(ctx, repo, repoDir)
if err != nil {
return err
diff --git a/internal/repos/pull_internal_test.go b/internal/repos/pull_internal_test.go
index 7836e93..6bd325b 100644
--- a/internal/repos/pull_internal_test.go
+++ b/internal/repos/pull_internal_test.go
@@ -27,7 +27,8 @@ 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/alrsh"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
)
type TestALRConfig struct{}
@@ -84,16 +85,10 @@ build_deps=('golang')
result, err := database.GetPkgs(ctx, "1 = 1")
assert.NoError(t, err)
pkgCount := 0
- for result.Next() {
- var dbPkg db.Package
- err = result.StructScan(&dbPkg)
- if err != nil {
- t.Errorf("Expected no error, got %s", err)
- }
-
- assert.Equal(t, "foo", dbPkg.Name)
- assert.Equal(t, db.NewJSON(map[string]string{"": "main desc"}), dbPkg.Description)
- assert.Equal(t, db.NewJSON(map[string][]string{"": {"sudo"}}), dbPkg.Depends)
+ for _, pkg := range result {
+ assert.Equal(t, "foo", pkg.Name)
+ assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "main desc"}), pkg.Description)
+ assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo"}}), pkg.Depends)
pkgCount++
}
assert.Equal(t, 1, pkgCount)
@@ -125,20 +120,18 @@ meta_buz() {
assert.NoError(t, err)
pkgCount := 0
- for result.Next() {
- var dbPkg db.Package
- err = result.StructScan(&dbPkg)
+ for _, pkg := range result {
if err != nil {
t.Errorf("Expected no error, got %s", err)
}
- if dbPkg.Name == "bar" {
- assert.Equal(t, db.NewJSON(map[string]string{"": "foo desc"}), dbPkg.Description)
- assert.Equal(t, db.NewJSON(map[string][]string{"": {"sudo"}}), dbPkg.Depends)
+ if pkg.Name == "bar" {
+ assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "foo desc"}), pkg.Description)
+ assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo"}}), pkg.Depends)
}
- if dbPkg.Name == "buz" {
- assert.Equal(t, db.NewJSON(map[string]string{"": "main desc"}), dbPkg.Description)
- assert.Equal(t, db.NewJSON(map[string][]string{"": {"sudo", "doas"}}), dbPkg.Depends)
+ if pkg.Name == "buz" {
+ assert.Equal(t, alrsh.OverridableFromMap(map[string]string{"": "main desc"}), pkg.Description)
+ assert.Equal(t, alrsh.OverridableFromMap(map[string][]string{"": {"sudo", "doas"}}), pkg.Depends)
}
pkgCount++
}
diff --git a/internal/repos/pull_test.go b/internal/repos/pull_test.go
index 0b0f1f3..56e306a 100644
--- a/internal/repos/pull_test.go
+++ b/internal/repos/pull_test.go
@@ -29,7 +29,7 @@ import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/repos"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
)
type TestEnv struct {
@@ -129,15 +129,7 @@ func TestPull(t *testing.T) {
t.Fatalf("Expected no error, got %s", err)
}
- var pkgAmt int
- for result.Next() {
- var dbPkg db.Package
- err = result.StructScan(&dbPkg)
- if err != nil {
- t.Errorf("Expected no error, got %s", err)
- }
- pkgAmt++
- }
+ pkgAmt := len(result)
if pkgAmt == 0 {
t.Errorf("Expected at least 1 matching package, but got %d", pkgAmt)
diff --git a/internal/repos/repos.go b/internal/repos/repos.go
index d89bea7..2f178a3 100644
--- a/internal/repos/repos.go
+++ b/internal/repos/repos.go
@@ -19,7 +19,7 @@ package repos
import (
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
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/pkg/types"
)
type Config interface {
diff --git a/internal/repos/utils.go b/internal/repos/utils.go
index b381b73..5b6e1cd 100644
--- a/internal/repos/utils.go
+++ b/internal/repos/utils.go
@@ -18,12 +18,9 @@ package repos
import (
"context"
- "errors"
"fmt"
"io"
"path/filepath"
- "reflect"
- "strings"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
@@ -34,11 +31,9 @@ import (
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/parser"
- "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/alrsh"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
)
// isValid makes sure the path of the file being updated is valid.
@@ -63,152 +58,21 @@ func parseScript(
syntaxParser *syntax.Parser,
runner *interp.Runner,
r io.ReadCloser,
-) ([]*db.Package, error) {
- fl, err := syntaxParser.Parse(r, "alr.sh")
+) ([]*alrsh.Package, error) {
+ f, err := alrsh.ReadFromIOReader(r, "/tmp")
if err != nil {
return nil, err
}
-
- runner.Reset()
- err = runner.Run(ctx, fl)
+ _, dbPkgs, err := f.ParseBuildVars(ctx, &distro.OSRelease{}, []string{})
if err != nil {
return nil, err
}
-
- d := decoder.New(&distro.OSRelease{}, runner)
- d.Overrides = false
- d.LikeDistros = false
-
- pkgNames, err := parser.ParseNames(d)
- if err != nil {
- return nil, fmt.Errorf("failed parsing package names: %w", err)
+ for _, pkg := range dbPkgs {
+ pkg.Repository = repo.Name
}
-
- 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 {
- Version string `sh:"version,required"`
- Release int `sh:"release,required"`
- Epoch uint `sh:"epoch"`
- Architectures db.JSON[[]string] `sh:"architectures"`
- Licenses db.JSON[[]string] `sh:"license"`
- Provides db.JSON[[]string] `sh:"provides"`
- Conflicts db.JSON[[]string] `sh:"conflicts"`
- Replaces db.JSON[[]string] `sh:"replaces"`
-}
-
-func (inf *PackageInfo) ToPackage(repoName string) *db.Package {
- pkg := EmptyPackage(repoName)
- pkg.Version = inf.Version
- pkg.Release = inf.Release
- pkg.Epoch = inf.Epoch
- pkg.Architectures = inf.Architectures
- pkg.Licenses = inf.Licenses
- pkg.Provides = inf.Provides
- pkg.Conflicts = inf.Conflicts
- pkg.Replaces = inf.Replaces
- return pkg
-}
-
-func EmptyPackage(repoName string) *db.Package {
- return &db.Package{
- Group: db.NewJSON(map[string]string{}),
- Summary: db.NewJSON(map[string]string{}),
- Description: db.NewJSON(map[string]string{}),
- Homepage: db.NewJSON(map[string]string{}),
- Maintainer: db.NewJSON(map[string]string{}),
- Depends: db.NewJSON(map[string][]string{}),
- BuildDepends: db.NewJSON(map[string][]string{}),
- Repository: repoName,
- }
-}
-
-var overridable = map[string]string{
- "deps": "Depends",
- "build_deps": "BuildDepends",
- "desc": "Description",
- "homepage": "Homepage",
- "maintainer": "Maintainer",
- "group": "Group",
- "summary": "Summary",
-}
-
-func resolveOverrides(runner *interp.Runner, pkg *db.Package) {
- pkgVal := reflect.ValueOf(pkg).Elem()
- for name, val := range runner.Vars {
- for prefix, field := range overridable {
- if strings.HasPrefix(name, prefix) {
- override := strings.TrimPrefix(name, prefix)
- override = strings.TrimPrefix(override, "_")
-
- field := pkgVal.FieldByName(field)
- varVal := field.FieldByName("Val")
- varType := varVal.Type()
-
- switch varType.Elem().String() {
- case "[]string":
- varVal.SetMapIndex(reflect.ValueOf(override), reflect.ValueOf(val.List))
- case "string":
- varVal.SetMapIndex(reflect.ValueOf(override), reflect.ValueOf(val.Str))
- }
- break
- }
- }
- }
-}
-
func getHeadReference(r *git.Repository) (plumbing.ReferenceName, error) {
remote, err := r.Remote(git.DefaultRemoteName)
if err != nil {
diff --git a/internal/search/search.go b/internal/search/search.go
index 64e5c5f..ca31bdc 100644
--- a/internal/search/search.go
+++ b/internal/search/search.go
@@ -22,13 +22,11 @@ package search
import (
"context"
- "github.com/jmoiron/sqlx"
-
- database "gitea.plemya-x.ru/Plemya-x/ALR/internal/db"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
)
type PackagesProvider interface {
- GetPkgs(ctx context.Context, where string, args ...any) (*sqlx.Rows, error)
+ GetPkgs(ctx context.Context, where string, args ...any) ([]alrsh.Package, error)
}
type Searcher struct {
@@ -44,23 +42,8 @@ func New(pp PackagesProvider) *Searcher {
func (s *Searcher) Search(
ctx context.Context,
opts *SearchOptions,
-) ([]database.Package, error) {
- var packages []database.Package
-
+) ([]alrsh.Package, error) {
where, args := opts.WhereClause()
- result, err := s.pp.GetPkgs(ctx, where, args...)
- if err != nil {
- return nil, err
- }
-
- for result.Next() {
- var dbPkg database.Package
- err = result.StructScan(&dbPkg)
- if err != nil {
- return nil, err
- }
- packages = append(packages, dbPkg)
- }
-
- return packages, nil
+ packages, err := s.pp.GetPkgs(ctx, where, args...)
+ return packages, err
}
diff --git a/internal/shutils/decoder/decoder.go b/internal/shutils/decoder/decoder.go
index 29b0352..0119664 100644
--- a/internal/shutils/decoder/decoder.go
+++ b/internal/shutils/decoder/decoder.go
@@ -22,6 +22,8 @@ package decoder
import (
"context"
"errors"
+ "fmt"
+ "log/slog"
"reflect"
"strings"
@@ -31,8 +33,8 @@ import (
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
)
var ErrNotPointerToStruct = errors.New("val must be a pointer to a struct")
@@ -52,7 +54,7 @@ type InvalidTypeError struct {
}
func (ite InvalidTypeError) Error() string {
- return "variable '" + ite.name + "' is of type " + ite.vartype + ", but " + ite.exptype + " is expected"
+ return fmt.Sprintf("variable '%s' is of type %s, but %s is expected", ite.name, ite.vartype, ite.exptype)
}
// Decoder provides methods for decoding variable values
@@ -81,13 +83,48 @@ func (d *Decoder) DecodeVar(name string, val any) error {
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
WeaklyTypedInput: true,
DecodeHook: mapstructure.DecodeHookFuncValue(func(from, to reflect.Value) (interface{}, error) {
- if strings.Contains(to.Type().String(), "db.JSON") {
- valType := to.FieldByName("Val").Type()
- if !from.Type().AssignableTo(valType) {
- return nil, InvalidTypeError{name, from.Type().String(), valType.String()}
+ if strings.Contains(to.Type().String(), "alrsh.OverridableField") {
+ if to.Kind() != reflect.Ptr && to.CanAddr() {
+ to = to.Addr()
+ }
+
+ names, err := overrides.Resolve(d.info, overrides.DefaultOpts.WithName(name))
+ if err != nil {
+ return nil, err
+ }
+
+ isNotSet := true
+
+ setMethod := to.MethodByName("Set")
+ setResolvedMethod := to.MethodByName("SetResolved")
+
+ for _, varName := range names {
+ val := d.getVarNoOverrides(varName)
+ if val == nil {
+ continue
+ }
+
+ t := setMethod.Type().In(1)
+
+ newVal := from
+
+ if !newVal.Type().AssignableTo(t) {
+ newVal = reflect.New(t)
+ err = d.DecodeVar(name, newVal.Interface())
+ if err != nil {
+ return nil, err
+ }
+ newVal = newVal.Elem()
+ }
+
+ if isNotSet {
+ setResolvedMethod.Call([]reflect.Value{newVal})
+ }
+
+ override := strings.TrimPrefix(strings.TrimPrefix(varName, name), "_")
+ setMethod.Call([]reflect.Value{reflect.ValueOf(override), newVal})
}
- to.FieldByName("Val").Set(from)
return to, nil
}
return from.Interface(), nil
@@ -96,6 +133,7 @@ func (d *Decoder) DecodeVar(name string, val any) error {
TagName: "sh",
})
if err != nil {
+ slog.Warn("err", "err", err)
return err
}
@@ -255,23 +293,31 @@ func (d *Decoder) getVar(name string) *expand.Variable {
}
for _, varName := range names {
- val, ok := d.Runner.Vars[varName]
- if ok {
- // Resolve nameref variables
- _, resolved := val.Resolve(expand.FuncEnviron(func(s string) string {
- if val, ok := d.Runner.Vars[s]; ok {
- return val.String()
- }
- return ""
- }))
- val = resolved
-
- return &val
+ res := d.getVarNoOverrides(varName)
+ if res != nil {
+ return res
}
}
return nil
}
+func (d *Decoder) getVarNoOverrides(name string) *expand.Variable {
+ val, ok := d.Runner.Vars[name]
+ if ok {
+ // Resolve nameref variables
+ _, resolved := val.Resolve(expand.FuncEnviron(func(s string) string {
+ if val, ok := d.Runner.Vars[s]; ok {
+ return val.String()
+ }
+ return ""
+ }))
+ val = resolved
+
+ return &val
+ }
+ return nil
+}
+
func IsTruthy(value string) bool {
value = strings.ToLower(strings.TrimSpace(value))
return value == "true" || value == "yes" || value == "1"
diff --git a/internal/shutils/decoder/decoder_test.go b/internal/shutils/decoder/decoder_test.go
index c9676b3..54a2b38 100644
--- a/internal/shutils/decoder/decoder_test.go
+++ b/internal/shutils/decoder/decoder_test.go
@@ -31,8 +31,8 @@ import (
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/decoder"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
)
type BuildVars struct {
diff --git a/internal/shutils/handlers/exec_test.go b/internal/shutils/handlers/exec_test.go
index d4eaacd..a81302d 100644
--- a/internal/shutils/handlers/exec_test.go
+++ b/internal/shutils/handlers/exec_test.go
@@ -27,9 +27,9 @@ import (
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
"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/pkg/distro"
)
const testScript = `
diff --git a/internal/translations/default.pot b/internal/translations/default.pot
index 92082a1..ce8bc93 100644
--- a/internal/translations/default.pot
+++ b/internal/translations/default.pot
@@ -126,71 +126,67 @@ msgstr ""
msgid "Error getting packages"
msgstr ""
-#: info.go:76
-msgid "Error iterating over packages"
-msgstr ""
-
-#: info.go:90
+#: info.go:83
msgid "Command info expected at least 1 argument, got %d"
msgstr ""
-#: info.go:110
+#: info.go:104
msgid "Error finding packages"
msgstr ""
-#: info.go:124
+#: info.go:118
msgid "Can't detect system language"
msgstr ""
-#: info.go:141
+#: info.go:135
msgid "Error resolving overrides"
msgstr ""
-#: info.go:149 info.go:154
+#: info.go:144 info.go:149
msgid "Error encoding script variables"
msgstr ""
-#: install.go:40
+#: install.go:39
msgid "Install a new package"
msgstr ""
-#: install.go:52
+#: install.go:51
msgid "Command install expected at least 1 argument, got %d"
msgstr ""
-#: install.go:114
+#: install.go:113
msgid "Error when installing the package"
msgstr ""
-#: install.go:159
+#: install.go:151
msgid "Remove an installed package"
msgstr ""
-#: install.go:178
+#: install.go:170
msgid "Error listing installed packages"
msgstr ""
-#: install.go:215
+#: install.go:199
msgid "Command remove expected at least 1 argument, got %d"
msgstr ""
-#: install.go:230
+#: install.go:214
msgid "Error removing packages"
msgstr ""
-#: internal/build/build.go:417
+#: internal/build/build.go:376
msgid "Building package"
msgstr ""
-#: internal/build/build.go:446
+#: internal/build/build.go:405
msgid "The checksums array must be the same length as sources"
msgstr ""
-#: internal/build/build.go:488
+#: internal/build/build.go:447
msgid "Downloading sources"
msgstr ""
-#: internal/build/build.go:580
+#: internal/build/build.go:539
msgid "Installing dependencies"
msgstr ""
@@ -224,19 +220,19 @@ msgstr ""
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
-#: internal/build/script_executor.go:236
+#: internal/build/script_executor.go:145
msgid "Building package metadata"
msgstr ""
-#: internal/build/script_executor.go:366
+#: internal/build/script_executor.go:276
msgid "Executing prepare()"
msgstr ""
-#: internal/build/script_executor.go:375
+#: internal/build/script_executor.go:285
msgid "Executing build()"
msgstr ""
-#: internal/build/script_executor.go:404 internal/build/script_executor.go:424
+#: internal/build/script_executor.go:314 internal/build/script_executor.go:334
msgid "Executing %s()"
msgstr ""
@@ -248,15 +244,15 @@ msgstr ""
msgid "Error initialization database"
msgstr ""
-#: internal/cliutils/app_builder/builder.go:135
+#: internal/cliutils/app_builder/builder.go:142
msgid "Error pulling repositories"
msgstr ""
-#: internal/cliutils/app_builder/builder.go:152
+#: internal/cliutils/app_builder/builder.go:159
msgid "Error parsing os release"
msgstr ""
-#: internal/cliutils/app_builder/builder.go:165
+#: internal/cliutils/app_builder/builder.go:172
msgid "Unable to detect a supported package manager on the system"
msgstr ""
@@ -340,17 +336,17 @@ msgstr ""
msgid "OPTIONS"
msgstr ""
-#: internal/cliutils/utils.go:69
+#: internal/cliutils/utils.go:72
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:76
msgid "Database version mismatch; resetting"
msgstr ""
-#: internal/db/db.go:144
+#: internal/db/db.go:82
msgid ""
"Database version does not exist. Run alr fix if something isn't working."
msgstr ""
@@ -429,11 +425,11 @@ msgstr ""
msgid "No packages for upgrade"
msgstr ""
-#: list.go:102 list.go:187
+#: list.go:102 list.go:184
msgid "Error parsing format template"
msgstr ""
-#: list.go:108 list.go:191
+#: list.go:108 list.go:188
msgid "Error executing template"
msgstr ""
@@ -545,14 +541,14 @@ msgstr ""
msgid "Error while executing search"
msgstr ""
-#: upgrade.go:47
+#: upgrade.go:48
msgid "Upgrade all installed packages"
msgstr ""
-#: upgrade.go:105 upgrade.go:122
+#: upgrade.go:106 upgrade.go:123
msgid "Error checking for updates"
msgstr ""
-#: upgrade.go:125
+#: upgrade.go:126
msgid "There is nothing to do."
msgstr ""
diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po
index dd35c8c..dd7d42c 100644
--- a/internal/translations/po/ru/default.po
+++ b/internal/translations/po/ru/default.po
@@ -133,71 +133,67 @@ msgstr "Показывать всю информацию, не только дл
msgid "Error getting packages"
msgstr "Ошибка при получении пакетов"
-#: info.go:76
-msgid "Error iterating over packages"
-msgstr "Ошибка при переборе пакетов"
-
-#: info.go:90
+#: info.go:83
msgid "Command info expected at least 1 argument, got %d"
msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d"
-#: info.go:110
+#: info.go:104
msgid "Error finding packages"
msgstr "Ошибка при поиске пакетов"
-#: info.go:124
+#: info.go:118
msgid "Can't detect system language"
msgstr "Ошибка при определении языка системы"
-#: info.go:141
+#: info.go:135
msgid "Error resolving overrides"
msgstr "Ошибка устранения переорпеделений"
-#: info.go:149 info.go:154
+#: info.go:144 info.go:149
msgid "Error encoding script variables"
msgstr "Ошибка кодирования переменных скрита"
-#: install.go:40
+#: install.go:39
msgid "Install a new package"
msgstr "Установить новый пакет"
-#: install.go:52
+#: install.go:51
msgid "Command install expected at least 1 argument, got %d"
msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d"
-#: install.go:114
+#: install.go:113
msgid "Error when installing the package"
msgstr "Ошибка при установке пакета"
-#: install.go:159
+#: install.go:151
msgid "Remove an installed package"
msgstr "Удалить установленный пакет"
-#: install.go:178
+#: install.go:170
msgid "Error listing installed packages"
msgstr "Ошибка при составлении списка установленных пакетов"
-#: install.go:215
+#: install.go:199
msgid "Command remove expected at least 1 argument, got %d"
msgstr "Для команды remove ожидался хотя бы 1 аргумент, получено %d"
-#: install.go:230
+#: install.go:214
msgid "Error removing packages"
msgstr "Ошибка при удалении пакетов"
-#: internal/build/build.go:417
+#: internal/build/build.go:376
msgid "Building package"
msgstr "Сборка пакета"
-#: internal/build/build.go:446
+#: internal/build/build.go:405
msgid "The checksums array must be the same length as sources"
msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
-#: internal/build/build.go:488
+#: internal/build/build.go:447
msgid "Downloading sources"
msgstr "Скачивание источников"
-#: internal/build/build.go:580
+#: internal/build/build.go:539
msgid "Installing dependencies"
msgstr "Установка зависимостей"
@@ -235,19 +231,19 @@ msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
-#: internal/build/script_executor.go:236
+#: internal/build/script_executor.go:145
msgid "Building package metadata"
msgstr "Сборка метаданных пакета"
-#: internal/build/script_executor.go:366
+#: internal/build/script_executor.go:276
msgid "Executing prepare()"
msgstr "Выполнение prepare()"
-#: internal/build/script_executor.go:375
+#: internal/build/script_executor.go:285
msgid "Executing build()"
msgstr "Выполнение build()"
-#: internal/build/script_executor.go:404 internal/build/script_executor.go:424
+#: internal/build/script_executor.go:314 internal/build/script_executor.go:334
msgid "Executing %s()"
msgstr "Выполнение %s()"
@@ -259,15 +255,15 @@ msgstr "Ошибка при загрузке"
msgid "Error initialization database"
msgstr "Ошибка инициализации базы данных"
-#: internal/cliutils/app_builder/builder.go:135
+#: internal/cliutils/app_builder/builder.go:142
msgid "Error pulling repositories"
msgstr "Ошибка при извлечении репозиториев"
-#: internal/cliutils/app_builder/builder.go:152
+#: internal/cliutils/app_builder/builder.go:159
msgid "Error parsing os release"
msgstr "Ошибка при разборе файла выпуска операционной системы"
-#: internal/cliutils/app_builder/builder.go:165
+#: internal/cliutils/app_builder/builder.go:172
msgid "Unable to detect a supported package manager on the system"
msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе"
@@ -351,7 +347,7 @@ msgstr "КАТЕГОРИЯ"
msgid "OPTIONS"
msgstr "ПАРАМЕТРЫ"
-#: internal/cliutils/utils.go:69
+#: internal/cliutils/utils.go:72
msgid ""
"This command is deprecated and would be removed in the future, use \"%s\" "
"instead!"
@@ -359,11 +355,11 @@ msgstr ""
"Эта команда устарела и будет удалена в будущем, используйте вместо нее \"%s"
"\"!"
-#: internal/db/db.go:137
+#: internal/db/db.go:76
msgid "Database version mismatch; resetting"
msgstr "Несоответствие версий базы данных; сброс настроек"
-#: internal/db/db.go:144
+#: internal/db/db.go:82
msgid ""
"Database version does not exist. Run alr fix if something isn't working."
msgstr ""
@@ -445,11 +441,11 @@ msgstr "Ошибка при получении пакетов для обнов
msgid "No packages for upgrade"
msgstr "Нет пакетов к обновлению"
-#: list.go:102 list.go:187
+#: list.go:102 list.go:184
msgid "Error parsing format template"
msgstr "Ошибка при разборе шаблона"
-#: list.go:108 list.go:191
+#: list.go:108 list.go:188
msgid "Error executing template"
msgstr "Ошибка при выполнении шаблона"
@@ -561,18 +557,21 @@ msgstr "Иcкать по provides"
msgid "Error while executing search"
msgstr "Ошибка при выполнении поиска"
-#: upgrade.go:47
+#: upgrade.go:48
msgid "Upgrade all installed packages"
msgstr "Обновить все установленные пакеты"
-#: upgrade.go:105 upgrade.go:122
+#: upgrade.go:106 upgrade.go:123
msgid "Error checking for updates"
msgstr "Ошибка при проверке обновлений"
-#: upgrade.go:125
+#: upgrade.go:126
msgid "There is nothing to do."
msgstr "Здесь нечего делать."
+#~ msgid "Error iterating over packages"
+#~ msgstr "Ошибка при переборе пакетов"
+
#~ msgid "Error pulling repos"
#~ msgstr "Ошибка при извлечении репозиториев"
diff --git a/list.go b/list.go
index 5b809eb..8d1ba69 100644
--- a/list.go
+++ b/list.go
@@ -32,9 +32,9 @@ import (
"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/manager"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/alrsh"
)
func ListCmd() *cli.Command {
@@ -69,9 +69,9 @@ func ListCmd() *cli.Command {
WithConfig().
WithDB().
WithManager().
+ WithDistroInfo().
// autoPull only
WithRepos().
- WithDistroInfo().
Build()
if err != nil {
return err
@@ -125,7 +125,6 @@ func ListCmd() *cli.Command {
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error getting packages"), err)
}
- defer result.Close()
installedAlrPackages := map[string]string{}
if c.Bool("installed") {
@@ -150,9 +149,7 @@ func ListCmd() *cli.Command {
}
}
- for result.Next() {
- var pkg database.Package
- err := result.StructScan(&pkg)
+ for _, pkg := range result {
if err != nil {
return cli.Exit(err, 1)
}
@@ -162,7 +159,7 @@ func ListCmd() *cli.Command {
}
type packageInfo struct {
- Package *database.Package
+ Package *alrsh.Package
Version string
}
diff --git a/old-files b/old-files
index 5be5cf9..70e552d 100644
--- a/old-files
+++ b/old-files
@@ -52,9 +52,9 @@
./internal/translations/files/lure.en.toml
./internal/translations/files/lure.ru.toml
./internal/translations/translations.go
-./internal/types/build.go
-./internal/types/config.go
-./internal/types/repo.go
+./pkg/types/build.go
+./pkg/types/config.go
+./pkg/types/repo.go
./list.go
./main.go
./pkg/build/build.go
diff --git a/pkg/alrsh/alrsh.go b/pkg/alrsh/alrsh.go
new file mode 100644
index 0000000..f2237b9
--- /dev/null
+++ b/pkg/alrsh/alrsh.go
@@ -0,0 +1,205 @@
+// 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 .
+
+package alrsh
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "strings"
+
+ "mvdan.cc/sh/v3/expand"
+ "mvdan.cc/sh/v3/interp"
+ "mvdan.cc/sh/v3/syntax"
+
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/cpu"
+ "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/pkg/distro"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
+)
+
+type ScriptFile struct {
+ file *syntax.File
+ path string
+}
+
+func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string {
+ env := os.Environ()
+
+ env = append(
+ env,
+ "DISTRO_NAME="+info.Name,
+ "DISTRO_PRETTY_NAME="+info.PrettyName,
+ "DISTRO_ID="+info.ID,
+ "DISTRO_VERSION_ID="+info.VersionID,
+ "DISTRO_ID_LIKE="+strings.Join(info.Like, " "),
+ "ARCH="+cpu.Arch(),
+ "NCPU="+strconv.Itoa(runtime.NumCPU()),
+ )
+
+ if dirs.ScriptDir != "" {
+ env = append(env, "scriptdir="+dirs.ScriptDir)
+ }
+
+ if dirs.PkgDir != "" {
+ env = append(env, "pkgdir="+dirs.PkgDir)
+ }
+
+ if dirs.SrcDir != "" {
+ env = append(env, "srcdir="+dirs.SrcDir)
+ }
+
+ return env
+}
+
+func (s *ScriptFile) ParseBuildVars(ctx context.Context, info *distro.OSRelease, packages []string) (string, []*Package, error) {
+ runner, err := s.createRunner(info)
+ if err != nil {
+ return "", nil, err
+ }
+
+ if err := runScript(ctx, runner, s.file); err != nil {
+ return "", nil, err
+ }
+
+ dec := newDecoder(info, runner)
+
+ pkgNames, err := ParseNames(dec)
+ if err != nil {
+ return "", nil, err
+ }
+
+ if len(pkgNames.Names) == 0 {
+ return "", nil, errors.New("package name is missing")
+ }
+
+ targetPackages := packages
+ if len(targetPackages) == 0 {
+ targetPackages = pkgNames.Names
+ }
+
+ varsOfPackages, err := s.createPackagesForBuildVars(ctx, dec, pkgNames, targetPackages)
+ if err != nil {
+ return "", nil, err
+ }
+
+ baseName := pkgNames.BasePkgName
+ if len(pkgNames.Names) == 1 {
+ baseName = pkgNames.Names[0]
+ }
+
+ return baseName, varsOfPackages, nil
+}
+
+func (s *ScriptFile) createRunner(info *distro.OSRelease) (*interp.Runner, error) {
+ scriptDir := filepath.Dir(s.path)
+ env := createBuildEnvVars(info, types.Directories{ScriptDir: scriptDir})
+
+ return interp.New(
+ interp.Env(expand.ListEnviron(env...)),
+ interp.StdIO(os.Stdin, os.Stderr, 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),
+ )
+}
+
+func (s *ScriptFile) createPackagesForBuildVars(
+ ctx context.Context,
+ dec *decoder.Decoder,
+ pkgNames *PackageNames,
+ targetPackages []string,
+) ([]*Package, error) {
+ var varsOfPackages []*Package
+
+ if len(pkgNames.Names) == 1 {
+ var pkg Package
+ pkg.Name = pkgNames.Names[0]
+ if err := dec.DecodeVars(&pkg); err != nil {
+ return nil, err
+ }
+ varsOfPackages = append(varsOfPackages, &pkg)
+ return varsOfPackages, nil
+ }
+
+ for _, pkgName := range targetPackages {
+ pkg, err := s.createPackageFromMeta(ctx, dec, pkgName, pkgNames.BasePkgName)
+ if err != nil {
+ return nil, err
+ }
+ varsOfPackages = append(varsOfPackages, pkg)
+ }
+
+ return varsOfPackages, nil
+}
+
+func (s *ScriptFile) createPackageFromMeta(
+ ctx context.Context,
+ dec *decoder.Decoder,
+ pkgName, basePkgName string,
+) (*Package, error) {
+ funcName := fmt.Sprintf("meta_%s", pkgName)
+ meta, ok := dec.GetFuncWithSubshell(funcName)
+ if !ok {
+ return nil, fmt.Errorf("func %s is missing", funcName)
+ }
+
+ metaRunner, err := meta(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ metaDecoder := decoder.New(&distro.OSRelease{}, metaRunner)
+
+ var vars Package
+ if err := metaDecoder.DecodeVars(&vars); err != nil {
+ return nil, err
+ }
+
+ vars.Name = pkgName
+ vars.BasePkgName = basePkgName
+
+ return &vars, nil
+}
+
+func runScript(ctx context.Context, runner *interp.Runner, fl *syntax.File) error {
+ runner.Reset()
+ return runner.Run(ctx, fl)
+}
+
+func newDecoder(info *distro.OSRelease, runner *interp.Runner) *decoder.Decoder {
+ d := decoder.New(info, runner)
+ // d.Overrides = false
+ // d.LikeDistros = false
+ return d
+}
+
+func (a *ScriptFile) Path() string {
+ return a.path
+}
+
+func (a *ScriptFile) File() *syntax.File {
+ return a.file
+}
diff --git a/pkg/alrsh/gob.go b/pkg/alrsh/gob.go
new file mode 100644
index 0000000..bb81815
--- /dev/null
+++ b/pkg/alrsh/gob.go
@@ -0,0 +1,61 @@
+// 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 .
+
+package alrsh
+
+import (
+ "bytes"
+ "encoding/gob"
+
+ "mvdan.cc/sh/v3/syntax"
+ "mvdan.cc/sh/v3/syntax/typedjson"
+)
+
+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
+ }
+ 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
+}
+
+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
+}
diff --git a/pkg/alrsh/overridable.go b/pkg/alrsh/overridable.go
new file mode 100644
index 0000000..f0ab785
--- /dev/null
+++ b/pkg/alrsh/overridable.go
@@ -0,0 +1,146 @@
+// 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 .
+
+package alrsh
+
+import (
+ "bytes"
+ "encoding/gob"
+ "encoding/json"
+)
+
+type OverridableField[T any] struct {
+ data map[string]T
+ // It can't be a pointer
+ //
+ // See https://gitea.com/xorm/xorm/issues/2431
+ resolved T
+}
+
+func (f *OverridableField[T]) Set(key string, value T) {
+ if f.data == nil {
+ f.data = make(map[string]T)
+ }
+ f.data[key] = value
+}
+
+func (f *OverridableField[T]) Get(key string) T {
+ if f.data == nil {
+ f.data = make(map[string]T)
+ }
+ return f.data[key]
+}
+
+func (f *OverridableField[T]) Has(key string) (T, bool) {
+ if f.data == nil {
+ f.data = make(map[string]T)
+ }
+ val, ok := f.data[key]
+ return val, ok
+}
+
+func (f *OverridableField[T]) SetResolved(value T) {
+ f.resolved = value
+}
+
+func (f *OverridableField[T]) Resolved() T {
+ return f.resolved
+}
+
+func (f *OverridableField[T]) All() map[string]T {
+ return f.data
+}
+
+func (o *OverridableField[T]) Resolve(overrides []string) {
+ for _, override := range overrides {
+ if v, ok := o.Has(override); ok {
+ o.SetResolved(v)
+ }
+ }
+}
+
+func (f *OverridableField[T]) ToDB() ([]byte, error) {
+ var data map[string]T
+
+ if f.data == nil {
+ data = make(map[string]T)
+ } else {
+ data = f.data
+ }
+
+ return json.Marshal(data)
+}
+
+func (f *OverridableField[T]) FromDB(data []byte) error {
+ if len(data) == 0 {
+ *f = OverridableField[T]{data: make(map[string]T)}
+ return nil
+ }
+
+ var temp map[string]T
+ if err := json.Unmarshal(data, &temp); err != nil {
+ return err
+ }
+
+ if temp == nil {
+ temp = make(map[string]T)
+ }
+
+ *f = OverridableField[T]{data: temp}
+ return nil
+}
+
+type overridableFieldGobPayload[T any] struct {
+ Data map[string]T
+ Resolved T
+}
+
+func (f *OverridableField[T]) GobEncode() ([]byte, error) {
+ var buf bytes.Buffer
+ enc := gob.NewEncoder(&buf)
+
+ payload := overridableFieldGobPayload[T]{
+ Data: f.data,
+ Resolved: f.resolved,
+ }
+
+ if err := enc.Encode(payload); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+func (f *OverridableField[T]) GobDecode(data []byte) error {
+ dec := gob.NewDecoder(bytes.NewBuffer(data))
+
+ var payload overridableFieldGobPayload[T]
+ if err := dec.Decode(&payload); err != nil {
+ return err
+ }
+
+ f.data = payload.Data
+ f.resolved = payload.Resolved
+ return nil
+}
+
+func OverridableFromMap[T any](data map[string]T) OverridableField[T] {
+ if data == nil {
+ data = make(map[string]T)
+ }
+ return OverridableField[T]{
+ data: data,
+ }
+}
diff --git a/pkg/alrsh/package.go b/pkg/alrsh/package.go
new file mode 100644
index 0000000..c24d0b2
--- /dev/null
+++ b/pkg/alrsh/package.go
@@ -0,0 +1,105 @@
+// 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 .
+
+package alrsh
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ "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
+}
+
+type Package struct {
+ Repository string `xorm:"pk 'repository'"`
+ Name string `xorm:"pk 'name'"`
+ BasePkgName string `xorm:"notnull 'basepkg_name'"`
+
+ Version string `sh:"version" xorm:"notnull 'version'"`
+ Release int `sh:"release" xorm:"notnull 'release'"`
+ Epoch uint `sh:"epoch" xorm:"'epoch'"`
+ Architectures []string `sh:"architectures" xorm:"json 'architectures'"`
+ Licenses []string `sh:"license" xorm:"json 'licenses'"`
+ Provides []string `sh:"provides" xorm:"json 'provides'"`
+ Conflicts []string `sh:"conflicts" xorm:"json 'conflicts'"`
+ Replaces []string `sh:"replaces" xorm:"json 'replaces'"`
+
+ Summary OverridableField[string] `sh:"summary" xorm:"'summary'"`
+ Description OverridableField[string] `sh:"desc" xorm:"'description'"`
+ Group OverridableField[string] `sh:"group" xorm:"'group_name'"`
+ Homepage OverridableField[string] `sh:"homepage" xorm:"'homepage'"`
+ Maintainer OverridableField[string] `sh:"maintainer" xorm:"'maintainer'"`
+ Depends OverridableField[[]string] `sh:"deps" xorm:"'depends'"`
+ BuildDepends OverridableField[[]string] `sh:"build_deps" xorm:"'builddepends'"`
+ OptDepends OverridableField[[]string] `sh:"opt_deps" xorm:"'optdepends'"`
+ Sources OverridableField[[]string] `sh:"sources" xorm:"-"`
+ Checksums OverridableField[[]string] `sh:"checksums" xorm:"-"`
+ Backup OverridableField[[]string] `sh:"backup" xorm:"-"`
+ Scripts OverridableField[Scripts] `sh:"scripts" xorm:"-"`
+ AutoReq OverridableField[[]string] `sh:"auto_req" xorm:"-"`
+ AutoProv OverridableField[[]string] `sh:"auto_prov" xorm:"-"`
+ AutoReqSkipList OverridableField[[]string] `sh:"auto_req_skiplist" xorm:"-"`
+ AutoProvSkipList OverridableField[[]string] `sh:"auto_prov_skiplist" xorm:"-"`
+}
+
+type Scripts struct {
+ PreInstall string `sh:"preinstall"`
+ PostInstall string `sh:"postinstall"`
+ PreRemove string `sh:"preremove"`
+ PostRemove string `sh:"postremove"`
+ PreUpgrade string `sh:"preupgrade"`
+ PostUpgrade string `sh:"postupgrade"`
+ PreTrans string `sh:"pretrans"`
+ PostTrans string `sh:"posttrans"`
+}
+
+func ResolvePackage(p *Package, overrides []string) {
+ val := reflect.ValueOf(p).Elem()
+ typ := val.Type()
+
+ for i := range val.NumField() {
+ field := val.Field(i)
+ fieldType := typ.Field(i)
+
+ if !field.CanInterface() {
+ continue
+ }
+
+ if field.Kind() == reflect.Struct && strings.HasPrefix(fieldType.Type.String(), "alrsh.OverridableField") {
+ of := field.Addr().Interface()
+ if res, ok := of.(interface {
+ Resolve([]string)
+ }); ok {
+ res.Resolve(overrides)
+ }
+ }
+ }
+}
diff --git a/pkg/alrsh/read.go b/pkg/alrsh/read.go
new file mode 100644
index 0000000..d5d7d74
--- /dev/null
+++ b/pkg/alrsh/read.go
@@ -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 .
+
+package alrsh
+
+import (
+ "fmt"
+ "io"
+ "io/fs"
+ "os"
+
+ "mvdan.cc/sh/v3/syntax"
+)
+
+type localFs struct{}
+
+func (fs *localFs) Open(name string) (fs.File, error) {
+ return os.Open(name)
+}
+
+func ReadFromIOReader(r io.Reader, script string) (*ScriptFile, error) {
+ file, err := syntax.NewParser().Parse(r, "alr.sh")
+ if err != nil {
+ return nil, err
+ }
+ return &ScriptFile{
+ file: file,
+ path: script,
+ }, nil
+}
+
+func ReadFromFS(fsys fs.FS, script string) (*ScriptFile, error) {
+ fl, err := fsys.Open(script)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open alr.sh: %w", err)
+ }
+ defer fl.Close()
+
+ return ReadFromIOReader(fl, script)
+}
+
+func ReadFromLocal(script string) (*ScriptFile, error) {
+ return ReadFromFS(&localFs{}, script)
+}
diff --git a/internal/distro/osrelease.go b/pkg/distro/osrelease.go
similarity index 100%
rename from internal/distro/osrelease.go
rename to pkg/distro/osrelease.go
diff --git a/internal/types/build.go b/pkg/types/build.go
similarity index 50%
rename from internal/types/build.go
rename to pkg/types/build.go
index 350a1f0..7e253b0 100644
--- a/internal/types/build.go
+++ b/pkg/types/build.go
@@ -24,49 +24,6 @@ type BuildOpts struct {
Interactive bool
}
-type BuildVarsPre struct {
- Version string `sh:"version,required"`
- Release int `sh:"release,required"`
- Epoch uint `sh:"epoch"`
- Summary string `sh:"summary"`
- Description string `sh:"desc"`
- Group string `sh:"group"`
- Homepage string `sh:"homepage"`
- Maintainer string `sh:"maintainer"`
- Architectures []string `sh:"architectures"`
- Licenses []string `sh:"license"`
- Provides []string `sh:"provides"`
- Conflicts []string `sh:"conflicts"`
- Depends []string `sh:"deps"`
- BuildDepends []string `sh:"build_deps"`
- OptDepends []string `sh:"opt_deps"`
- Replaces []string `sh:"replaces"`
- Sources []string `sh:"sources"`
- Checksums []string `sh:"checksums"`
- Backup []string `sh:"backup"`
- Scripts Scripts `sh:"scripts"`
- AutoReq []string `sh:"auto_req"`
- AutoProv []string `sh:"auto_prov"`
- AutoReqSkipList []string `sh:"auto_req_skiplist"`
- AutoProvSkipList []string `sh:"auto_prov_skiplist"`
-}
-
-func (bv *BuildVarsPre) ToBuildVars() BuildVars {
- return BuildVars{
- Name: "",
- Base: "",
- BuildVarsPre: *bv,
- }
-}
-
-// BuildVars represents the script variables required
-// to build a package
-type BuildVars struct {
- Name string `sh:"name,required"`
- Base string
- BuildVarsPre
-}
-
type Scripts struct {
PreInstall string `sh:"preinstall"`
PostInstall string `sh:"postinstall"`
diff --git a/internal/types/config.go b/pkg/types/config.go
similarity index 100%
rename from internal/types/config.go
rename to pkg/types/config.go
diff --git a/internal/types/repo.go b/pkg/types/repo.go
similarity index 100%
rename from internal/types/repo.go
rename to pkg/types/repo.go
diff --git a/pkg/types/script.go b/pkg/types/script.go
new file mode 100644
index 0000000..c167a6d
--- /dev/null
+++ b/pkg/types/script.go
@@ -0,0 +1,66 @@
+// 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 .
+
+package types
+
+import (
+ "bytes"
+ "encoding/gob"
+
+ "mvdan.cc/sh/v3/syntax"
+ "mvdan.cc/sh/v3/syntax/typedjson"
+)
+
+type ScriptFile struct {
+ File *syntax.File
+ 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
+ }
+ 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
+}
+
+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
+}
diff --git a/repo.go b/repo.go
index e7e852b..64123aa 100644
--- a/repo.go
+++ b/repo.go
@@ -29,8 +29,8 @@ import (
"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/types"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/utils"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
)
func RepoCmd() *cli.Command {
diff --git a/search.go b/search.go
index f677bee..02c88ae 100644
--- a/search.go
+++ b/search.go
@@ -27,11 +27,11 @@ import (
"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/db"
- "gitea.plemya-x.ru/Plemya-x/ALR/internal/distro"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/overrides"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/search"
"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"
)
func SearchCmd() *cli.Command {
@@ -139,27 +139,16 @@ func SearchCmd() *cli.Command {
}
}
- for _, dbPkg := range packages {
- var pkg any
- if !all {
- pkg = overrides.ResolvePackage(&dbPkg, names)
- } else {
- pkg = &dbPkg
- }
-
+ for _, pkg := range packages {
+ alrsh.ResolvePackage(&pkg, names)
if tmpl != nil {
- err = tmpl.Execute(os.Stdout, pkg)
+ err = tmpl.Execute(os.Stdout, &pkg)
if err != nil {
return cliutils.FormatCliExit(gotext.Get("Error executing template"), err)
}
fmt.Println()
} else {
- switch v := pkg.(type) {
- case *overrides.ResolvedPackage:
- fmt.Println(v.Name)
- case *db.Package:
- fmt.Println(v.Name)
- }
+ fmt.Println(pkg.Name)
}
}
diff --git a/upgrade.go b/upgrade.go
index d90b46e..254edaa 100644
--- a/upgrade.go
+++ b/upgrade.go
@@ -33,12 +33,13 @@ 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/distro"
"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/search"
- "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/alrsh"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/distro"
+ "gitea.plemya-x.ru/Plemya-x/ALR/pkg/types"
)
func UpgradeCmd() *cli.Command {
@@ -130,8 +131,8 @@ func UpgradeCmd() *cli.Command {
}
}
-func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package {
- var pkgs []database.Package
+func mapUptatesInfoToPackages(updates []UpdateInfo) []alrsh.Package {
+ var pkgs []alrsh.Package
for _, info := range updates {
pkgs = append(pkgs, *info.Package)
}
@@ -139,7 +140,7 @@ func mapUptatesInfoToPackages(updates []UpdateInfo) []database.Package {
}
type UpdateInfo struct {
- Package *database.Package
+ Package *alrsh.Package
FromVersion string
ToVersion string