diff --git a/.deb.yaml b/.deb.yaml index bd985c7..e492fbf 100755 --- a/.deb.yaml +++ b/.deb.yaml @@ -7,7 +7,7 @@ packages: - amd64 - arm64 maintainer: The OSSPkg Team - homepage: https://deb.osspkg.com/ + homepage: https://dl.osspkg.com/ description: - Debian package builder section: web @@ -16,3 +16,5 @@ packages: build: goppy build --arch=%arch% data: usr/bin/deb-builder: build/deb-builder_%arch% + ignore: + - .git/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a66a0cf..3ec7abe 100755 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: [ '1.25' ] + go: [ '1.26' ] steps: - uses: actions/checkout@v3 diff --git a/Makefile b/Makefile index 89a3894..64aa070 100755 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: install install: - go install go.osspkg.com/goppy/v2/cmd/goppy@latest + go install go.osspkg.com/goppy/v3/cmd/goppy@latest .PHONY: setup setup: diff --git a/README.md b/README.md index eecddc0..8033748 100755 --- a/README.md +++ b/README.md @@ -52,6 +52,9 @@ data: # A list of files that will be packaged during the build, where the file i demo/file: 'c:write file content' demo/dir: 'd:/build' demo/dir1: 'e:/build/.*.(go|js)' +ignore: + - .git/ + - .gitignore ``` data prefix: diff --git a/cmd/deb-builder/main.go b/cmd/deb-builder/main.go index 5ac01f1..9061704 100755 --- a/cmd/deb-builder/main.go +++ b/cmd/deb-builder/main.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/go.mod b/go.mod index 4e5aa2e..8edaf2e 100755 --- a/go.mod +++ b/go.mod @@ -1,13 +1,13 @@ module github.com/osspkg/deb-builder -go 1.25.3 +go 1.26.3 require ( github.com/stretchr/testify v1.11.1 go.osspkg.com/archives v1.1.0 go.osspkg.com/console v0.3.3 - go.osspkg.com/encrypt v0.5.1 - go.osspkg.com/ioutils v0.7.3 + go.osspkg.com/encrypt v0.5.3 + go.osspkg.com/ioutils v0.7.4 gopkg.in/yaml.v3 v3.0.1 ) @@ -15,5 +15,5 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.osspkg.com/errors v0.4.0 // indirect - golang.org/x/crypto v0.43.0 // indirect + golang.org/x/crypto v0.53.0 // indirect ) diff --git a/go.sum b/go.sum index 4f4f871..9392246 100644 --- a/go.sum +++ b/go.sum @@ -10,14 +10,14 @@ go.osspkg.com/casecheck v0.3.0 h1:x15blEszElbrHrEH5H02JIIhGIg/lGZzIt1kQlD3pwM= go.osspkg.com/casecheck v0.3.0/go.mod h1:TRFXDMFJEOtnlp3ET2Hix3osbxwPWhvaiT/HfD3+gBA= go.osspkg.com/console v0.3.3 h1:UB/pPoPsgWbyNFix8pEMQHbsXdMv/UK/dgsbRknCH2A= go.osspkg.com/console v0.3.3/go.mod h1:IknBCliH6mX/ogHa6wbycnGDFYixCGH3WuNc5W5tQe8= -go.osspkg.com/encrypt v0.5.1 h1:DaYhos4Si9Mzi1LBW2mkin7TPQGkKvlwI+aq/a8Z6ko= -go.osspkg.com/encrypt v0.5.1/go.mod h1:mGDe5PTd+i6cntpiOaesAaD7498ypqPbbMPbI89PK4c= +go.osspkg.com/encrypt v0.5.3 h1:/DnWw1zVETxErZa0UD0Xwh7LSPWDHptLvayPSdEAaY4= +go.osspkg.com/encrypt v0.5.3/go.mod h1:xqTL2V0utimVtrL4i86czYe4llQzwDMFx5NWF8pJmxk= go.osspkg.com/errors v0.4.0 h1:E17+WyUzTXEHCTxGm8lOMPOOojzHG1lsOuQtTVGoATQ= go.osspkg.com/errors v0.4.0/go.mod h1:s75ZovPemYtrCtRPVsbQNq9MgMbmLMK1NEypr+uwjXI= -go.osspkg.com/ioutils v0.7.3 h1:QF+Ra0bHoU3MGMGH5PGdV2lRLq1rWPdv/OB+v5UTjkI= -go.osspkg.com/ioutils v0.7.3/go.mod h1:RO/43IM//Wq8RnLvEzivDAuM37mnLW3eWxTCVmkUaY4= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +go.osspkg.com/ioutils v0.7.4 h1:Z8Y4jYYmLGWcvHZMLjbai+s48GmHxjMuepsxZcjF5X4= +go.osspkg.com/ioutils v0.7.4/go.mod h1:pPIsTL1w1+ESrGTeHDCd6cKsujeWvschxGGP5FqrAqc= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/commands/build.go b/internal/commands/build.go index 3b7505f..b2bcc9f 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ @@ -7,7 +7,6 @@ package commands import ( "fmt" - iofs "io/fs" "os" "path/filepath" "regexp" @@ -35,6 +34,8 @@ func Build() console.CommandGetter { flag.Bool("no-revision", "Don`t build revision deb package") }) setter.ExecFunc(func(_ []string, debConf, baseDir, tmpDir string, noRevision bool) { + curr := fs.CurrentDir() + configs, err := config.Detect(debConf) console.FatalIfErr(err, "deb config not found") @@ -48,6 +49,11 @@ func Build() console.CommandGetter { console.FatalIfErr(os.MkdirAll(storeDir, 0755), "creating storage directory") exec.Build(conf.Control.Build, conf.Version, conf.Architecture, func(arch string, replacer exec.Replacer) { + defer func() { + if r := recover(); r != nil { + console.Fatalf("build failed: %v", r) + } + }() // check file version @@ -71,92 +77,69 @@ func Build() console.CommandGetter { err1 error ) - switch true { - case strings.HasPrefix(src, "+"): - f, h, err1 = tg.WriteData(dst, []byte(src)[1:]) - console.FatalIfErr(err1, "write %s to data.tar.gz", src) - md5sum.Add(f, h) - console.Infof("Add: %s", dst) + if prefix, ok := utils.MultiPrefix(src, "+", "c:"); ok { - case strings.HasPrefix(src, "c:"): - f, h, err1 = tg.WriteData(dst, []byte(src)[2:]) + f, h, err1 = tg.WriteData(dst, []byte(utils.MustValueAfterPrefix(src, prefix))) console.FatalIfErr(err1, "write %s to data.tar.gz", src) + md5sum.Add(f, h) console.Infof("Add: %s", dst) - case strings.HasPrefix(src, "~"): - fullpath, err0 := filepath.Abs(src[1:]) - console.FatalIfErr(err0, "get full path for %s", src[1:]) + } else if prefix, ok := utils.MultiPrefix(src, "~", "d:"); ok { - err2 := filepath.Walk(fullpath, func(path string, info iofs.FileInfo, e error) error { - if e != nil { - return e - } - if info.IsDir() { - return nil - } - walkedFile := strings.ReplaceAll(path, fullpath, dst) - ff, hh, ee := tg.WriteFile(path, walkedFile) - console.FatalIfErr(ee, "write %s to data.tar.gz", src) - md5sum.Add(ff, hh) - console.Infof("Add: %s", walkedFile) - return nil - }) - console.FatalIfErr(err2, "write %s to data.tar.gz", src) + srcPath := utils.MustValueAfterPrefix(src, prefix) + fullpath, err0 := filepath.Abs(srcPath) + console.FatalIfErr(err0, "get full path for %s", srcPath) - case strings.HasPrefix(src, "d:"): - fullpath, err0 := filepath.Abs(src[2:]) - console.FatalIfErr(err0, "get full path for %s", src[2:]) + if !strings.HasPrefix(fullpath, curr) { + console.Fatalf("full path for %s is incorrect", srcPath) + } - err2 := filepath.Walk(fullpath, func(path string, info iofs.FileInfo, e error) error { - if e != nil { - return e - } - if info.IsDir() { - return nil - } + err2 := utils.DirWalk(fullpath, func(path string) error { walkedFile := strings.ReplaceAll(path, fullpath, dst) + ff, hh, ee := tg.WriteFile(path, walkedFile) console.FatalIfErr(ee, "write %s to data.tar.gz", src) + md5sum.Add(ff, hh) console.Infof("Add: %s", walkedFile) + return nil - }) + }, conf.Ignore...) console.FatalIfErr(err2, "write %s to data.tar.gz", src) - case strings.HasPrefix(src, "e:"): + } else if _, ok := utils.MultiPrefix(src, "e:"); ok { + rex, err0 := regexp.Compile(`(?Us)^` + src[2:] + `$`) console.FatalIfErr(err0, "build regexp `%s`", src[2:]) - fullpath := fs.CurrentDir() - err2 := filepath.Walk(fullpath, func(path string, info iofs.FileInfo, e error) error { - if e != nil { - return e - } - if info.IsDir() { - return nil - } - - if !rex.MatchString(strings.TrimPrefix(path, fullpath)) { + err2 := utils.DirWalk(curr, func(path string) error { + if !rex.MatchString(strings.TrimPrefix(path, curr)) { return nil } - walkedFile := strings.ReplaceAll(path, fullpath, dst) + walkedFile := strings.ReplaceAll(path, curr, dst) ff, hh, ee := tg.WriteFile(path, walkedFile) console.FatalIfErr(ee, "write %s to data.tar.gz", src) + md5sum.Add(ff, hh) console.Infof("Add: %s", walkedFile) + return nil - }) + }, conf.Ignore...) console.FatalIfErr(err2, "write %s to data.tar.gz", src) - default: + } else { + f, h, err1 = tg.WriteFile(src, dst) console.FatalIfErr(err1, "write %s to data.tar.gz", src) + md5sum.Add(f, h) console.Infof("Add: %s", dst) + } } + console.FatalIfErr(tg.Close(), "close data.tar.gz") md5file, err := md5sum.Save(buildDir) @@ -204,6 +187,7 @@ func Build() console.CommandGetter { console.FatalIfErr(deb.Close(), "close file %s", debFile) console.Infof("Result: %s", debFile) + }) } diff --git a/internal/commands/config.go b/internal/commands/config.go index 11f7a0a..747a340 100644 --- a/internal/commands/config.go +++ b/internal/commands/config.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/commands/pgp.go b/internal/commands/pgp.go index 49d9df3..6524e44 100644 --- a/internal/commands/pgp.go +++ b/internal/commands/pgp.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/internal/commands/release.go b/internal/commands/release.go index 5f0791d..86545e2 100644 --- a/internal/commands/release.go +++ b/internal/commands/release.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/archive/gzwriter.go b/pkg/archive/gzwriter.go index 8bc3707..5a31b5e 100644 --- a/pkg/archive/gzwriter.go +++ b/pkg/archive/gzwriter.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/archive/reader.go b/pkg/archive/reader.go index 9670267..16ce9a0 100644 --- a/pkg/archive/reader.go +++ b/pkg/archive/reader.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/archive/writer.go b/pkg/archive/writer.go index 2157705..c05f910 100644 --- a/pkg/archive/writer.go +++ b/pkg/archive/writer.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/buffer/buffer.go b/pkg/buffer/buffer.go index dcfcccc..da5cdab 100644 --- a/pkg/buffer/buffer.go +++ b/pkg/buffer/buffer.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/config/config.go b/pkg/config/config.go index 64e3a1f..28e3252 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ @@ -41,6 +41,7 @@ type ( Priority string `yaml:"priority"` Control Control `yaml:"control"` Data map[string]string `yaml:"data"` + Ignore []string `yaml:"ignore"` } Control struct { Depends []string `yaml:"depends"` @@ -125,6 +126,10 @@ func Create() error { "etc/" + filepath.Base(dir) + "/config.yaml": "configs/config.yaml", "var/log/" + filepath.Base(dir) + ".log": "+Write contents of file here after '+'", }, + Ignore: []string{ + ".git/", + ".gitignore", + }, } cfg := Multi{ diff --git a/pkg/control/control.go b/pkg/control/control.go index 794d16b..06b5a83 100644 --- a/pkg/control/control.go +++ b/pkg/control/control.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/control/controlpkg.go b/pkg/control/controlpkg.go index d8f417a..967cbf9 100644 --- a/pkg/control/controlpkg.go +++ b/pkg/control/controlpkg.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/control/md5sums.go b/pkg/control/md5sums.go index ee93a2f..0639080 100644 --- a/pkg/control/md5sums.go +++ b/pkg/control/md5sums.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/control/other.go b/pkg/control/other.go index 7dbdc28..14140fc 100644 --- a/pkg/control/other.go +++ b/pkg/control/other.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/exec/common.go b/pkg/exec/common.go index ec8d80b..025cd46 100644 --- a/pkg/exec/common.go +++ b/pkg/exec/common.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/hash/hash.go b/pkg/hash/hash.go index ad98684..d0b4d55 100644 --- a/pkg/hash/hash.go +++ b/pkg/hash/hash.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/packages/codec.go b/pkg/packages/codec.go index 330bf8e..7a22be0 100644 --- a/pkg/packages/codec.go +++ b/pkg/packages/codec.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/packages/name.go b/pkg/packages/name.go index da6add8..7b93ab2 100644 --- a/pkg/packages/name.go +++ b/pkg/packages/name.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/packages/packages.go b/pkg/packages/packages.go index 6ecdef0..7c2ed6e 100644 --- a/pkg/packages/packages.go +++ b/pkg/packages/packages.go @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ diff --git a/pkg/utils/common.go b/pkg/utils/common.go index 6c471fb..6490c36 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -1,11 +1,14 @@ /* - * Copyright (c) 2021-2025 Mikhail Knyazhev . All rights reserved. + * Copyright (c) 2021-2026 Mikhail Knyazhev . All rights reserved. * Use of this source code is governed by a BSD-3-Clause license that can be found in the LICENSE file. */ package utils import ( + "fmt" + "io" + "io/fs" "os" "path/filepath" "strings" @@ -41,3 +44,70 @@ func FileStat(filename string, callFunc func(fi os.FileInfo)) { callFunc(info) } } + +func MultiPrefix(value string, prefixes ...string) (string, bool) { + for _, prefix := range prefixes { + if strings.HasPrefix(value, prefix) { + return prefix, true + } + } + return "", false +} + +func MustValueAfterPrefix(value, prefix string) string { + indx := strings.Index(value, prefix) + if indx == -1 { + panic(fmt.Sprintf("value does not have prefix `%s`: %s", prefix, value)) + } + return value[indx+len(prefix):] +} + +func DirWalk(path string, walkFunc func(path string) error, ignore ...string) error { + return filepath.Walk(path, func(path string, info fs.FileInfo, e error) error { + if e != nil { + return e + } + if info.IsDir() { + return nil + } + + for _, ign := range ignore { + if strings.Contains(path, ign) { + return nil + } + } + + return walkFunc(path) + }) +} + +func RootDirWalk(path string, walkFunc func(path string, r io.Reader) error, ignore ...string) error { + r, err := os.OpenRoot(path) + if err != nil { + return fmt.Errorf("open root path %s: %w", path, err) + } + defer r.Close() //nolint:errcheck + + return fs.WalkDir(r.FS(), ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.Type().IsRegular() { + return nil + } + + for _, ign := range ignore { + if strings.Contains(path, ign) { + return nil + } + } + + f, err := r.Open(path) + if err != nil { + return fmt.Errorf("open %s: %w", path, err) + } + defer f.Close() //nolint:errcheck + + return walkFunc(path, f) + }) +} diff --git a/pkg/utils/common_test.go b/pkg/utils/common_test.go new file mode 100644 index 0000000..ef81a8f --- /dev/null +++ b/pkg/utils/common_test.go @@ -0,0 +1,50 @@ +package utils + +import ( + "testing" +) + +func TestUnit_MustValueAfterPrefix(t *testing.T) { + tests := []struct { + name string + value string + prefix string + want string + panic bool // ожидается ли паника + }{ + // успешные случаи + {"префикс в начале", "hello world", "hello", " world", false}, + {"префикс в середине", "xxhello world", "hello", " world", false}, + {"пустой префикс", "value", "", "value", false}, + {"оба параметра пусты", "", "", "", false}, + {"возврат пустой строки (префикс равен значению)", "whole", "whole", "", false}, + {"юникод", "привет мир", "привет", " мир", false}, + {"несколько вхождений – берётся первое", "a_b_c", "_", "b_c", false}, + {"префикс, который встречается несколько раз", "prefixprefixsuffix", "prefix", "prefixsuffix", false}, + + // случаи с паникой + {"префикс не найден", "value", "missing", "", true}, + {"пустое значение и непустой префикс", "", "x", "", true}, + {"префикс длиннее значения", "abc", "abcdef", "", true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.panic { + defer func() { + if r := recover(); r == nil { + t.Error("ожидалась паника, но функция завершилась без паники") + } + }() + _ = MustValueAfterPrefix(tt.value, tt.prefix) + t.Error("ожидалась паника, но функция вернула управление") + return + } + + got := MustValueAfterPrefix(tt.value, tt.prefix) + if got != tt.want { + t.Errorf("MustValueAfterPrefix(%q, %q) = %q, want %q", tt.value, tt.prefix, got, tt.want) + } + }) + } +}