mirror of
https://github.com/go-gitea/gitea.git
synced 2025-06-15 06:02:19 +02:00
Refactor embedded assets and drop unnecessary dependencies (#34692)
Benefits: 1. smaller binary size (reduces more than 1MB) 2. better control of the assets details 3. fewer unmaintained dependencies 4. faster startup if the assets are not needed 5. won't hang up editors when open "bindata.go" by accident
This commit is contained in:
parent
18bafcc378
commit
65986f423f
12
.gitignore
vendored
12
.gitignore
vendored
@ -42,14 +42,10 @@ _testmain.go
|
||||
coverage.all
|
||||
cpu.out
|
||||
|
||||
/modules/migration/bindata.go
|
||||
/modules/migration/bindata.go.hash
|
||||
/modules/options/bindata.go
|
||||
/modules/options/bindata.go.hash
|
||||
/modules/public/bindata.go
|
||||
/modules/public/bindata.go.hash
|
||||
/modules/templates/bindata.go
|
||||
/modules/templates/bindata.go.hash
|
||||
/modules/migration/bindata.*
|
||||
/modules/options/bindata.*
|
||||
/modules/public/bindata.*
|
||||
/modules/templates/bindata.*
|
||||
|
||||
*.db
|
||||
*.log
|
||||
|
17
Makefile
17
Makefile
@ -120,8 +120,7 @@ WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
|
||||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
||||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
|
||||
|
||||
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
||||
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
||||
BINDATA_DEST := modules/public/bindata.dat modules/options/bindata.dat modules/templates/bindata.dat
|
||||
|
||||
GENERATED_GO_DEST := modules/charset/invisible_gen.go modules/charset/ambiguous_gen.go
|
||||
|
||||
@ -149,14 +148,8 @@ SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US
|
||||
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
|
||||
|
||||
GO_SOURCES := $(wildcard *.go)
|
||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go")
|
||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
||||
|
||||
ifeq ($(filter $(TAGS_SPLIT),bindata),bindata)
|
||||
GO_SOURCES += $(BINDATA_DEST)
|
||||
GENERATED_GO_DEST += $(BINDATA_DEST)
|
||||
endif
|
||||
|
||||
# Force installation of playwright dependencies by setting this flag
|
||||
ifdef DEPS_PLAYWRIGHT
|
||||
@ -226,7 +219,7 @@ clean-all: clean ## delete backend, frontend and integration files
|
||||
|
||||
.PHONY: clean
|
||||
clean: ## delete backend and integration files
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) \
|
||||
integrations*.test \
|
||||
e2e*.test \
|
||||
tests/integration/gitea-integration-* \
|
||||
@ -268,7 +261,7 @@ endif
|
||||
.PHONY: generate-swagger
|
||||
generate-swagger: $(SWAGGER_SPEC) ## generate the swagger spec from code comments
|
||||
|
||||
$(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA) $(SWAGGER_SPEC_INPUT)
|
||||
$(SWAGGER_SPEC): $(GO_SOURCES) $(SWAGGER_SPEC_INPUT)
|
||||
$(GO) run $(SWAGGER_PACKAGE) generate spec --exclude "$(SWAGGER_EXCLUDE)" --input "$(SWAGGER_SPEC_INPUT)" --output './$(SWAGGER_SPEC)'
|
||||
|
||||
.PHONY: swagger-check
|
||||
@ -373,7 +366,7 @@ lint-go-gitea-vet: ## lint go files with gitea-vet
|
||||
.PHONY: lint-go-gopls
|
||||
lint-go-gopls: ## lint go files with gopls
|
||||
@echo "Running gopls check..."
|
||||
@GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES_NO_BINDATA)
|
||||
@GO=$(GO) GOPLS_PACKAGE=$(GOPLS_PACKAGE) tools/lint-go-gopls.sh $(GO_SOURCES)
|
||||
|
||||
.PHONY: lint-editorconfig
|
||||
lint-editorconfig:
|
||||
|
11
build.go
11
build.go
@ -5,19 +5,10 @@
|
||||
|
||||
package main
|
||||
|
||||
// Libraries that are included to vendor utilities used during build.
|
||||
// Libraries that are included to vendor utilities used during Makefile build.
|
||||
// These libraries will not be included in a normal compilation.
|
||||
|
||||
import (
|
||||
// for embed
|
||||
_ "github.com/shurcooL/vfsgen"
|
||||
|
||||
// for cover merge
|
||||
_ "golang.org/x/tools/cover"
|
||||
|
||||
// for vet
|
||||
_ "code.gitea.io/gitea-vet"
|
||||
|
||||
// for swagger
|
||||
_ "github.com/go-swagger/go-swagger/cmd/swagger"
|
||||
)
|
||||
|
@ -6,87 +6,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/shurcooL/vfsgen"
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
)
|
||||
|
||||
func needsUpdate(dir, filename string) (bool, []byte) {
|
||||
needRegen := false
|
||||
_, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
needRegen = true
|
||||
}
|
||||
|
||||
oldHash, err := os.ReadFile(filename + ".hash")
|
||||
if err != nil {
|
||||
oldHash = []byte{}
|
||||
}
|
||||
|
||||
hasher := sha1.New()
|
||||
|
||||
err = filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := d.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = hasher.Write([]byte(d.Name()))
|
||||
_, _ = hasher.Write([]byte(info.ModTime().String()))
|
||||
_, _ = hasher.Write([]byte(strconv.FormatInt(info.Size(), 16)))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return true, oldHash
|
||||
}
|
||||
|
||||
newHash := hasher.Sum([]byte{})
|
||||
|
||||
if bytes.Compare(oldHash, newHash) != 0 {
|
||||
return true, newHash
|
||||
}
|
||||
|
||||
return needRegen, newHash
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 4 {
|
||||
log.Fatal("Insufficient number of arguments. Need: directory packageName filename")
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Println("usage: ./generate-bindata {local-directory} {bindata-filename}")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dir, packageName, filename := os.Args[1], os.Args[2], os.Args[3]
|
||||
var useGlobalModTime bool
|
||||
if len(os.Args) == 5 {
|
||||
useGlobalModTime, _ = strconv.ParseBool(os.Args[4])
|
||||
dir, filename := os.Args[1], os.Args[2]
|
||||
fmt.Printf("generating bindata for %s to %s\n", dir, filename)
|
||||
if err := assetfs.GenerateEmbedBindata(dir, filename); err != nil {
|
||||
fmt.Printf("failed: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
update, newHash := needsUpdate(dir, filename)
|
||||
|
||||
if !update {
|
||||
fmt.Printf("bindata for %s already up-to-date\n", packageName)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("generating bindata for %s\n", packageName)
|
||||
var fsTemplates http.FileSystem = http.Dir(dir)
|
||||
err := vfsgen.Generate(fsTemplates, vfsgen.Options{
|
||||
PackageName: packageName,
|
||||
BuildTags: "bindata",
|
||||
VariableName: "Assets",
|
||||
Filename: filename,
|
||||
UseGlobalModTime: useGlobalModTime,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("%v\n", err)
|
||||
}
|
||||
_ = os.WriteFile(filename+".hash", newHash, 0o666)
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ func initEmbeddedExtractor(c *cli.Command) error {
|
||||
|
||||
func runList(_ context.Context, c *cli.Command) error {
|
||||
if err := runListDo(c); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -126,7 +126,7 @@ func runList(_ context.Context, c *cli.Command) error {
|
||||
|
||||
func runView(_ context.Context, c *cli.Command) error {
|
||||
if err := runViewDo(c); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -134,7 +134,7 @@ func runView(_ context.Context, c *cli.Command) error {
|
||||
|
||||
func runExtract(_ context.Context, c *cli.Command) error {
|
||||
if err := runExtractDo(c); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -217,7 +217,7 @@ func runExtractDo(c *cli.Command) error {
|
||||
for _, a := range matchedAssetFiles {
|
||||
if err := extractAsset(destdir, a, overwrite, rename); err != nil {
|
||||
// Non-fatal error
|
||||
fmt.Fprintf(os.Stderr, "%s: %v", a.path, err)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%s: %v\n", a.path, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
43
go.mod
43
go.mod
@ -60,7 +60,6 @@ require (
|
||||
github.com/go-ldap/ldap/v3 v3.4.11
|
||||
github.com/go-redsync/redsync/v4 v4.13.0
|
||||
github.com/go-sql-driver/mysql v1.9.2
|
||||
github.com/go-swagger/go-swagger v0.31.0
|
||||
github.com/go-webauthn/webauthn v0.12.3
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
@ -105,7 +104,6 @@ require (
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
||||
github.com/sassoftware/go-rpmutils v0.4.0
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/tstranex/u2f v1.0.0
|
||||
@ -126,7 +124,6 @@ require (
|
||||
golang.org/x/sync v0.15.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/text v0.26.0
|
||||
golang.org/x/tools v0.33.0
|
||||
google.golang.org/grpc v1.72.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
@ -144,15 +141,11 @@ require (
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/DataDog/zstd v1.5.7 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||
@ -195,7 +188,6 @@ require (
|
||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
|
||||
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect
|
||||
@ -204,18 +196,6 @@ require (
|
||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.1 // indirect
|
||||
github.com/go-openapi/inflect v0.21.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/runtime v0.28.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/go-webauthn/x v0.1.20 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
@ -229,7 +209,6 @@ require (
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/go-tpm v0.9.3 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@ -237,12 +216,9 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jessevdk/go-flags v1.6.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/libdns/libdns v1.0.0-beta.1 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/markbates/going v1.0.3 // indirect
|
||||
@ -253,19 +229,15 @@ require (
|
||||
github.com/miekg/dns v1.1.65 // indirect
|
||||
github.com/minio/crc64nvme v1.0.1 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
@ -274,22 +246,11 @@ require (
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/rhysd/actionlint v1.7.7 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.9.0 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.14.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spf13/viper v1.20.1 // indirect
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
||||
github.com/unknwon/com v1.0.1 // indirect
|
||||
github.com/valyala/fastjson v1.6.4 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
@ -300,7 +261,6 @@ require (
|
||||
github.com/zeebo/assert v1.3.0 // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
go.etcd.io/bbolt v1.4.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.3 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
@ -308,6 +268,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.33.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
@ -315,8 +276,6 @@ require (
|
||||
|
||||
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||
|
||||
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
||||
|
||||
replace github.com/nektos/act => gitea.com/gitea/act v0.261.6
|
||||
|
||||
// TODO: the only difference is in `PutObject`: the fork doesn't use `NewVerifyingReader(r, sha256.New(), oid, expectedSize)`, need to figure out why
|
||||
|
75
go.sum
75
go.sum
@ -62,12 +62,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE=
|
||||
github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/Julusian/godocdown v0.0.0-20170816220326-6d19f8ff2df8/go.mod h1:INZr5t32rG59/5xeltqoCJoNY7e5x/3xoY9WSWVWg74=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
|
||||
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
@ -103,8 +97,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
|
||||
@ -274,12 +266,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
|
||||
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
@ -325,28 +313,6 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
|
||||
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU=
|
||||
github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
|
||||
github.com/go-openapi/inflect v0.21.2 h1:0gClGlGcxifcJR56zwvhaOulnNgnhc4qTAkob5ObnSM=
|
||||
github.com/go-openapi/inflect v0.21.2/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
|
||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
|
||||
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
|
||||
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
|
||||
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
|
||||
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redis/v7 v7.4.1 h1:PASvf36gyUpr2zdOUS/9Zqc80GbM+9BDyiJSJDDOrTI=
|
||||
@ -357,13 +323,9 @@ github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkv
|
||||
github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ=
|
||||
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
||||
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc=
|
||||
github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE=
|
||||
github.com/go-webauthn/webauthn v0.12.3/go.mod h1:4JRe8Z3W7HIw8NGEWn2fnUwecoDzkkeach/NnvhkqGY=
|
||||
github.com/go-webauthn/x v0.1.20 h1:brEBDqfiPtNNCdS/peu8gARtq8fIPsHz0VzpPjGvgiw=
|
||||
@ -446,8 +408,6 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||
github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
|
||||
github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
|
||||
github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
|
||||
@ -497,8 +457,6 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
|
||||
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
|
||||
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
|
||||
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
|
||||
github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw=
|
||||
github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@ -540,8 +498,6 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ=
|
||||
github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||
github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI=
|
||||
github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0/go.mod h1:JEfTc3+2DF9Z4PXhLLvXL42zexJyh8rIq3OzUj/0rAk=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
@ -577,14 +533,10 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.91 h1:tWLZnEfo3OZl5PoXQwcwTAPNNrjyWwOh6cbZitW5JQc=
|
||||
github.com/minio/minio-go/v7 v7.0.91/go.mod h1:uvMUcGrpgeSAAI6+sD3818508nUyMULw94j2Nxku/Go=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -607,8 +559,6 @@ github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWk
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E=
|
||||
@ -629,8 +579,6 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
|
||||
@ -674,7 +622,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
@ -682,8 +629,6 @@ github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
|
||||
github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY=
|
||||
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
|
||||
@ -692,10 +637,6 @@ github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLS
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
@ -707,22 +648,12 @@ github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl
|
||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||
github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc=
|
||||
@ -745,13 +676,9 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
|
||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
||||
github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
|
||||
github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
@ -809,8 +736,6 @@ gitlab.com/gitlab-org/api/client-go v0.127.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAj
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
|
||||
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
|
375
modules/assetfs/embed.go
Normal file
375
modules/assetfs/embed.go
Normal file
@ -0,0 +1,375 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package assetfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type EmbeddedFile interface {
|
||||
io.ReadSeeker
|
||||
fs.ReadDirFile
|
||||
ReadDir(n int) ([]fs.DirEntry, error)
|
||||
}
|
||||
|
||||
type EmbeddedFileInfo interface {
|
||||
fs.FileInfo
|
||||
fs.DirEntry
|
||||
GetGzipContent() ([]byte, bool)
|
||||
}
|
||||
|
||||
type decompressor interface {
|
||||
io.Reader
|
||||
Close() error
|
||||
Reset(io.Reader) error
|
||||
}
|
||||
|
||||
type embeddedFileInfo struct {
|
||||
fs *embeddedFS
|
||||
fullName string
|
||||
data []byte
|
||||
|
||||
BaseName string `json:"n"`
|
||||
OriginSize int64 `json:"s,omitempty"`
|
||||
DataBegin int64 `json:"b,omitempty"`
|
||||
DataLen int64 `json:"l,omitempty"`
|
||||
Children []*embeddedFileInfo `json:"c,omitempty"`
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) GetGzipContent() ([]byte, bool) {
|
||||
// when generating the bindata, if the compressed data equals or is larger than the original data, we store the original data
|
||||
if fi.DataLen == fi.OriginSize {
|
||||
return nil, false
|
||||
}
|
||||
return fi.data, true
|
||||
}
|
||||
|
||||
type EmbeddedFileBase struct {
|
||||
info *embeddedFileInfo
|
||||
dataReader io.ReadSeeker
|
||||
seekPos int64
|
||||
}
|
||||
|
||||
func (f *EmbeddedFileBase) ReadDir(n int) ([]fs.DirEntry, error) {
|
||||
// this method is used to satisfy the "func (f ioFile) ReadDir(...)" in httpfs
|
||||
l, err := f.info.fs.ReadDir(f.info.fullName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n < 0 || n > len(l) {
|
||||
return l, nil
|
||||
}
|
||||
return l[:n], nil
|
||||
}
|
||||
|
||||
type EmbeddedOriginFile struct {
|
||||
EmbeddedFileBase
|
||||
}
|
||||
|
||||
type EmbeddedCompressedFile struct {
|
||||
EmbeddedFileBase
|
||||
decompressor decompressor
|
||||
decompressorPos int64
|
||||
}
|
||||
|
||||
type embeddedFS struct {
|
||||
meta func() *EmbeddedMeta
|
||||
|
||||
files map[string]*embeddedFileInfo
|
||||
filesMu sync.RWMutex
|
||||
|
||||
data []byte
|
||||
}
|
||||
|
||||
type EmbeddedMeta struct {
|
||||
Root *embeddedFileInfo
|
||||
}
|
||||
|
||||
func NewEmbeddedFS(data []byte) fs.ReadDirFS {
|
||||
efs := &embeddedFS{data: data, files: make(map[string]*embeddedFileInfo)}
|
||||
efs.meta = sync.OnceValue(func() *EmbeddedMeta {
|
||||
var meta EmbeddedMeta
|
||||
p := bytes.LastIndexByte(data, '\n')
|
||||
if p < 0 {
|
||||
return &meta
|
||||
}
|
||||
if err := json.Unmarshal(data[p+1:], &meta); err != nil {
|
||||
panic("embedded file is not valid")
|
||||
}
|
||||
return &meta
|
||||
})
|
||||
return efs
|
||||
}
|
||||
|
||||
var _ fs.ReadDirFS = (*embeddedFS)(nil)
|
||||
|
||||
func (e *embeddedFS) ReadDir(name string) (l []fs.DirEntry, err error) {
|
||||
fi, err := e.getFileInfo(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !fi.IsDir() {
|
||||
return nil, fs.ErrNotExist
|
||||
}
|
||||
l = make([]fs.DirEntry, len(fi.Children))
|
||||
for i, child := range fi.Children {
|
||||
l[i], err = e.getFileInfo(name + "/" + child.BaseName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (e *embeddedFS) getFileInfo(fullName string) (*embeddedFileInfo, error) {
|
||||
// no need to do heavy "path.Clean()" because we don't want to support "foo/../bar" or absolute paths
|
||||
fullName = strings.TrimPrefix(fullName, "./")
|
||||
if fullName == "" {
|
||||
fullName = "."
|
||||
}
|
||||
|
||||
e.filesMu.RLock()
|
||||
fi := e.files[fullName]
|
||||
e.filesMu.RUnlock()
|
||||
if fi != nil {
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
fields := strings.Split(fullName, "/")
|
||||
fi = e.meta().Root
|
||||
if fullName != "." {
|
||||
found := true
|
||||
for _, field := range fields {
|
||||
for _, child := range fi.Children {
|
||||
if found = child.BaseName == field; found {
|
||||
fi = child
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, fs.ErrNotExist
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.filesMu.Lock()
|
||||
defer e.filesMu.Unlock()
|
||||
if fi != nil {
|
||||
fi.fs = e
|
||||
fi.fullName = fullName
|
||||
fi.data = e.data[fi.DataBegin : fi.DataBegin+fi.DataLen]
|
||||
e.files[fullName] = fi // do not cache nil, otherwise keeping accessing random non-existing file will cause OOM
|
||||
return fi, nil
|
||||
}
|
||||
return nil, fs.ErrNotExist
|
||||
}
|
||||
|
||||
func (e *embeddedFS) Open(name string) (fs.File, error) {
|
||||
info, err := e.getFileInfo(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base := EmbeddedFileBase{info: info}
|
||||
base.dataReader = bytes.NewReader(base.info.data)
|
||||
if info.DataLen != info.OriginSize {
|
||||
decomp, err := gzip.NewReader(base.dataReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EmbeddedCompressedFile{EmbeddedFileBase: base, decompressor: decomp}, nil
|
||||
}
|
||||
return &EmbeddedOriginFile{base}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
_ EmbeddedFileInfo = (*embeddedFileInfo)(nil)
|
||||
_ EmbeddedFile = (*EmbeddedOriginFile)(nil)
|
||||
_ EmbeddedFile = (*EmbeddedCompressedFile)(nil)
|
||||
)
|
||||
|
||||
func (f *EmbeddedOriginFile) Read(p []byte) (n int, err error) {
|
||||
return f.dataReader.Read(p)
|
||||
}
|
||||
|
||||
func (f *EmbeddedCompressedFile) Read(p []byte) (n int, err error) {
|
||||
if f.decompressorPos > f.seekPos {
|
||||
if err = f.decompressor.Reset(bytes.NewReader(f.info.data)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
f.decompressorPos = 0
|
||||
}
|
||||
if f.decompressorPos < f.seekPos {
|
||||
if _, err = io.CopyN(io.Discard, f.decompressor, f.seekPos-f.decompressorPos); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
f.decompressorPos = f.seekPos
|
||||
}
|
||||
n, err = f.decompressor.Read(p)
|
||||
f.decompressorPos += int64(n)
|
||||
f.seekPos = f.decompressorPos
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (f *EmbeddedFileBase) Seek(offset int64, whence int) (int64, error) {
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
f.seekPos = offset
|
||||
case io.SeekCurrent:
|
||||
f.seekPos += offset
|
||||
case io.SeekEnd:
|
||||
f.seekPos = f.info.OriginSize + offset
|
||||
}
|
||||
return f.seekPos, nil
|
||||
}
|
||||
|
||||
func (f *EmbeddedFileBase) Stat() (fs.FileInfo, error) {
|
||||
return f.info, nil
|
||||
}
|
||||
|
||||
func (f *EmbeddedOriginFile) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *EmbeddedCompressedFile) Close() error {
|
||||
return f.decompressor.Close()
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) Name() string {
|
||||
return fi.BaseName
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) Size() int64 {
|
||||
return fi.OriginSize
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) Mode() fs.FileMode {
|
||||
return util.Iif(fi.IsDir(), fs.ModeDir|0o555, 0o444)
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) ModTime() time.Time {
|
||||
return getExecutableModTime()
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) IsDir() bool {
|
||||
return fi.Children != nil
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) Sys() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) Type() fs.FileMode {
|
||||
return util.Iif(fi.IsDir(), fs.ModeDir, 0)
|
||||
}
|
||||
|
||||
func (fi *embeddedFileInfo) Info() (fs.FileInfo, error) {
|
||||
return fi, nil
|
||||
}
|
||||
|
||||
// getExecutableModTime returns the modification time of the executable file.
|
||||
// In bindata, we can't use the ModTime of the files because we need to make the build reproducible
|
||||
var getExecutableModTime = sync.OnceValue(func() (modTime time.Time) {
|
||||
exePath, err := os.Executable()
|
||||
if err != nil {
|
||||
return modTime
|
||||
}
|
||||
exePath, err = filepath.Abs(exePath)
|
||||
if err != nil {
|
||||
return modTime
|
||||
}
|
||||
exePath, err = filepath.EvalSymlinks(exePath)
|
||||
if err != nil {
|
||||
return modTime
|
||||
}
|
||||
st, err := os.Stat(exePath)
|
||||
if err != nil {
|
||||
return modTime
|
||||
}
|
||||
return st.ModTime()
|
||||
})
|
||||
|
||||
func GenerateEmbedBindata(fsRootPath, outputFile string) error {
|
||||
output, err := os.OpenFile(outputFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer output.Close()
|
||||
|
||||
meta := &EmbeddedMeta{}
|
||||
meta.Root = &embeddedFileInfo{}
|
||||
var outputOffset int64
|
||||
var embedFiles func(parent *embeddedFileInfo, fsPath, embedPath string) error
|
||||
embedFiles = func(parent *embeddedFileInfo, fsPath, embedPath string) error {
|
||||
dirEntries, err := os.ReadDir(fsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, dirEntry := range dirEntries {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dirEntry.IsDir() {
|
||||
child := &embeddedFileInfo{
|
||||
BaseName: dirEntry.Name(),
|
||||
Children: []*embeddedFileInfo{}, // non-nil means it's a directory
|
||||
}
|
||||
parent.Children = append(parent.Children, child)
|
||||
if err = embedFiles(child, filepath.Join(fsPath, dirEntry.Name()), path.Join(embedPath, dirEntry.Name())); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
data, err := os.ReadFile(filepath.Join(fsPath, dirEntry.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var compressed bytes.Buffer
|
||||
gz, _ := gzip.NewWriterLevel(&compressed, gzip.BestCompression)
|
||||
if _, err = gz.Write(data); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = gz.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// only use the compressed data if it is smaller than the original data
|
||||
outputBytes := util.Iif(len(compressed.Bytes()) < len(data), compressed.Bytes(), data)
|
||||
child := &embeddedFileInfo{
|
||||
BaseName: dirEntry.Name(),
|
||||
OriginSize: int64(len(data)),
|
||||
DataBegin: outputOffset,
|
||||
DataLen: int64(len(outputBytes)),
|
||||
}
|
||||
if _, err = output.Write(outputBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
outputOffset += child.DataLen
|
||||
parent.Children = append(parent.Children, child)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = embedFiles(meta.Root, fsRootPath, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
jsonBuf, err := json.Marshal(meta) // can't use json.NewEncoder here because it writes extra EOL
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = output.Write([]byte{'\n'})
|
||||
_, err = output.Write(jsonBuf)
|
||||
return err
|
||||
}
|
98
modules/assetfs/embed_test.go
Normal file
98
modules/assetfs/embed_test.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package assetfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEmbed(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
tmpDataDir := tmpDir + "/data"
|
||||
_ = os.MkdirAll(tmpDataDir+"/foo/bar", 0o755)
|
||||
_ = os.WriteFile(tmpDataDir+"/a.txt", []byte("a"), 0o644)
|
||||
_ = os.WriteFile(tmpDataDir+"/foo/bar/b.txt", bytes.Repeat([]byte("a"), 1000), 0o644)
|
||||
_ = os.WriteFile(tmpDataDir+"/foo/c.txt", []byte("c"), 0o644)
|
||||
require.NoError(t, GenerateEmbedBindata(tmpDataDir, tmpDir+"/out.dat"))
|
||||
|
||||
data, err := os.ReadFile(tmpDir + "/out.dat")
|
||||
require.NoError(t, err)
|
||||
efs := NewEmbeddedFS(data)
|
||||
|
||||
// test a non-existing file
|
||||
_, err = fs.ReadFile(efs, "not exist")
|
||||
assert.ErrorIs(t, err, fs.ErrNotExist)
|
||||
|
||||
// test a normal file (no compression)
|
||||
content, err := fs.ReadFile(efs, "a.txt")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "a", string(content))
|
||||
fi, err := fs.Stat(efs, "a.txt")
|
||||
require.NoError(t, err)
|
||||
_, ok := fi.(EmbeddedFileInfo).GetGzipContent()
|
||||
assert.False(t, ok)
|
||||
|
||||
// test a compressed file
|
||||
content, err = fs.ReadFile(efs, "foo/bar/b.txt")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, bytes.Repeat([]byte("a"), 1000), content)
|
||||
fi, err = fs.Stat(efs, "foo/bar/b.txt")
|
||||
require.NoError(t, err)
|
||||
assert.False(t, fi.Mode().IsDir())
|
||||
assert.True(t, fi.Mode().IsRegular())
|
||||
gzipContent, ok := fi.(EmbeddedFileInfo).GetGzipContent()
|
||||
assert.True(t, ok)
|
||||
assert.Greater(t, len(gzipContent), 1)
|
||||
assert.Less(t, len(gzipContent), 1000)
|
||||
|
||||
// test list root directory
|
||||
entries, err := fs.ReadDir(efs, ".")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, entries, 2)
|
||||
assert.Equal(t, "a.txt", entries[0].Name())
|
||||
assert.False(t, entries[0].IsDir())
|
||||
|
||||
// test list subdirectory
|
||||
entries, err = fs.ReadDir(efs, "foo")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, entries, 2)
|
||||
assert.Equal(t, "bar", entries[0].Name())
|
||||
assert.True(t, entries[0].IsDir())
|
||||
assert.Equal(t, "c.txt", entries[1].Name())
|
||||
assert.False(t, entries[1].IsDir())
|
||||
|
||||
// test directory mode
|
||||
fi, err = fs.Stat(efs, "foo")
|
||||
require.NoError(t, err)
|
||||
assert.True(t, fi.IsDir())
|
||||
assert.True(t, fi.Mode().IsDir())
|
||||
assert.False(t, fi.Mode().IsRegular())
|
||||
|
||||
// test httpfs
|
||||
hfs := http.FS(efs)
|
||||
hf, err := hfs.Open("foo/bar/b.txt")
|
||||
require.NoError(t, err)
|
||||
hi, err := hf.Stat()
|
||||
require.NoError(t, err)
|
||||
fiEmbedded, ok := hi.(EmbeddedFileInfo)
|
||||
require.True(t, ok)
|
||||
gzipContent, ok = fiEmbedded.GetGzipContent()
|
||||
assert.True(t, ok)
|
||||
assert.Greater(t, len(gzipContent), 1)
|
||||
assert.Less(t, len(gzipContent), 1000)
|
||||
|
||||
// test httpfs directory listing
|
||||
hf, err = hfs.Open("foo")
|
||||
require.NoError(t, err)
|
||||
dirs, err := hf.Readdir(1)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, dirs, 1)
|
||||
}
|
@ -52,8 +52,8 @@ func Local(name, base string, sub ...string) *Layer {
|
||||
}
|
||||
|
||||
// Bindata returns a new Layer with the given name, it serves files from the given bindata asset.
|
||||
func Bindata(name string, fs http.FileSystem) *Layer {
|
||||
return &Layer{name: name, fs: fs}
|
||||
func Bindata(name string, fs fs.FS) *Layer {
|
||||
return &Layer{name: name, fs: http.FS(fs)}
|
||||
}
|
||||
|
||||
// LayeredFS is a layered asset file-system. It works like http.FileSystem, but it can have multiple layers.
|
||||
|
@ -3,6 +3,28 @@
|
||||
|
||||
//go:build bindata
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas bindata.dat
|
||||
|
||||
package migration
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../modules/migration/schemas migration bindata.go
|
||||
import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
)
|
||||
|
||||
//go:embed bindata.dat
|
||||
var bindata []byte
|
||||
|
||||
var BuiltinAssets = sync.OnceValue(func() fs.FS {
|
||||
return assetfs.NewEmbeddedFS(bindata)
|
||||
})
|
||||
|
||||
func openSchema(filename string) (io.ReadCloser, error) {
|
||||
return BuiltinAssets().Open(path.Base(filename))
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build bindata
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"io"
|
||||
"path"
|
||||
)
|
||||
|
||||
func openSchema(filename string) (io.ReadCloser, error) {
|
||||
return Assets.Open(path.Base(filename))
|
||||
}
|
@ -3,6 +3,21 @@
|
||||
|
||||
//go:build bindata
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../options bindata.dat
|
||||
|
||||
package options
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../options options bindata.go
|
||||
import (
|
||||
"sync"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
)
|
||||
|
||||
//go:embed bindata.dat
|
||||
var bindata []byte
|
||||
|
||||
var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer {
|
||||
return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata))
|
||||
})
|
||||
|
@ -1,14 +0,0 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build bindata
|
||||
|
||||
package options
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
)
|
||||
|
||||
func BuiltinAssets() *assetfs.Layer {
|
||||
return assetfs.Bindata("builtin(bindata)", Assets)
|
||||
}
|
@ -89,19 +89,16 @@ func handleRequest(w http.ResponseWriter, req *http.Request, fs http.FileSystem,
|
||||
servePublicAsset(w, req, fi, fi.ModTime(), f)
|
||||
}
|
||||
|
||||
type GzipBytesProvider interface {
|
||||
GzipBytes() []byte
|
||||
}
|
||||
|
||||
// servePublicAsset serve http content
|
||||
func servePublicAsset(w http.ResponseWriter, req *http.Request, fi os.FileInfo, modtime time.Time, content io.ReadSeeker) {
|
||||
setWellKnownContentType(w, fi.Name())
|
||||
httpcache.SetCacheControlInHeader(w.Header(), httpcache.CacheControlForPublicStatic())
|
||||
encodings := parseAcceptEncoding(req.Header.Get("Accept-Encoding"))
|
||||
if encodings.Contains("gzip") {
|
||||
// try to provide gzip content directly from bindata (provided by vfsgen۰CompressedFileInfo)
|
||||
if compressed, ok := fi.(GzipBytesProvider); ok {
|
||||
rdGzip := bytes.NewReader(compressed.GzipBytes())
|
||||
fiEmbedded, _ := fi.(assetfs.EmbeddedFileInfo)
|
||||
if encodings.Contains("gzip") && fiEmbedded != nil {
|
||||
// try to provide gzip content directly from bindata
|
||||
if gzipBytes, ok := fiEmbedded.GetGzipContent(); ok {
|
||||
rdGzip := bytes.NewReader(gzipBytes)
|
||||
// all gzipped static files (from bindata) are managed by Gitea, so we can make sure every file has the correct ext name
|
||||
// then we can get the correct Content-Type, we do not need to do http.DetectContentType on the decompressed data
|
||||
if w.Header().Get("Content-Type") == "" {
|
||||
|
@ -5,4 +5,19 @@
|
||||
|
||||
package public
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../public public bindata.go true
|
||||
//go:generate go run ../../build/generate-bindata.go ../../public bindata.dat
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
)
|
||||
|
||||
//go:embed bindata.dat
|
||||
var bindata []byte
|
||||
|
||||
var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer {
|
||||
return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata))
|
||||
})
|
||||
|
@ -1,24 +0,0 @@
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build bindata
|
||||
|
||||
package public
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
)
|
||||
|
||||
var _ GzipBytesProvider = (*vfsgen۰CompressedFileInfo)(nil)
|
||||
|
||||
// GlobalModTime provide a global mod time for embedded asset files
|
||||
func GlobalModTime(filename string) time.Time {
|
||||
return timeutil.GetExecutableModTime()
|
||||
}
|
||||
|
||||
func BuiltinAssets() *assetfs.Layer {
|
||||
return assetfs.Bindata("builtin(bindata)", Assets)
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build bindata
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
)
|
||||
|
||||
// GlobalModTime provide a global mod time for embedded asset files
|
||||
func GlobalModTime(filename string) time.Time {
|
||||
return timeutil.GetExecutableModTime()
|
||||
}
|
||||
|
||||
func BuiltinAssets() *assetfs.Layer {
|
||||
return assetfs.Bindata("builtin(bindata)", Assets)
|
||||
}
|
@ -3,6 +3,21 @@
|
||||
|
||||
//go:build bindata
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../templates bindata.dat
|
||||
|
||||
package templates
|
||||
|
||||
//go:generate go run ../../build/generate-bindata.go ../../templates templates bindata.go true
|
||||
import (
|
||||
"sync"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
)
|
||||
|
||||
//go:embed bindata.dat
|
||||
var bindata []byte
|
||||
|
||||
var BuiltinAssets = sync.OnceValue(func() *assetfs.Layer {
|
||||
return assetfs.Bindata("builtin(bindata)", assetfs.NewEmbeddedFS(bindata))
|
||||
})
|
||||
|
@ -1,50 +0,0 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package timeutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
||||
var (
|
||||
executablModTime = time.Now()
|
||||
executablModTimeOnce sync.Once
|
||||
)
|
||||
|
||||
// GetExecutableModTime get executable file modified time of current process.
|
||||
func GetExecutableModTime() time.Time {
|
||||
executablModTimeOnce.Do(func() {
|
||||
exePath, err := os.Executable()
|
||||
if err != nil {
|
||||
log.Error("os.Executable: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
exePath, err = filepath.Abs(exePath)
|
||||
if err != nil {
|
||||
log.Error("filepath.Abs: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
exePath, err = filepath.EvalSymlinks(exePath)
|
||||
if err != nil {
|
||||
log.Error("filepath.EvalSymlinks: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
st, err := os.Stat(exePath)
|
||||
if err != nil {
|
||||
log.Error("os.Stat: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
executablModTime = st.ModTime()
|
||||
})
|
||||
return executablModTime
|
||||
}
|
@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
func TestWriterReader(t *testing.T) {
|
||||
testData := prepareTestData(t, 20_000_000)
|
||||
testData := prepareTestData(t, 1_000_000)
|
||||
|
||||
result := bytes.NewBuffer(nil)
|
||||
|
||||
@ -64,7 +64,7 @@ func TestWriterReader(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSeekableWriterReader(t *testing.T) {
|
||||
testData := prepareTestData(t, 20_000_000)
|
||||
testData := prepareTestData(t, 2_000_000)
|
||||
|
||||
result := bytes.NewBuffer(nil)
|
||||
|
||||
@ -109,7 +109,7 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
reader, err := NewSeekableReader(assertReader)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = reader.Seek(10_000_000, io.SeekStart)
|
||||
_, err = reader.Seek(1_000_000, io.SeekStart)
|
||||
require.NoError(t, err)
|
||||
|
||||
data := make([]byte, 1000)
|
||||
@ -117,7 +117,7 @@ func TestSeekableWriterReader(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, reader.Close())
|
||||
|
||||
assert.Equal(t, testData[10_000_000:10_000_000+1000], data)
|
||||
assert.Equal(t, testData[1_000_000:1_000_000+1000], data)
|
||||
|
||||
// Should seek 3 times,
|
||||
// the first two times are for getting the index,
|
||||
|
Loading…
x
Reference in New Issue
Block a user