Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
9d0047a11e
|
|||
06d81f1682
|
|||
7b8ab03779
|
|||
07cbcf5a0a
|
|||
da41ec3e84
|
|||
592fae25af
|
@@ -1,9 +0,0 @@
|
||||
FROM golang:latest
|
||||
|
||||
RUN apt install -y make curl python3 && go install gotest.tools/gotestsum@latest
|
||||
|
||||
COPY . /source
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
CMD ["make", "test"]
|
@@ -10,21 +10,27 @@ on: [push]
|
||||
|
||||
jobs:
|
||||
run_tests:
|
||||
name: Run goext test-suite
|
||||
name: Run goext test-suite
|
||||
runs-on: bfb-cicd-latest
|
||||
steps:
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build test docker
|
||||
id: build_docker
|
||||
run: echo "DOCKER_IMG_ID=$(docker build -q . -f .gitea/workflows/Dockerfile_tests || echo __err_build__)" >> $GITHUB_OUTPUT
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: '${{ gitea.workspace }}/go.mod'
|
||||
|
||||
- name: Setup packages
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: curl python3
|
||||
version: 1.0
|
||||
|
||||
- name: go version
|
||||
run: go version
|
||||
|
||||
- name: Run tests
|
||||
run: docker run --rm "${{ steps.build_docker.outputs.DOCKER_IMG_ID }}"
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: docker image rm "${{ steps.build_docker.outputs.DOCKER_IMG_ID }}"
|
||||
run: cd "${{ gitea.workspace }}" && make test
|
||||
|
||||
|
59
README.md
59
README.md
@@ -10,32 +10,33 @@ Potentially needs `export GOPRIVATE="gogs.mikescher.com"`
|
||||
|
||||
### Packages:
|
||||
|
||||
| Name | Maintainer | Description |
|
||||
|--------------|------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| langext | Mike | General uttility/helper functions, (everything thats missing from go standard library) |
|
||||
| mathext | Mike | Utility/Helper functions for math |
|
||||
| cryptext | Mike | Utility/Helper functions for encryption |
|
||||
| syncext | Mike | Utility/Helper funtions for multi-threading / mutex / channels |
|
||||
| dataext | Mike | Various useful data structures |
|
||||
| zipext | Mike | Utility for zip/gzip/tar etc |
|
||||
| reflectext | Mike | Utility for golagn reflection |
|
||||
| | | |
|
||||
| mongoext | Mike | Utility/Helper functions for mongodb |
|
||||
| cursortoken | Mike | MongoDB cursortoken implementation |
|
||||
| | | |
|
||||
| totpext | Mike | Implementation of TOTP (2-Factor-Auth) |
|
||||
| termext | Mike | Utilities for terminals (mostly color output) |
|
||||
| confext | Mike | Parses environment configuration into structs |
|
||||
| cmdext | Mike | Runner for external commands/processes |
|
||||
| | | |
|
||||
| sq | Mike | Utility functions for sql based databases |
|
||||
| tst | Mike | Utility functions for unit tests |
|
||||
| | | |
|
||||
| rfctime | Mike | Classes for time seriallization, with different marshallign method for mongo and json |
|
||||
| gojson | Mike | Same interface for marshalling/unmarshalling as go/json, except with proper serialization of null arrays/maps |
|
||||
| | | |
|
||||
| bfcodegen | Mike | Various codegen tools (run via go generate) |
|
||||
| | | |
|
||||
| rext | Mike | Regex Wrapper, wraps regexp with a better interface |
|
||||
| wmo | Mike | Mongo Wrapper, wraps mongodb with a better interface |
|
||||
| | | |
|
||||
| Name | Maintainer | Description |
|
||||
|-------------|------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| langext | Mike | General uttility/helper functions, (everything thats missing from go standard library) |
|
||||
| mathext | Mike | Utility/Helper functions for math |
|
||||
| cryptext | Mike | Utility/Helper functions for encryption |
|
||||
| syncext | Mike | Utility/Helper funtions for multi-threading / mutex / channels |
|
||||
| dataext | Mike | Various useful data structures |
|
||||
| zipext | Mike | Utility for zip/gzip/tar etc |
|
||||
| reflectext | Mike | Utility for golang reflection |
|
||||
| fsext | Mike | Utility for filesytem access |
|
||||
| | | |
|
||||
| mongoext | Mike | Utility/Helper functions for mongodb |
|
||||
| cursortoken | Mike | MongoDB cursortoken implementation |
|
||||
| | | |
|
||||
| totpext | Mike | Implementation of TOTP (2-Factor-Auth) |
|
||||
| termext | Mike | Utilities for terminals (mostly color output) |
|
||||
| confext | Mike | Parses environment configuration into structs |
|
||||
| cmdext | Mike | Runner for external commands/processes |
|
||||
| | | |
|
||||
| sq | Mike | Utility functions for sql based databases |
|
||||
| tst | Mike | Utility functions for unit tests |
|
||||
| | | |
|
||||
| rfctime | Mike | Classes for time seriallization, with different marshallign method for mongo and json |
|
||||
| gojson | Mike | Same interface for marshalling/unmarshalling as go/json, except with proper serialization of null arrays/maps |
|
||||
| | | |
|
||||
| bfcodegen | Mike | Various codegen tools (run via go generate) |
|
||||
| | | |
|
||||
| rext | Mike | Regex Wrapper, wraps regexp with a better interface |
|
||||
| wmo | Mike | Mongo Wrapper, wraps mongodb with a better interface |
|
||||
| | | |
|
365
bfcodegen/csid-generate.go
Normal file
365
bfcodegen/csid-generate.go
Normal file
@@ -0,0 +1,365 @@
|
||||
package bfcodegen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/cmdext"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/cryptext"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/rext"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CSIDDef struct {
|
||||
File string
|
||||
FileRelative string
|
||||
Name string
|
||||
Prefix string
|
||||
}
|
||||
|
||||
var rexCSIDPackage = rext.W(regexp.MustCompile(`^package\s+(?P<name>[A-Za-z0-9_]+)\s*$`))
|
||||
|
||||
var rexCSIDDef = rext.W(regexp.MustCompile(`^\s*type\s+(?P<name>[A-Za-z0-9_]+)\s+string\s*//\s*(@csid:type)\s+\[(?P<prefix>[A-Z0-9]{3})].*$`))
|
||||
|
||||
var rexCSIDChecksumConst = rext.W(regexp.MustCompile(`const ChecksumCharsetIDGenerator = "(?P<cs>[A-Za-z0-9_]*)"`))
|
||||
|
||||
func GenerateCharsetIDSpecs(sourceDir string, destFile string) error {
|
||||
|
||||
files, err := os.ReadDir(sourceDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oldChecksum := "N/A"
|
||||
if _, err := os.Stat(destFile); !os.IsNotExist(err) {
|
||||
content, err := os.ReadFile(destFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m, ok := rexCSIDChecksumConst.MatchFirst(string(content)); ok {
|
||||
oldChecksum = m.GroupByName("cs").Value()
|
||||
}
|
||||
}
|
||||
|
||||
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return v.Name() != path.Base(destFile) })
|
||||
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return strings.HasSuffix(v.Name(), ".go") })
|
||||
files = langext.ArrFilter(files, func(v os.DirEntry) bool { return !strings.HasSuffix(v.Name(), "_gen.go") })
|
||||
langext.SortBy(files, func(v os.DirEntry) string { return v.Name() })
|
||||
|
||||
newChecksumStr := goext.GoextVersion
|
||||
for _, f := range files {
|
||||
content, err := os.ReadFile(path.Join(sourceDir, f.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newChecksumStr += "\n" + f.Name() + "\t" + cryptext.BytesSha256(content)
|
||||
}
|
||||
|
||||
newChecksum := cryptext.BytesSha256([]byte(newChecksumStr))
|
||||
|
||||
if newChecksum != oldChecksum {
|
||||
fmt.Printf("[IDGenerate] Checksum has changed ( %s -> %s ), will generate new file\n\n", oldChecksum, newChecksum)
|
||||
} else {
|
||||
fmt.Printf("[IDGenerate] Checksum unchanged ( %s ), nothing to do\n", oldChecksum)
|
||||
return nil
|
||||
}
|
||||
|
||||
allIDs := make([]CSIDDef, 0)
|
||||
|
||||
pkgname := ""
|
||||
|
||||
for _, f := range files {
|
||||
fmt.Printf("========= %s =========\n\n", f.Name())
|
||||
fileIDs, pn, err := processCSIDFile(sourceDir, path.Join(sourceDir, f.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("\n")
|
||||
|
||||
allIDs = append(allIDs, fileIDs...)
|
||||
|
||||
if pn != "" {
|
||||
pkgname = pn
|
||||
}
|
||||
}
|
||||
|
||||
if pkgname == "" {
|
||||
return errors.New("no package name found in any file")
|
||||
}
|
||||
|
||||
err = os.WriteFile(destFile, []byte(fmtCSIDOutput(newChecksum, allIDs, pkgname)), 0o755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := cmdext.RunCommand("go", []string{"fmt", destFile}, langext.Ptr(2*time.Second))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if res.CommandTimedOut {
|
||||
fmt.Println(res.StdCombined)
|
||||
return errors.New("go fmt timed out")
|
||||
}
|
||||
if res.ExitCode != 0 {
|
||||
fmt.Println(res.StdCombined)
|
||||
return errors.New("go fmt did not succeed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func processCSIDFile(basedir string, fn string) ([]CSIDDef, string, error) {
|
||||
file, err := os.Open(fn)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
defer func() { _ = file.Close() }()
|
||||
|
||||
bin, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(bin), "\n")
|
||||
|
||||
ids := make([]CSIDDef, 0)
|
||||
|
||||
pkgname := ""
|
||||
|
||||
for i, line := range lines {
|
||||
if i == 0 && strings.HasPrefix(line, "// Code generated by") {
|
||||
break
|
||||
}
|
||||
|
||||
if match, ok := rexCSIDPackage.MatchFirst(line); i == 0 && ok {
|
||||
pkgname = match.GroupByName("name").Value()
|
||||
continue
|
||||
}
|
||||
|
||||
if match, ok := rexCSIDDef.MatchFirst(line); ok {
|
||||
|
||||
rfp, err := filepath.Rel(basedir, fn)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
def := CSIDDef{
|
||||
File: fn,
|
||||
FileRelative: rfp,
|
||||
Name: match.GroupByName("name").Value(),
|
||||
Prefix: match.GroupByName("prefix").Value(),
|
||||
}
|
||||
fmt.Printf("Found ID definition { '%s' }\n", def.Name)
|
||||
ids = append(ids, def)
|
||||
}
|
||||
}
|
||||
|
||||
return ids, pkgname, nil
|
||||
}
|
||||
|
||||
func fmtCSIDOutput(cs string, ids []CSIDDef, pkgname string) string {
|
||||
str := "// Code generated by id-generate.go DO NOT EDIT.\n"
|
||||
str += "\n"
|
||||
str += "package " + pkgname + "\n"
|
||||
str += "\n"
|
||||
|
||||
str += `import "crypto/rand"` + "\n"
|
||||
str += `import "fmt"` + "\n"
|
||||
str += `import "github.com/go-playground/validator/v10"` + "\n"
|
||||
str += `import "github.com/rs/zerolog/log"` + "\n"
|
||||
str += `import "gogs.mikescher.com/BlackForestBytes/goext/exerr"` + "\n"
|
||||
str += `import "gogs.mikescher.com/BlackForestBytes/goext/langext"` + "\n"
|
||||
str += `import "gogs.mikescher.com/BlackForestBytes/goext/rext"` + "\n"
|
||||
str += `import "math/big"` + "\n"
|
||||
str += `import "reflect"` + "\n"
|
||||
str += `import "regexp"` + "\n"
|
||||
str += `import "strings"` + "\n"
|
||||
str += "\n"
|
||||
|
||||
str += "const ChecksumCharsetIDGenerator = \"" + cs + "\" // GoExtVersion: " + goext.GoextVersion + "\n"
|
||||
str += "\n"
|
||||
|
||||
str += "const idlen = 24\n"
|
||||
str += "\n"
|
||||
str += "const checklen = 1\n"
|
||||
str += "\n"
|
||||
str += `const idCharset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"` + "\n"
|
||||
str += "const idCharsetLen = len(idCharset)\n"
|
||||
str += "\n"
|
||||
str += "var charSetReverseMap = generateCharsetMap()\n"
|
||||
str += "\n"
|
||||
str += "const (\n"
|
||||
for _, iddef := range ids {
|
||||
str += " prefix" + iddef.Name + " = \"" + iddef.Prefix + "\"" + "\n"
|
||||
}
|
||||
str += ")\n"
|
||||
str += "\n"
|
||||
str += "var (\n"
|
||||
for _, iddef := range ids {
|
||||
str += " regex" + iddef.Name + " = generateRegex(prefix" + iddef.Name + ")" + "\n"
|
||||
}
|
||||
str += ")\n"
|
||||
str += "\n"
|
||||
str += "func generateRegex(prefix string) rext.Regex {\n"
|
||||
str += " return rext.W(regexp.MustCompile(fmt.Sprintf(\"^%s[%s]{%d}[%s]{%d}$\", prefix, idCharset, idlen-len(prefix)-checklen, idCharset, checklen)))\n"
|
||||
str += "}\n"
|
||||
str += "\n"
|
||||
|
||||
str += `func generateCharsetMap() []int {` + "\n"
|
||||
str += ` result := make([]int, 128)` + "\n"
|
||||
str += ` for i := 0; i < len(result); i++ {` + "\n"
|
||||
str += ` result[i] = -1` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` for idx, chr := range idCharset {` + "\n"
|
||||
str += ` result[int(chr)] = idx` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` return result` + "\n"
|
||||
str += `}` + "\n"
|
||||
str += "\n"
|
||||
str += `func generateID(prefix string) string {` + "\n"
|
||||
str += ` k := ""` + "\n"
|
||||
str += ` max := big.NewInt(int64(idCharsetLen))` + "\n"
|
||||
str += ` checksum := 0` + "\n"
|
||||
str += ` for i := 0; i < idlen-len(prefix)-checklen; i++ {` + "\n"
|
||||
str += ` v, err := rand.Int(rand.Reader, max)` + "\n"
|
||||
str += ` if err != nil {` + "\n"
|
||||
str += ` panic(err)` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` v64 := v.Int64()` + "\n"
|
||||
str += ` k += string(idCharset[v64])` + "\n"
|
||||
str += ` checksum = (checksum + int(v64)) % (idCharsetLen)` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` checkstr := string(idCharset[checksum%idCharsetLen])` + "\n"
|
||||
str += ` return prefix + k + checkstr` + "\n"
|
||||
str += `}` + "\n"
|
||||
str += "\n"
|
||||
str += `func validateID(prefix string, value string) error {` + "\n"
|
||||
str += ` if len(value) != idlen {` + "\n"
|
||||
str += ` return exerr.New(exerr.TypeInvalidCSID, "id has the wrong length").Str("value", value).Build()` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` if !strings.HasPrefix(value, prefix) {` + "\n"
|
||||
str += ` return exerr.New(exerr.TypeInvalidCSID, "id is missing the correct prefix").Str("value", value).Str("prefix", prefix).Build()` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` checksum := 0` + "\n"
|
||||
str += ` for i := len(prefix); i < len(value)-checklen; i++ {` + "\n"
|
||||
str += ` ichr := int(value[i])` + "\n"
|
||||
str += ` if ichr < 0 || ichr >= len(charSetReverseMap) || charSetReverseMap[ichr] == -1 {` + "\n"
|
||||
str += ` return exerr.New(exerr.TypeInvalidCSID, "id contains invalid characters").Str("value", value).Build()` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` checksum = (checksum + charSetReverseMap[ichr]) % (idCharsetLen)` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` checkstr := string(idCharset[checksum%idCharsetLen])` + "\n"
|
||||
str += "\n"
|
||||
str += ` if !strings.HasSuffix(value, checkstr) {` + "\n"
|
||||
str += ` return exerr.New(exerr.ErrInvalidCSID, "id checkstring is invalid").Str("value", value).Str("checkstr", checkstr).Build()` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` return nil` + "\n"
|
||||
str += `}` + "\n"
|
||||
str += "\n"
|
||||
str += `func getRawData(prefix string, value string) string {` + "\n"
|
||||
str += ` if len(value) != idlen {` + "\n"
|
||||
str += ` return ""` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` return value[len(prefix) : idlen-checklen]` + "\n"
|
||||
str += `}` + "\n"
|
||||
str += "\n"
|
||||
str += `func getCheckString(prefix string, value string) string {` + "\n"
|
||||
str += ` if len(value) != idlen {` + "\n"
|
||||
str += ` return ""` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += ` return value[idlen-checklen:]` + "\n"
|
||||
str += `}` + "\n"
|
||||
str += "\n"
|
||||
str += `func ValidateEntityID(vfl validator.FieldLevel) bool {` + "\n"
|
||||
str += ` if !vfl.Field().CanInterface() {` + "\n"
|
||||
str += ` log.Error().Msgf("Failed to validate EntityID (cannot interface ?!?)")` + "\n"
|
||||
str += ` return false` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` ifvalue := vfl.Field().Interface()` + "\n"
|
||||
str += "\n"
|
||||
str += ` if value1, ok := ifvalue.(EntityID); ok {` + "\n"
|
||||
str += "\n"
|
||||
str += ` if vfl.Field().Type().Kind() == reflect.Pointer && langext.IsNil(value1) {` + "\n"
|
||||
str += ` return true` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` if err := value1.Valid(); err != nil {` + "\n"
|
||||
str += ` log.Debug().Msgf("Failed to validate EntityID '%s' (%s)", value1.String(), err.Error())` + "\n"
|
||||
str += ` return false` + "\n"
|
||||
str += ` } else {` + "\n"
|
||||
str += ` return true` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += "\n"
|
||||
str += ` } else {` + "\n"
|
||||
str += ` log.Error().Msgf("Failed to validate EntityID (wrong type: %T)", ifvalue)` + "\n"
|
||||
str += ` return false` + "\n"
|
||||
str += ` }` + "\n"
|
||||
str += `}` + "\n"
|
||||
str += "\n"
|
||||
|
||||
for _, iddef := range ids {
|
||||
|
||||
str += "// ================================ " + iddef.Name + " (" + iddef.FileRelative + ") ================================" + "\n"
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func New" + iddef.Name + "() " + iddef.Name + " {" + "\n"
|
||||
str += " return " + iddef.Name + "(generateID(prefix" + iddef.Name + "))" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func (id " + iddef.Name + ") Valid() error {" + "\n"
|
||||
str += " return validateID(prefix" + iddef.Name + ", string(id))" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func (i " + iddef.Name + ") String() string {" + "\n"
|
||||
str += " return string(i)" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func (i " + iddef.Name + ") Prefix() string {" + "\n"
|
||||
str += " return prefix" + iddef.Name + "" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func (id " + iddef.Name + ") Raw() string {" + "\n"
|
||||
str += " return getRawData(prefix" + iddef.Name + ", string(id))" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func (id " + iddef.Name + ") CheckString() string {" + "\n"
|
||||
str += " return getCheckString(prefix" + iddef.Name + ", string(id))" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
str += "func (id " + iddef.Name + ") Regex() rext.Regex {" + "\n"
|
||||
str += " return regex" + iddef.Name + "" + "\n"
|
||||
str += "}" + "\n"
|
||||
|
||||
str += "" + "\n"
|
||||
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
@@ -35,7 +35,7 @@ var rexEnumPackage = rext.W(regexp.MustCompile(`^package\s+(?P<name>[A-Za-z0-9_]
|
||||
|
||||
var rexEnumDef = rext.W(regexp.MustCompile(`^\s*type\s+(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*//\s*(@enum:type).*$`))
|
||||
|
||||
var rexEnumValueDef = rext.W(regexp.MustCompile(`^\s*(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*=\s*(?P<value>("[A-Za-z0-9_:]+"|[0-9]+))\s*(//(?P<descr>.*))?.*$`))
|
||||
var rexEnumValueDef = rext.W(regexp.MustCompile(`^\s*(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*=\s*(?P<value>("[A-Za-z0-9_:\s]+"|[0-9]+))\s*(//(?P<descr>.*))?.*$`))
|
||||
|
||||
var rexEnumChecksumConst = rext.W(regexp.MustCompile(`const ChecksumEnumGenerator = "(?P<cs>[A-Za-z0-9_]*)"`))
|
||||
|
||||
|
@@ -41,12 +41,12 @@ func processEnvOverrides(rval reflect.Value, delim string, prefix string) error
|
||||
continue
|
||||
}
|
||||
|
||||
if rvfield.Kind() == reflect.Struct {
|
||||
envkey, found := rsfield.Tag.Lookup("env")
|
||||
if !found || envkey == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
envkey, found := rsfield.Tag.Lookup("env")
|
||||
if !found || envkey == "-" {
|
||||
continue
|
||||
}
|
||||
if rvfield.Kind() == reflect.Struct && rvfield.Type() != reflect.TypeOf(time.UnixMilli(0)) {
|
||||
|
||||
subPrefix := prefix
|
||||
if envkey != "" {
|
||||
@@ -57,10 +57,7 @@ func processEnvOverrides(rval reflect.Value, delim string, prefix string) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
envkey := rsfield.Tag.Get("env")
|
||||
if envkey == "" || envkey == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@@ -56,6 +56,7 @@ var (
|
||||
TypeBindFailHeader = NewType("BINDFAIL_HEADER", langext.Ptr(400))
|
||||
|
||||
TypeMarshalEntityID = NewType("MARSHAL_ENTITY_ID", langext.Ptr(400))
|
||||
TypeInvalidCSID = NewType("INVALID_CSID", langext.Ptr(400))
|
||||
|
||||
TypeUnauthorized = NewType("UNAUTHORIZED", langext.Ptr(401))
|
||||
TypeAuthFailed = NewType("AUTH_FAILED", langext.Ptr(401))
|
||||
|
@@ -30,7 +30,7 @@ type ExErr struct {
|
||||
}
|
||||
|
||||
func (ee *ExErr) Error() string {
|
||||
return ee.Message
|
||||
return ee.RecursiveMessage()
|
||||
}
|
||||
|
||||
// Unwrap must be implemented so that some error.XXX methods work
|
||||
|
36
fsext/exists.go
Normal file
36
fsext/exists.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package fsext
|
||||
|
||||
import "os"
|
||||
|
||||
func PathExists(fp string) (bool, error) {
|
||||
_, err := os.Stat(fp)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func FileExists(fp string) (bool, error) {
|
||||
stat, err := os.Stat(fp)
|
||||
if err == nil {
|
||||
return !stat.IsDir(), nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
func DirectoryExists(fp string) (bool, error) {
|
||||
stat, err := os.Stat(fp)
|
||||
if err == nil {
|
||||
return stat.IsDir(), nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
8
go.mod
8
go.mod
@@ -17,7 +17,7 @@ require (
|
||||
github.com/bytedance/sonic v1.10.2 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
@@ -25,11 +25,11 @@ require (
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
@@ -41,7 +41,7 @@ require (
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
|
||||
golang.org/x/arch v0.5.0 // indirect
|
||||
golang.org/x/net v0.16.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sync v0.4.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
|
10
go.sum
10
go.sum
@@ -14,6 +14,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
@@ -45,6 +47,10 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g=
|
||||
github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
@@ -58,6 +64,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -121,6 +129,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
|
||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
|
@@ -1,5 +1,5 @@
|
||||
package goext
|
||||
|
||||
const GoextVersion = "0.0.285"
|
||||
const GoextVersion = "0.0.290"
|
||||
|
||||
const GoextVersionTimestamp = "2023-10-09T15:25:30+0200"
|
||||
const GoextVersionTimestamp = "2023-10-26T13:01:58+0200"
|
||||
|
Reference in New Issue
Block a user