4 Commits

9 changed files with 640 additions and 170 deletions

14
go.mod
View File

@@ -1,8 +1,8 @@
module gitea.plemya-x.ru/Plemya-x/ALR module gitea.plemya-x.ru/Plemya-x/ALR
go 1.21 go 1.22
toolchain go1.21.3 toolchain go1.23.5
require ( require (
github.com/AlecAivazis/survey/v2 v2.3.7 github.com/AlecAivazis/survey/v2 v2.3.7
@@ -34,7 +34,7 @@ require (
golang.org/x/text v0.21.0 golang.org/x/text v0.21.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.25.0 modernc.org/sqlite v1.25.0
mvdan.cc/sh/v3 v3.7.0 mvdan.cc/sh/v3 v3.10.0
plemya-x.ru/fakeroot v0.0.0-20240601131003-c638a3543283 plemya-x.ru/fakeroot v0.0.0-20240601131003-c638a3543283
) )
@@ -110,11 +110,11 @@ require (
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/mod v0.17.0 // indirect golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.25.0 // indirect golang.org/x/net v0.26.0 // indirect
golang.org/x/sync v0.10.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/term v0.24.0 // indirect golang.org/x/term v0.25.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/tools v0.22.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
lukechampine.com/uint128 v1.2.0 // indirect lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect

11
go.sum
View File

@@ -97,6 +97,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -404,6 +405,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20180826012351-8a410e7b638d/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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -426,6 +429,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -478,6 +483,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -520,6 +527,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -605,6 +614,8 @@ modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=
mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4=
mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY=
plemya-x.ru/fakeroot v0.0.0-20240601131003-c638a3543283 h1:BXCLPeA8g2M6qYngicyxyB/2Bo4J54Q9Rb+8jMmE3ik= plemya-x.ru/fakeroot v0.0.0-20240601131003-c638a3543283 h1:BXCLPeA8g2M6qYngicyxyB/2Bo4J54Q9Rb+8jMmE3ik=
plemya-x.ru/fakeroot v0.0.0-20240601131003-c638a3543283/go.mod h1:itzL9Jx52VXOhRaucFHuMpa3y7iwjnuLGdNvypoh/S4= plemya-x.ru/fakeroot v0.0.0-20240601131003-c638a3543283/go.mod h1:itzL9Jx52VXOhRaucFHuMpa3y7iwjnuLGdNvypoh/S4=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@@ -177,7 +177,35 @@ func (d *Decoder) GetFunc(name string) (ScriptFunc, bool) {
return func(ctx context.Context, opts ...interp.RunnerOption) error { return func(ctx context.Context, opts ...interp.RunnerOption) error {
sub := d.Runner.Subshell() sub := d.Runner.Subshell()
for _, opt := range opts { for _, opt := range opts {
opt(sub) err := opt(sub)
if err != nil {
return err
}
}
return sub.Run(ctx, fn)
}, true
}
type PrepareFunc func(context.Context, *interp.Runner) error
func (d *Decoder) GetFuncP(name string, prepare PrepareFunc) (ScriptFunc, bool) {
fn := d.getFunc(name)
if fn == nil {
return nil, false
}
return func(ctx context.Context, opts ...interp.RunnerOption) error {
sub := d.Runner.Subshell()
for _, opt := range opts {
err := opt(sub)
if err != nil {
return err
}
}
if prepare != nil {
if err := prepare(ctx, sub); err != nil {
return err
}
} }
return sub.Run(ctx, fn) return sub.Run(ctx, fn)
}, true }, true

View File

@@ -24,6 +24,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@@ -55,12 +56,17 @@ var Helpers = handlers.ExecFuncs{
"install-completion": installCompletionCmd, "install-completion": installCompletionCmd,
"install-library": installLibraryCmd, "install-library": installLibraryCmd,
"git-version": gitVersionCmd, "git-version": gitVersionCmd,
"files-find-lang": filesFindLangCmd,
"files-find-doc": filesFindDocCmd,
} }
// Restricted contains restricted read-only helper commands // Restricted contains restricted read-only helper commands
// that don't modify any state // that don't modify any state
var Restricted = handlers.ExecFuncs{ var Restricted = handlers.ExecFuncs{
"git-version": gitVersionCmd, "git-version": gitVersionCmd,
"files-find-lang": filesFindLangCmd,
"files-find-doc": filesFindDocCmd,
} }
func installHelperCmd(prefix string, perms os.FileMode) handlers.ExecFunc { func installHelperCmd(prefix string, perms os.FileMode) handlers.ExecFunc {
@@ -256,6 +262,114 @@ func gitVersionCmd(hc interp.HandlerContext, cmd string, args []string) error {
return nil return nil
} }
func filesFindLangCmd(hc interp.HandlerContext, cmd string, args []string) error {
namePattern := "*.mo"
if len(args) > 0 {
namePattern = args[0] + ".mo"
}
localePath := "./usr/share/locale/"
realPath := path.Join(hc.Dir, localePath)
info, err := os.Stat(realPath)
if err != nil {
return fmt.Errorf("files-find-lang: %w", err)
}
if !info.IsDir() {
return fmt.Errorf("files-find-lang: %s is not a directory", localePath)
}
var langFiles []string
err = filepath.Walk(realPath, func(p string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && matchNamePattern(info.Name(), namePattern) {
relPath, relErr := filepath.Rel(hc.Dir, p)
if relErr != nil {
return relErr
}
langFiles = append(langFiles, "./"+relPath)
}
return nil
})
if err != nil {
return fmt.Errorf("files-find-lang: %w", err)
}
for _, file := range langFiles {
fmt.Fprintln(hc.Stdout, file)
}
return nil
}
func filesFindDocCmd(hc interp.HandlerContext, cmd string, args []string) error {
namePattern := "*"
if len(args) > 0 {
namePattern = args[0]
}
docPath := "./usr/share/doc/"
docRealPath := path.Join(hc.Dir, docPath)
info, err := os.Stat(docRealPath)
if err != nil {
return fmt.Errorf("files-find-doc: %w", err)
}
if !info.IsDir() {
return fmt.Errorf("files-find-doc: %s is not a directory", docPath)
}
var docFiles []string
entries, err := os.ReadDir(docRealPath)
if err != nil {
return err
}
for _, entry := range entries {
if matchNamePattern(entry.Name(), namePattern) {
targetPath := filepath.Join(docRealPath, entry.Name())
targetInfo, err := os.Stat(targetPath)
if err != nil {
return err
}
if targetInfo.IsDir() {
err := filepath.Walk(targetPath, func(subPath string, subInfo os.FileInfo, subErr error) error {
relPath, err := filepath.Rel(hc.Dir, subPath)
if err != nil {
return err
}
docFiles = append(docFiles, "./"+relPath)
return nil
})
if err != nil {
return err
}
}
}
}
if err != nil {
return fmt.Errorf("files-find-doc: %w", err)
}
for _, file := range docFiles {
fmt.Fprintln(hc.Stdout, file)
}
return nil
}
func matchNamePattern(name, pattern string) bool {
matched, err := filepath.Match(pattern, name)
if err != nil {
return false
}
return matched
}
func helperInstall(from, to string, perms os.FileMode) error { func helperInstall(from, to string, perms os.FileMode) error {
err := os.MkdirAll(filepath.Dir(to), 0o755) err := os.MkdirAll(filepath.Dir(to), 0o755)
if err != nil { if err != nil {

View File

@@ -0,0 +1,216 @@
// ALR - Any Linux Repository
// Copyright (C) 2025 Евгений Храмов
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package helpers
import (
"bytes"
"context"
"os"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/syntax"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/shutils/handlers"
)
type testCase struct {
name string
dirsToCreate []string
filesToCreate []string
expectedOutput []string
args string
}
func TestFindFilesDoc(t *testing.T) {
tests := []testCase{
{
name: "All dirs",
dirsToCreate: []string{
"usr/share/doc/yandex-browser-stable/subdir",
"usr/share/doc/firefox",
},
filesToCreate: []string{
"usr/share/doc/yandex-browser-stable/README.md",
"usr/share/doc/yandex-browser-stable/subdir/nested-file.txt",
"usr/share/doc/firefox/README.md",
},
expectedOutput: []string{
"./usr/share/doc/yandex-browser-stable",
"./usr/share/doc/yandex-browser-stable/README.md",
"./usr/share/doc/yandex-browser-stable/subdir",
"./usr/share/doc/yandex-browser-stable/subdir/nested-file.txt",
"./usr/share/doc/firefox",
"./usr/share/doc/firefox/README.md",
},
args: "",
},
{
name: "Only selected dir",
dirsToCreate: []string{
"usr/share/doc/yandex-browser-stable/subdir",
"usr/share/doc/firefox",
"usr/share/doc/foo/yandex-browser-stable",
},
filesToCreate: []string{
"usr/share/doc/yandex-browser-stable/README.md",
"usr/share/doc/yandex-browser-stable/subdir/nested-file.txt",
"usr/share/doc/firefox/README.md",
"usr/share/doc/firefox/yandex-browser-stable",
"usr/share/doc/foo/yandex-browser-stable/README.md",
},
expectedOutput: []string{
"./usr/share/doc/yandex-browser-stable",
"./usr/share/doc/yandex-browser-stable/README.md",
"./usr/share/doc/yandex-browser-stable/subdir",
"./usr/share/doc/yandex-browser-stable/subdir/nested-file.txt",
},
args: "yandex-browser-stable",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tempDir, err := os.MkdirTemp("", "test-files-find-doc")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)
for _, dir := range tc.dirsToCreate {
dirPath := filepath.Join(tempDir, dir)
err := os.MkdirAll(dirPath, 0o755)
assert.NoError(t, err)
}
for _, file := range tc.filesToCreate {
filePath := filepath.Join(tempDir, file)
err := os.WriteFile(filePath, []byte("test content"), 0o644)
assert.NoError(t, err)
}
helpers := handlers.ExecFuncs{
"files-find-doc": filesFindDocCmd,
}
buf := &bytes.Buffer{}
runner, err := interp.New(
interp.Dir(tempDir),
interp.StdIO(os.Stdin, buf, os.Stderr),
interp.ExecHandler(helpers.ExecHandler(interp.DefaultExecHandler(1000))),
)
assert.NoError(t, err)
scriptContent := `
shopt -s globstar
files-find-doc ` + tc.args
script, err := syntax.NewParser().Parse(strings.NewReader(scriptContent), "")
assert.NoError(t, err)
err = runner.Run(context.Background(), script)
assert.NoError(t, err)
contents := strings.Fields(strings.TrimSpace(buf.String()))
assert.ElementsMatch(t, tc.expectedOutput, contents)
})
}
}
func TestFindLang(t *testing.T) {
tests := []testCase{
{
name: "All dirs",
dirsToCreate: []string{
"usr/share/locale/ru/LC_MESSAGES",
"usr/share/locale/tr/LC_MESSAGES",
},
filesToCreate: []string{
"usr/share/locale/ru/LC_MESSAGES/yandex-disk.mo",
"usr/share/locale/ru/LC_MESSAGES/yandex-disk-indicator.mo",
"usr/share/locale/tr/LC_MESSAGES/yandex-disk.mo",
},
expectedOutput: []string{
"./usr/share/locale/ru/LC_MESSAGES/yandex-disk.mo",
"./usr/share/locale/ru/LC_MESSAGES/yandex-disk-indicator.mo",
"./usr/share/locale/tr/LC_MESSAGES/yandex-disk.mo",
},
args: "",
},
{
name: "All dirs",
dirsToCreate: []string{
"usr/share/locale/ru/LC_MESSAGES",
"usr/share/locale/tr/LC_MESSAGES",
},
filesToCreate: []string{
"usr/share/locale/ru/LC_MESSAGES/yandex-disk.mo",
"usr/share/locale/ru/LC_MESSAGES/yandex-disk-indicator.mo",
"usr/share/locale/tr/LC_MESSAGES/yandex-disk.mo",
},
expectedOutput: []string{
"./usr/share/locale/ru/LC_MESSAGES/yandex-disk.mo",
"./usr/share/locale/tr/LC_MESSAGES/yandex-disk.mo",
},
args: "yandex-disk",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tempDir, err := os.MkdirTemp("", "test-files-find-lang")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)
for _, dir := range tc.dirsToCreate {
dirPath := filepath.Join(tempDir, dir)
err := os.MkdirAll(dirPath, 0o755)
assert.NoError(t, err)
}
for _, file := range tc.filesToCreate {
filePath := filepath.Join(tempDir, file)
err := os.WriteFile(filePath, []byte("test content"), 0o644)
assert.NoError(t, err)
}
helpers := handlers.ExecFuncs{
"files-find-lang": filesFindLangCmd,
}
buf := &bytes.Buffer{}
runner, err := interp.New(
interp.Dir(tempDir),
interp.StdIO(os.Stdin, buf, os.Stderr),
interp.ExecHandler(helpers.ExecHandler(interp.DefaultExecHandler(1000))),
)
assert.NoError(t, err)
scriptContent := `
shopt -s globstar
files-find-lang ` + tc.args
script, err := syntax.NewParser().Parse(strings.NewReader(scriptContent), "")
assert.NoError(t, err)
err = runner.Run(context.Background(), script)
assert.NoError(t, err)
contents := strings.Fields(strings.TrimSpace(buf.String()))
assert.ElementsMatch(t, tc.expectedOutput, contents)
})
}
}

View File

@@ -251,7 +251,7 @@ msgstr ""
msgid "Downloading source" msgid "Downloading source"
msgstr "" msgstr ""
#: internal/logger/log.go:44 #: internal/logger/log.go:47
msgid "ERROR" msgid "ERROR"
msgstr "" msgstr ""
@@ -323,35 +323,43 @@ msgstr ""
msgid "Installing dependencies" msgid "Installing dependencies"
msgstr "" msgstr ""
#: pkg/build/build.go:435 #: pkg/build/build.go:439
msgid "Executing version()" msgid "Executing version()"
msgstr "" msgstr ""
#: pkg/build/build.go:460 #: pkg/build/build.go:459
msgid "Updating version"
msgstr ""
#: pkg/build/build.go:464
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "" msgstr ""
#: pkg/build/build.go:470 #: pkg/build/build.go:474
msgid "Executing build()" msgid "Executing build()"
msgstr "" msgstr ""
#: pkg/build/build.go:482 #: pkg/build/build.go:486
msgid "Executing package()" msgid "Executing package()"
msgstr "" msgstr ""
#: pkg/build/build.go:557 #: pkg/build/build.go:524
msgid "AutoProv is not implemented for this package format, so it's skiped" msgid "Executing files()"
msgstr "" msgstr ""
#: pkg/build/build.go:568 #: pkg/build/build.go:601
msgid "AutoReq is not implemented for this package format, so it's skiped" msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr "" msgstr ""
#: pkg/build/build.go:653 #: pkg/build/build.go:612
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
#: pkg/build/build.go:719
msgid "Would you like to remove the build dependencies?" msgid "Would you like to remove the build dependencies?"
msgstr "" msgstr ""
#: pkg/build/build.go:759 #: pkg/build/build.go:825
msgid "The checksums array must be the same length as sources" msgid "The checksums array must be the same length as sources"
msgstr "" msgstr ""
@@ -389,7 +397,7 @@ msgstr ""
#: pkg/repos/pull.go:172 #: pkg/repos/pull.go:172
msgid "" msgid ""
"ALR repo's minumum ALR version is greater than the current version. Try " "ALR repo's minimum ALR version is greater than the current version. Try "
"updating ALR if something doesn't work." "updating ALR if something doesn't work."
msgstr "" msgstr ""
@@ -437,10 +445,14 @@ msgstr ""
msgid "Pull all repositories that have changed" msgid "Pull all repositories that have changed"
msgstr "" msgstr ""
#: upgrade.go:47 #: upgrade.go:46
msgid "Upgrade all installed packages" msgid "Upgrade all installed packages"
msgstr "" msgstr ""
#: upgrade.go:83 #: upgrade.go:82
msgid "Error checking for updates" msgid "Error checking for updates"
msgstr "" msgstr ""
#: upgrade.go:93
msgid "There is nothing to do."
msgstr ""

View File

@@ -1,11 +1,12 @@
# #
# Maxim Slipenko <maks1ms@alt-gnome.ru>, 2025. # Maxim Slipenko <maks1ms@alt-gnome.ru>, 2025.
# x1z53 <x1z53@yandex.ru>, 2025.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: unnamed project\n" "Project-Id-Version: unnamed project\n"
"PO-Revision-Date: 2025-01-22 16:50+0300\n" "PO-Revision-Date: 2025-01-24 21:20+0300\n"
"Last-Translator: Maxim Slipenko <maks1ms@alt-gnome.ru>\n" "Last-Translator: x1z53 <x1z53@yandex.ru>\n"
"Language-Team: Russian\n" "Language-Team: Russian\n"
"Language: ru\n" "Language: ru\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -16,31 +17,29 @@ msgstr ""
"X-Generator: Gtranslator 47.1\n" "X-Generator: Gtranslator 47.1\n"
#: build.go:41 #: build.go:41
#, fuzzy
msgid "Build a local package" msgid "Build a local package"
msgstr "Сборка пакета" msgstr "Сборка локального пакета"
#: build.go:47 #: build.go:47
#, fuzzy
msgid "Path to the build script" msgid "Path to the build script"
msgstr "Не удалось предложить просмотреть скрипт" msgstr "Путь к скрипту сборки"
#: build.go:52 #: build.go:52
msgid "Name of the package to build and its repo (example: default/go-bin)" msgid "Name of the package to build and its repo (example: default/go-bin)"
msgstr "" msgstr "Имя пакета для сборки и его репозиторий (пример: default/go-bin)"
#: build.go:57 #: build.go:57
msgid "" msgid ""
"Build package from scratch even if there's an already built package available" "Build package from scratch even if there's an already built package available"
msgstr "" msgstr "Создайте пакет с нуля, даже если уже имеется готовый пакет"
#: build.go:71 #: build.go:71
msgid "Error pulling repositories" msgid "Error pulling repositories"
msgstr "" msgstr "Ошибка при извлечении репозиториев"
#: build.go:78 #: build.go:78
msgid "Unable to detect a supported package manager on the system" msgid "Unable to detect a supported package manager on the system"
msgstr "" msgstr "Не удалось обнаружить поддерживаемый менеджер пакетов в системе"
#: build.go:89 #: build.go:89
msgid "Error building package" msgid "Error building package"
@@ -48,123 +47,123 @@ msgstr "Ошибка при сборке пакета"
#: build.go:95 #: build.go:95
msgid "Error getting working directory" msgid "Error getting working directory"
msgstr "" msgstr "Ошибка при получении рабочего каталога"
#: build.go:103 #: build.go:103
msgid "Error moving the package" msgid "Error moving the package"
msgstr "" msgstr "Ошибка при перемещении пакета"
#: fix.go:37 #: fix.go:37
msgid "Attempt to fix problems with ALR" msgid "Attempt to fix problems with ALR"
msgstr "" msgstr "Попытка устранить проблемы с ALR"
#: fix.go:44 #: fix.go:44
msgid "Removing cache directory" msgid "Removing cache directory"
msgstr "" msgstr "Удаление каталога кэша"
#: fix.go:48 #: fix.go:48
msgid "Unable to remove cache directory" msgid "Unable to remove cache directory"
msgstr "" msgstr "Не удалось удалить каталог кэша"
#: fix.go:52 #: fix.go:52
msgid "Rebuilding cache" msgid "Rebuilding cache"
msgstr "" msgstr "Восстановление кэша"
#: fix.go:56 #: fix.go:56
msgid "Unable to create new cache directory" msgid "Unable to create new cache directory"
msgstr "" msgstr "Не удалось создать новый каталог кэша"
#: fix.go:62 #: fix.go:62
msgid "Error pulling repos" msgid "Error pulling repos"
msgstr "" msgstr "Ошибка при извлечении репозиториев"
#: fix.go:66 #: fix.go:66
msgid "Done" msgid "Done"
msgstr "" msgstr "Сделано"
#: gen.go:34 #: gen.go:34
msgid "Generate a ALR script from a template" msgid "Generate a ALR script from a template"
msgstr "" msgstr "Генерация скрипта ALR из шаблона"
#: gen.go:39 #: gen.go:39
msgid "Generate a ALR script for a pip module" msgid "Generate a ALR script for a pip module"
msgstr "" msgstr "Генерация скрипта ALR для модуля pip"
#: helper.go:41 #: helper.go:41
msgid "List all the available helper commands" msgid "List all the available helper commands"
msgstr "" msgstr "Список всех доступных вспомогательных команды"
#: helper.go:53 #: helper.go:53
msgid "Run a ALR helper command" msgid "Run a ALR helper command"
msgstr "" msgstr "Запустить вспомогательную команду ALR"
#: helper.go:60 #: helper.go:60
msgid "The directory that the install commands will install to" msgid "The directory that the install commands will install to"
msgstr "" msgstr "Каталог, в который будут устанавливать команды установки"
#: helper.go:73 #: helper.go:73
msgid "No such helper command" msgid "No such helper command"
msgstr "" msgstr "Такой вспомогательной команды нет"
#: info.go:42 #: info.go:42
msgid "Print information about a package" msgid "Print information about a package"
msgstr "Напечатать информацию о пакете" msgstr "Отобразить информацию о пакете"
#: info.go:47 #: info.go:47
msgid "Show all information, not just for the current distro" msgid "Show all information, not just for the current distro"
msgstr "Показывать всю информацию, а не только для текущего дистрибутива" msgstr "Показывать всю информацию, не только для текущего дистрибутива"
#: info.go:57 #: info.go:57
msgid "Error initialization database" msgid "Error initialization database"
msgstr "" msgstr "Ошибка инициализации базы данных"
#: info.go:64 #: info.go:64
msgid "Command info expected at least 1 argument, got %d" msgid "Command info expected at least 1 argument, got %d"
msgstr "" msgstr "Для команды info ожидался хотя бы 1 аргумент, получено %d"
#: info.go:78 #: info.go:78
msgid "Error finding packages" msgid "Error finding packages"
msgstr "" msgstr "Ошибка при поиске пакетов"
#: info.go:94 #: info.go:94
msgid "Error parsing os-release file" msgid "Error parsing os-release file"
msgstr "" msgstr "Ошибка при разборе файла выпуска операционной системы"
#: info.go:103 #: info.go:103
msgid "Error resolving overrides" msgid "Error resolving overrides"
msgstr "" msgstr "Ошибка устранения переорпеделений"
#: info.go:112 info.go:118 #: info.go:112 info.go:118
msgid "Error encoding script variables" msgid "Error encoding script variables"
msgstr "" msgstr "Ошибка кодирования переменных скрита"
#: install.go:42 #: install.go:42
msgid "Install a new package" msgid "Install a new package"
msgstr "" msgstr "Установить новый пакет"
#: install.go:56 #: install.go:56
msgid "Command install expected at least 1 argument, got %d" msgid "Command install expected at least 1 argument, got %d"
msgstr "" msgstr "Для команды install ожидался хотя бы 1 аргумент, получено %d"
#: install.go:91 #: install.go:91
msgid "Error getting packages" msgid "Error getting packages"
msgstr "" msgstr "Ошибка при получении пакетов"
#: install.go:100 #: install.go:100
msgid "Error iterating over packages" msgid "Error iterating over packages"
msgstr "" msgstr "Ошибка при переборе пакетов"
#: install.go:113 #: install.go:113
msgid "Remove an installed package" msgid "Remove an installed package"
msgstr "" msgstr "Удалить установленный пакет"
#: install.go:118 #: install.go:118
msgid "Command remove expected at least 1 argument, got %d" msgid "Command remove expected at least 1 argument, got %d"
msgstr "" msgstr "Для команды remove ожидался хотя бы 1 аргумент, получено %d"
#: install.go:130 #: install.go:130
msgid "Error removing packages" msgid "Error removing packages"
msgstr "" msgstr "Ошибка при удалении пакетов"
#: internal/cliutils/prompt.go:60 #: internal/cliutils/prompt.go:60
msgid "Would you like to view the build script for %s" msgid "Would you like to view the build script for %s"
@@ -180,122 +179,129 @@ msgstr "Пользователь решил не продолжать после
#: internal/cliutils/prompt.go:111 #: internal/cliutils/prompt.go:111
msgid "Error prompting for choice of package" msgid "Error prompting for choice of package"
msgstr "" msgstr "Ошибка при запросе выбора пакета"
#: internal/cliutils/prompt.go:135 #: internal/cliutils/prompt.go:135
msgid "Choose which package to %s" msgid "Choose which package to %s"
msgstr "" msgstr "Выберите, какой пакет использовать для %s"
#: internal/cliutils/prompt.go:156 #: internal/cliutils/prompt.go:156
msgid "Choose which optional package(s) to install" msgid "Choose which optional package(s) to install"
msgstr "" msgstr "Выберите, какой дополнительный пакет(ы) следует установить"
#: internal/config/config.go:64 #: internal/config/config.go:64
msgid "Error opening config file, using defaults" msgid "Error opening config file, using defaults"
msgstr "" msgstr ""
"Ошибка при открытии конфигурационного файла, используются значения по "
"умолчанию"
#: internal/config/config.go:77 #: internal/config/config.go:77
msgid "Error decoding config file, using defaults" msgid "Error decoding config file, using defaults"
msgstr "" msgstr ""
"Ошибка при декодировании конфигурационного файла, используются значения по "
"умолчанию"
#: internal/config/config.go:89 #: internal/config/config.go:89
msgid "Unable to detect user config directory" msgid "Unable to detect user config directory"
msgstr "" msgstr "Не удалось обнаружить каталог конфигурации пользователя"
#: internal/config/config.go:97 #: internal/config/config.go:97
msgid "Unable to create ALR config directory" msgid "Unable to create ALR config directory"
msgstr "" msgstr "Не удалось создать каталог конфигурации ALR"
#: internal/config/config.go:106 #: internal/config/config.go:106
msgid "Unable to create ALR config file" msgid "Unable to create ALR config file"
msgstr "" msgstr "Не удалось создать конфигурационный файл ALR"
#: internal/config/config.go:112 #: internal/config/config.go:112
msgid "Error encoding default configuration" msgid "Error encoding default configuration"
msgstr "" msgstr "Ошибка кодирования конфигурации по умолчанию"
#: internal/config/config.go:121 #: internal/config/config.go:121
msgid "Unable to detect cache directory" msgid "Unable to detect cache directory"
msgstr "" msgstr "Не удалось обнаружить каталог кэша"
#: internal/config/config.go:131 #: internal/config/config.go:131
msgid "Unable to create repo cache directory" msgid "Unable to create repo cache directory"
msgstr "" msgstr "Не удалось создать каталог кэша репозитория"
#: internal/config/config.go:137 #: internal/config/config.go:137
msgid "Unable to create package cache directory" msgid "Unable to create package cache directory"
msgstr "" msgstr "Не удалось создать каталог кэша пакетов"
#: internal/config/lang.go:50 #: internal/config/lang.go:50
msgid "Error parsing system language" msgid "Error parsing system language"
msgstr "" msgstr "Ошибка при парсинге языка системы"
#: internal/db/db.go:131 #: internal/db/db.go:131
msgid "Database version mismatch; resetting" msgid "Database version mismatch; resetting"
msgstr "" msgstr "Несоответствие версий базы данных; сброс настроек"
#: internal/db/db.go:135 #: internal/db/db.go:135
msgid "" msgid ""
"Database version does not exist. Run alr fix if something isn't working." "Database version does not exist. Run alr fix if something isn't working."
msgstr "" msgstr ""
"Версия базы данных не существует. Запустите alr fix, если что-то не работает."
#: internal/db/db_legacy.go:101 #: internal/db/db_legacy.go:101
msgid "Error opening database" msgid "Error opening database"
msgstr "" msgstr "Ошибка при открытии базы данных"
#: internal/dl/dl.go:170 #: internal/dl/dl.go:170
msgid "Source can be updated, updating if required" msgid "Source can be updated, updating if required"
msgstr "" msgstr "Исходный код можно обновлять, обновляя при необходимости"
#: internal/dl/dl.go:201 #: internal/dl/dl.go:201
msgid "Source found in cache and linked to destination" msgid "Source found in cache and linked to destination"
msgstr "" msgstr "Источник найден в кэше и связан с пунктом назначения"
#: internal/dl/dl.go:208 #: internal/dl/dl.go:208
msgid "Source updated and linked to destination" msgid "Source updated and linked to destination"
msgstr "" msgstr "Источник обновлён и связан с пунктом назначения"
#: internal/dl/dl.go:222 #: internal/dl/dl.go:222
msgid "Downloading source" msgid "Downloading source"
msgstr "Скачивание источника" msgstr "Скачивание источника"
#: internal/logger/log.go:44 #: internal/logger/log.go:47
msgid "ERROR" msgid "ERROR"
msgstr "ОШИБКА" msgstr "ОШИБКА"
#: list.go:40 #: list.go:40
msgid "List ALR repo packages" msgid "List ALR repo packages"
msgstr "" msgstr "Список пакетов репозитория ALR"
#: list.go:91 #: list.go:91
msgid "Error listing installed packages" msgid "Error listing installed packages"
msgstr "" msgstr "Ошибка при составлении списка установленных пакетов"
#: main.go:45 #: main.go:45
msgid "Print the current ALR version and exit" msgid "Print the current ALR version and exit"
msgstr "" msgstr "Показать текущую версию ALR и выйти"
#: main.go:61 #: main.go:61
msgid "Arguments to be passed on to the package manager" msgid "Arguments to be passed on to the package manager"
msgstr "" msgstr "Аргументы, которые будут переданы менеджеру пакетов"
#: main.go:67 #: main.go:67
msgid "Enable interactive questions and prompts" msgid "Enable interactive questions and prompts"
msgstr "" msgstr "Включение интерактивных вопросов и запросов"
#: main.go:90 #: main.go:90
msgid "" msgid ""
"Running ALR as root is forbidden as it may cause catastrophic damage to your " "Running ALR as root is forbidden as it may cause catastrophic damage to your "
"system" "system"
msgstr "" msgstr ""
"Запуск ALR от имени root запрещён, так как это может привести к "
"катастрофическому повреждению вашей системы"
#: main.go:124 #: main.go:124
msgid "Error while running app" msgid "Error while running app"
msgstr "" msgstr "Ошибка при запуске приложения"
#: pkg/build/build.go:104 #: pkg/build/build.go:104
msgid "Failed to prompt user to view build script" msgid "Failed to prompt user to view build script"
msgstr "Не удалось предложить просмотреть скрипт" msgstr "Не удалось предложить пользователю просмотреть скрипт сборки"
#: pkg/build/build.go:108 #: pkg/build/build.go:108
msgid "Building package" msgid "Building package"
@@ -303,85 +309,97 @@ msgstr "Сборка пакета"
#: pkg/build/build.go:152 #: pkg/build/build.go:152
msgid "Downloading sources" msgid "Downloading sources"
msgstr "Скачивание файлов" msgstr "Скачивание источников"
#: pkg/build/build.go:164 #: pkg/build/build.go:164
msgid "Building package metadata" msgid "Building package metadata"
msgstr "" msgstr "Сборка метаданных пакета"
#: pkg/build/build.go:186 #: pkg/build/build.go:186
msgid "Compressing package" msgid "Compressing package"
msgstr "" msgstr "Сжатие пакета"
#: pkg/build/build.go:312 #: pkg/build/build.go:312
msgid "" msgid ""
"Your system's CPU architecture doesn't match this package. Do you want to " "Your system's CPU architecture doesn't match this package. Do you want to "
"build anyway?" "build anyway?"
msgstr "" msgstr ""
"Архитектура процессора вашей системы не соответствует этому пакету. Вы все "
"равно хотите выполнить сборку?"
#: pkg/build/build.go:323 #: pkg/build/build.go:323
msgid "This package is already installed" msgid "This package is already installed"
msgstr "" msgstr "Этот пакет уже установлен"
#: pkg/build/build.go:351 #: pkg/build/build.go:351
msgid "Installing build dependencies" msgid "Installing build dependencies"
msgstr "" msgstr "Установка зависимостей сборки"
#: pkg/build/build.go:393 #: pkg/build/build.go:393
msgid "Installing dependencies" msgid "Installing dependencies"
msgstr "" msgstr "Установка зависимостей"
#: pkg/build/build.go:435 #: pkg/build/build.go:439
msgid "Executing version()" msgid "Executing version()"
msgstr "" msgstr "Исполнение версия()"
#: pkg/build/build.go:460 #: pkg/build/build.go:459
msgid "Updating version"
msgstr "Обновление версии"
#: pkg/build/build.go:464
msgid "Executing prepare()" msgid "Executing prepare()"
msgstr "" msgstr "Исполнение prepare()"
#: pkg/build/build.go:470 #: pkg/build/build.go:474
msgid "Executing build()" msgid "Executing build()"
msgstr "" msgstr "Исполнение build()"
#: pkg/build/build.go:482 #: pkg/build/build.go:486
msgid "Executing package()" msgid "Executing package()"
msgstr "" msgstr "Исполнение package()"
#: pkg/build/build.go:557 #: pkg/build/build.go:524
msgid "AutoProv is not implemented for this package format, so it's skiped" msgid "Executing files()"
msgstr "" msgstr "Исполнение package()"
#: pkg/build/build.go:568 #: pkg/build/build.go:601
msgid "AutoReq is not implemented for this package format, so it's skiped" msgid "AutoProv is not implemented for this package format, so it's skipped"
msgstr "" msgstr ""
"AutoProv не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/build.go:653 #: pkg/build/build.go:612
msgid "AutoReq is not implemented for this package format, so it's skipped"
msgstr ""
"AutoReq не реализовано для этого формата пакета, поэтому будет пропущено"
#: pkg/build/build.go:719
msgid "Would you like to remove the build dependencies?" msgid "Would you like to remove the build dependencies?"
msgstr "" msgstr "Хотели бы вы удалить зависимости сборки?"
#: pkg/build/build.go:759 #: pkg/build/build.go:825
msgid "The checksums array must be the same length as sources" msgid "The checksums array must be the same length as sources"
msgstr "" msgstr "Массив контрольных сумм должен быть той же длины, что и источники"
#: pkg/build/findDeps.go:35 #: pkg/build/findDeps.go:35
msgid "Command not found on the system" msgid "Command not found on the system"
msgstr "" msgstr "Команда не найдена в системе"
#: pkg/build/findDeps.go:82 #: pkg/build/findDeps.go:82
msgid "Provided dependency found" msgid "Provided dependency found"
msgstr "" msgstr "Найденная предоставленная зависимость"
#: pkg/build/findDeps.go:89 #: pkg/build/findDeps.go:89
msgid "Required dependency found" msgid "Required dependency found"
msgstr "" msgstr "Найдена требуемая зависимость"
#: pkg/build/install.go:42 #: pkg/build/install.go:42
msgid "Error installing native packages" msgid "Error installing native packages"
msgstr "" msgstr "Ошибка при установке нативных пакетов"
#: pkg/build/install.go:79 #: pkg/build/install.go:79
msgid "Error installing package" msgid "Error installing package"
msgstr "" msgstr "Ошибка при установке пакета"
#: pkg/repos/pull.go:75 #: pkg/repos/pull.go:75
msgid "Pulling repository" msgid "Pulling repository"
@@ -389,67 +407,72 @@ msgstr "Скачивание репозитория"
#: pkg/repos/pull.go:99 #: pkg/repos/pull.go:99
msgid "Repository up to date" msgid "Repository up to date"
msgstr "Репозиторий уже обновлен" msgstr "Репозиторий уже обновлён"
#: pkg/repos/pull.go:156 #: pkg/repos/pull.go:156
msgid "Git repository does not appear to be a valid ALR repo" msgid "Git repository does not appear to be a valid ALR repo"
msgstr "" msgstr "Репозиторий Git не поддерживается репозиторием ALR"
#: pkg/repos/pull.go:172 #: pkg/repos/pull.go:172
msgid "" msgid ""
"ALR repo's minumum ALR version is greater than the current version. Try " "ALR repo's minimum ALR version is greater than the current version. Try "
"updating ALR if something doesn't work." "updating ALR if something doesn't work."
msgstr "" msgstr ""
"Минимальная версия ALR для ALR-репозитория выше текущей версии. Попробуйте "
"обновить ALR, если что-то не работает."
#: repo.go:41 #: repo.go:41
#, fuzzy
msgid "Add a new repository" msgid "Add a new repository"
msgstr "Скачивание репозитория" msgstr "Добавить новый репозиторий"
#: repo.go:48 #: repo.go:48
msgid "Name of the new repo" msgid "Name of the new repo"
msgstr "" msgstr "Название нового репозитория"
#: repo.go:54 #: repo.go:54
msgid "URL of the new repo" msgid "URL of the new repo"
msgstr "" msgstr "URL-адрес нового репозитория"
#: repo.go:79 repo.go:136 #: repo.go:79 repo.go:136
msgid "Error opening config file" msgid "Error opening config file"
msgstr "" msgstr "Ошибка при открытии конфигурационного файла"
#: repo.go:85 repo.go:142 #: repo.go:85 repo.go:142
msgid "Error encoding config" msgid "Error encoding config"
msgstr "" msgstr "Ошибка при кодировании конфигурации"
#: repo.go:103 #: repo.go:103
msgid "Remove an existing repository" msgid "Remove an existing repository"
msgstr "" msgstr "Удалить существующий репозиторий"
#: repo.go:110 #: repo.go:110
msgid "Name of the repo to be deleted" msgid "Name of the repo to be deleted"
msgstr "" msgstr "Название репозитория удалён"
#: repo.go:128 #: repo.go:128
msgid "Repo does not exist" msgid "Repo does not exist"
msgstr "" msgstr "Репозитория не существует"
#: repo.go:148 #: repo.go:148
msgid "Error removing repo directory" msgid "Error removing repo directory"
msgstr "" msgstr "Ошибка при удалении каталога репозитория"
#: repo.go:154 #: repo.go:154
msgid "Error removing packages from database" msgid "Error removing packages from database"
msgstr "" msgstr "Ошибка при удалении пакетов из базы данных"
#: repo.go:166 #: repo.go:166
msgid "Pull all repositories that have changed" msgid "Pull all repositories that have changed"
msgstr "" msgstr "Скачать все изменённые репозитории"
#: upgrade.go:47 #: upgrade.go:46
msgid "Upgrade all installed packages" msgid "Upgrade all installed packages"
msgstr "" msgstr "Обновить все установленные пакеты"
#: upgrade.go:83 #: upgrade.go:82
msgid "Error checking for updates" msgid "Error checking for updates"
msgstr "" msgstr "Ошибка при проверке обновлений"
#: upgrade.go:93
msgid "There is nothing to do."
msgstr "Здесь нечего делать."

View File

@@ -156,7 +156,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
return nil, nil, err return nil, nil, err
} }
err = executeFunctions(ctx, dec, dirs, vars) // Выполняем специальные функции funcOut, err := executeFunctions(ctx, dec, dirs, vars) // Выполняем специальные функции
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -165,7 +165,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
pkgFormat := getPkgFormat(opts.Manager) // Получаем формат пакета pkgFormat := getPkgFormat(opts.Manager) // Получаем формат пакета
pkgInfo, err := buildPkgMetadata(ctx, vars, dirs, pkgFormat, info, append(repoDeps, builtNames...)) // Собираем метаданные пакета pkgInfo, err := buildPkgMetadata(ctx, vars, dirs, pkgFormat, info, append(repoDeps, builtNames...), funcOut.Contents) // Собираем метаданные пакета
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -428,40 +428,44 @@ func buildALRDeps(ctx context.Context, opts types.BuildOpts, vars *types.BuildVa
return builtPaths, builtNames, repoDeps, nil return builtPaths, builtNames, repoDeps, nil
} }
type FunctionsOutput struct {
Contents *[]string
}
// Функция executeFunctions выполняет специальные функции ALR, такие как version(), prepare() и т.д. // Функция executeFunctions выполняет специальные функции ALR, такие как version(), prepare() и т.д.
func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Directories, vars *types.BuildVars) (err error) { func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Directories, vars *types.BuildVars) (*FunctionsOutput, error) {
version, ok := dec.GetFunc("version") version, ok := dec.GetFunc("version")
if ok { if ok {
slog.Info(gotext.Get("Executing version()")) slog.Info(gotext.Get("Executing version()"))
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
err = version( err := version(
ctx, ctx,
interp.Dir(dirs.SrcDir), interp.Dir(dirs.SrcDir),
interp.StdIO(os.Stdin, buf, os.Stderr), interp.StdIO(os.Stdin, buf, os.Stderr),
) )
if err != nil { if err != nil {
return err return nil, err
} }
newVer := strings.TrimSpace(buf.String()) newVer := strings.TrimSpace(buf.String())
err = setVersion(ctx, dec.Runner, newVer) err = setVersion(ctx, dec.Runner, newVer)
if err != nil { if err != nil {
return err return nil, err
} }
vars.Version = newVer vars.Version = newVer
slog.Info("Updating version", "new", newVer) slog.Info(gotext.Get("Updating version"), "new", newVer)
} }
prepare, ok := dec.GetFunc("prepare") prepare, ok := dec.GetFunc("prepare")
if ok { if ok {
slog.Info(gotext.Get("Executing prepare()")) slog.Info(gotext.Get("Executing prepare()"))
err = prepare(ctx, interp.Dir(dirs.SrcDir)) err := prepare(ctx, interp.Dir(dirs.SrcDir))
if err != nil { if err != nil {
return err return nil, err
} }
} }
@@ -469,9 +473,9 @@ func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Dire
if ok { if ok {
slog.Info(gotext.Get("Executing build()")) slog.Info(gotext.Get("Executing build()"))
err = build(ctx, interp.Dir(dirs.SrcDir)) err := build(ctx, interp.Dir(dirs.SrcDir))
if err != nil { if err != nil {
return err return nil, err
} }
} }
@@ -480,9 +484,9 @@ func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Dire
packageFn, ok := dec.GetFunc("package") packageFn, ok := dec.GetFunc("package")
if ok { if ok {
slog.Info(gotext.Get("Executing package()")) slog.Info(gotext.Get("Executing package()"))
err = packageFn(ctx, interp.Dir(dirs.SrcDir)) err := packageFn(ctx, interp.Dir(dirs.SrcDir))
if err != nil { if err != nil {
return err return nil, err
} }
} }
@@ -502,11 +506,51 @@ func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Dire
break break
} }
return nil output := &FunctionsOutput{}
files, ok := dec.GetFuncP("files", func(ctx context.Context, s *interp.Runner) error {
// It should be done via interp.RunnerOption,
// but due to the issues below, it cannot be done.
// - https://github.com/mvdan/sh/issues/962
// - https://github.com/mvdan/sh/issues/1125
script, err := syntax.NewParser().Parse(strings.NewReader("cd $pkgdir && shopt -s globstar"), "")
if err != nil {
return err
}
return s.Run(ctx, script)
})
if ok {
slog.Info(gotext.Get("Executing files()"))
buf := &bytes.Buffer{}
err := files(
ctx,
interp.Dir(dirs.PkgDir),
interp.StdIO(os.Stdin, buf, os.Stderr),
)
if err != nil {
return nil, err
}
contents := strings.Fields(strings.TrimSpace(buf.String()))
output.Contents = &contents
}
return output, nil
} }
// Функция buildPkgMetadata создает метаданные для пакета, который будет собран. // Функция buildPkgMetadata создает метаданные для пакета, который будет собран.
func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Directories, pkgFormat string, info *distro.OSRelease, deps []string) (*nfpm.Info, error) { func buildPkgMetadata(
ctx context.Context,
vars *types.BuildVars,
dirs types.Directories,
pkgFormat string,
info *distro.OSRelease,
deps []string,
preferedContents *[]string,
) (*nfpm.Info, error) {
pkgInfo := getBasePkgInfo(vars) pkgInfo := getBasePkgInfo(vars)
pkgInfo.Description = vars.Description pkgInfo.Description = vars.Description
pkgInfo.Platform = "linux" pkgInfo.Platform = "linux"
@@ -541,7 +585,7 @@ func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Dir
pkgInfo.Arch = "all" pkgInfo.Arch = "all"
} }
contents, err := buildContents(vars, dirs) contents, err := buildContents(vars, dirs, preferedContents)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -554,7 +598,7 @@ func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Dir
return nil, err return nil, err
} }
} else { } else {
slog.Info(gotext.Get("AutoProv is not implemented for this package format, so it's skiped")) slog.Info(gotext.Get("AutoProv is not implemented for this package format, so it's skipped"))
} }
} }
@@ -565,7 +609,7 @@ func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Dir
return nil, err return nil, err
} }
} else { } else {
slog.Info(gotext.Get("AutoReq is not implemented for this package format, so it's skiped")) slog.Info(gotext.Get("AutoReq is not implemented for this package format, so it's skipped"))
} }
} }
@@ -574,21 +618,27 @@ func buildPkgMetadata(ctx context.Context, vars *types.BuildVars, dirs types.Dir
// Функция buildContents создает секцию содержимого пакета, которая содержит файлы, // Функция buildContents создает секцию содержимого пакета, которая содержит файлы,
// которые будут включены в конечный пакет. // которые будут включены в конечный пакет.
func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Content, error) { func buildContents(vars *types.BuildVars, dirs types.Directories, preferedContents *[]string) ([]*files.Content, error) {
contents := []*files.Content{} contents := []*files.Content{}
err := filepath.Walk(dirs.PkgDir, func(path string, fi os.FileInfo, err error) error {
trimmed := strings.TrimPrefix(path, dirs.PkgDir) processPath := func(path, trimmed string, prefered bool) error {
fi, err := os.Lstat(path)
if err != nil {
return err
}
if fi.IsDir() { if fi.IsDir() {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
return err return err
} }
defer f.Close()
// Если директория пустая, пропускаем её if !prefered {
_, err = f.Readdirnames(1) _, err = f.Readdirnames(1)
if err != io.EOF { if err != io.EOF {
return nil return nil
}
} }
contents = append(contents, &files.Content{ contents = append(contents, &files.Content{
@@ -599,16 +649,14 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
MTime: fi.ModTime(), MTime: fi.ModTime(),
}, },
}) })
return nil
return f.Close()
} }
// Если файл является символической ссылкой, прорабатываем это
if fi.Mode()&os.ModeSymlink != 0 { if fi.Mode()&os.ModeSymlink != 0 {
link, err := os.Readlink(path) link, err := os.Readlink(path)
if err != nil { if err != nil {
return err return err
} }
// Удаляем pkgdir из пути символической ссылки
link = strings.TrimPrefix(link, dirs.PkgDir) link = strings.TrimPrefix(link, dirs.PkgDir)
contents = append(contents, &files.Content{ contents = append(contents, &files.Content{
@@ -620,10 +668,9 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
Mode: fi.Mode(), Mode: fi.Mode(),
}, },
}) })
return nil return nil
} }
// Обрабатываем обычные файлы
fileContent := &files.Content{ fileContent := &files.Content{
Source: path, Source: path,
Destination: trimmed, Destination: trimmed,
@@ -634,16 +681,35 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
}, },
} }
// Если файл должен быть сохранен, установите его тип как config|noreplace
if slices.Contains(vars.Backup, trimmed) { if slices.Contains(vars.Backup, trimmed) {
fileContent.Type = "config|noreplace" fileContent.Type = "config|noreplace"
} }
contents = append(contents, fileContent) contents = append(contents, fileContent)
return nil return nil
}) }
return contents, err
if preferedContents != nil {
for _, trimmed := range *preferedContents {
path := filepath.Join(dirs.PkgDir, trimmed)
if err := processPath(path, trimmed, true); err != nil {
return nil, err
}
}
} else {
err := filepath.Walk(dirs.PkgDir, func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
trimmed := strings.TrimPrefix(path, dirs.PkgDir)
return processPath(path, trimmed, false)
})
if err != nil {
return nil, err
}
}
return contents, nil
} }
// Функция removeBuildDeps спрашивает у пользователя, хочет ли он удалить зависимости, // Функция removeBuildDeps спрашивает у пользователя, хочет ли он удалить зависимости,

View File

@@ -169,7 +169,7 @@ func (rs *Repos) Pull(ctx context.Context, repos []types.Repo) error {
// to compare it to the repo version, so only compare versions with the "v". // to compare it to the repo version, so only compare versions with the "v".
if strings.HasPrefix(config.Version, "v") { if strings.HasPrefix(config.Version, "v") {
if vercmp.Compare(config.Version, repoCfg.Repo.MinVersion) == -1 { if vercmp.Compare(config.Version, repoCfg.Repo.MinVersion) == -1 {
slog.Warn(gotext.Get("ALR repo's minumum ALR version is greater than the current version. Try updating ALR if something doesn't work."), "repo", repo.Name) slog.Warn(gotext.Get("ALR repo's minimum ALR version is greater than the current version. Try updating ALR if something doesn't work."), "repo", repo.Name)
} }
} }
} }